]> granicus.if.org Git - clang/commitdiff
Fix <rdar://problem/6144382> [sema] gcc inconsistency w.r.t. forward protocol declara...
authorSteve Naroff <snaroff@apple.com>
Thu, 5 Mar 2009 15:22:01 +0000 (15:22 +0000)
committerSteve Naroff <snaroff@apple.com>
Thu, 5 Mar 2009 15:22:01 +0000 (15:22 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@66161 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DiagnosticSemaKinds.def
lib/Sema/Sema.h
lib/Sema/SemaDeclObjC.cpp
test/SemaObjC/protocol-forward-circular.m [new file with mode: 0644]

index 6f94d8e2ec3bde36dc05954c1bc8b9e1a6f224d7..2d751ad8afbe3c62268957f0124622ace37e2ce4 100644 (file)
@@ -135,6 +135,8 @@ DIAG(warn_undef_interface, WARNING,
      "cannot find interface declaration for %0")
 DIAG(err_duplicate_protocol_def, ERROR,
      "duplicate protocol definition of %0")
+DIAG(err_protocol_has_circular_dependency, ERROR,
+     "protocol has circular dependency")
 DIAG(err_undeclared_protocol, ERROR,
      "cannot find protocol declaration for %0")
 DIAG(warn_undef_protocolref, WARNING,
index de9b4cd013ab8ab53e9fd7d9751895f52a3af7fa..d7d80638d19228d4102d99aef809474a04a35022 100644 (file)
@@ -25,6 +25,7 @@
 #include "llvm/ADT/DenseSet.h"
 #include "llvm/ADT/SmallPtrSet.h"
 #include "llvm/ADT/OwningPtr.h"
+#include "clang/AST/DeclObjC.h"
 #include <string>
 #include <vector>
 
@@ -1678,6 +1679,11 @@ public:
                     SourceLocation AtCompatibilityAliasLoc,
                     IdentifierInfo *AliasName,  SourceLocation AliasLocation,
                     IdentifierInfo *ClassName, SourceLocation ClassLocation);
+
+  void CheckForwardProtocolDeclarationForCircularDependency(
+    IdentifierInfo *PName,
+    SourceLocation &PLoc, SourceLocation PrevLoc,
+    const ObjCList<ObjCProtocolDecl> &PList);
                     
   virtual DeclTy *ActOnStartProtocolInterface(
                     SourceLocation AtProtoInterfaceLoc,
index 55b0d16e8c48590ea2dda75493d80935ef363d05..d90f2adc77abf8c7b3afdb7ef9eee3f150e2a9b6 100644 (file)
@@ -215,6 +215,25 @@ Sema::DeclTy *Sema::ActOnCompatiblityAlias(SourceLocation AtLoc,
   return AliasDecl;
 }
 
+void Sema::CheckForwardProtocolDeclarationForCircularDependency(
+  IdentifierInfo *PName,
+  SourceLocation &Ploc, SourceLocation PrevLoc,
+  const ObjCList<ObjCProtocolDecl> &PList) 
+{
+  for (ObjCList<ObjCProtocolDecl>::iterator I = PList.begin(),
+       E = PList.end(); I != E; ++I) {
+       
+    if (ObjCProtocolDecl *PDecl = ObjCProtocols[(*I)->getIdentifier()]) {
+      if (PDecl->getIdentifier() == PName) {
+        Diag(Ploc, diag::err_protocol_has_circular_dependency);
+        Diag(PrevLoc, diag::note_previous_definition);
+      }
+      CheckForwardProtocolDeclarationForCircularDependency(PName, Ploc, 
+        PDecl->getLocation(), PDecl->getReferencedProtocols());
+    }
+  }
+}
+
 Sema::DeclTy *
 Sema::ActOnStartProtocolInterface(SourceLocation AtProtoInterfaceLoc,
                                   IdentifierInfo *ProtocolName,
@@ -236,6 +255,12 @@ Sema::ActOnStartProtocolInterface(SourceLocation AtProtoInterfaceLoc,
       // FIXME: don't leak the objects passed in!
       return PDecl;
     }
+    ObjCList<ObjCProtocolDecl> PList;
+    PList.set((ObjCProtocolDecl *const*)ProtoRefs, NumProtoRefs, Context); 
+    CheckForwardProtocolDeclarationForCircularDependency(
+      ProtocolName, ProtocolLoc, PDecl->getLocation(), PList);
+    PList.Destroy(Context);
+    
     // Make sure the cached decl gets a valid start location.
     PDecl->setLocation(AtProtoInterfaceLoc);
     PDecl->setForwardDecl(false);
diff --git a/test/SemaObjC/protocol-forward-circular.m b/test/SemaObjC/protocol-forward-circular.m
new file mode 100644 (file)
index 0000000..836d5b2
--- /dev/null
@@ -0,0 +1,10 @@
+// RUN: clang -fsyntax-only -verify %s
+
+@protocol B;
+@protocol C < B > // expected-warning{{cannot find protocol definition for 'B'}} // expected-note{{previous definition is here}}
+@end
+@protocol A < C > 
+@end
+@protocol B < A > // expected-error{{protocol has circular dependency}}
+@end
+