]> granicus.if.org Git - clang/commitdiff
Don't crash when a duplicate interface/protocol is inside an extern "C" context.
authorArgyrios Kyrtzidis <akyrtzi@gmail.com>
Sun, 13 Nov 2011 22:08:30 +0000 (22:08 +0000)
committerArgyrios Kyrtzidis <akyrtzi@gmail.com>
Sun, 13 Nov 2011 22:08:30 +0000 (22:08 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@144508 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaDeclObjC.cpp
test/SemaObjC/alias-test-2.m
test/SemaObjCXX/objc-extern-c.mm [new file with mode: 0644]

index 592d7c231e4de0c20222e119f6b70a8d40e32e68..fe9a7841cfd07adf76f7fc657e55704893e19cc1 100644 (file)
@@ -373,9 +373,15 @@ ActOnStartClassInterface(SourceLocation AtInterfaceLoc,
       Diag(AtInterfaceLoc, diag::err_duplicate_class_def)<<IDecl->getDeclName();
       Diag(IDecl->getLocation(), diag::note_previous_definition);
 
-      // Return the previous class interface.
-      // FIXME: don't leak the objects passed in!
-      return ActOnObjCContainerStartDefinition(IDecl);
+      // Create a new one; the other may be in a different DeclContex, (e.g.
+      // this one may be in a LinkageSpecDecl while the other is not) which
+      // will break invariants.
+      IDecl = ObjCInterfaceDecl::Create(Context, CurContext, AtInterfaceLoc,
+                                        ClassName, ClassLoc);
+      if (AttrList)
+        ProcessDeclAttributeList(TUScope, IDecl, AttrList);
+      PushOnScopeChains(IDecl, TUScope);
+
     } else {
       IDecl->setLocation(ClassLoc);
       IDecl->setAtStartLoc(AtInterfaceLoc);
@@ -575,23 +581,30 @@ Sema::ActOnStartProtocolInterface(SourceLocation AtProtoInterfaceLoc,
     if (!PDecl->isForwardDecl()) {
       Diag(ProtocolLoc, diag::warn_duplicate_protocol_def) << ProtocolName;
       Diag(PDecl->getLocation(), diag::note_previous_definition);
-      // Just return the protocol we already had.
-      // FIXME: don't leak the objects passed in!
-      return ActOnObjCContainerStartDefinition(PDecl);
+
+      // Create a new one; the other may be in a different DeclContex, (e.g.
+      // this one may be in a LinkageSpecDecl while the other is not) which
+      // will break invariants.
+      // We will not add it to scope chains to ignore it as the warning says.
+      PDecl = ObjCProtocolDecl::Create(Context, CurContext, ProtocolName,
+                                       ProtocolLoc, AtProtoInterfaceLoc,
+                                       /*isForwardDecl=*/false);
+
+    } else {
+      ObjCList<ObjCProtocolDecl> PList;
+      PList.set((ObjCProtocolDecl *const*)ProtoRefs, NumProtoRefs, Context);
+      err = CheckForwardProtocolDeclarationForCircularDependency(
+              ProtocolName, ProtocolLoc, PDecl->getLocation(), PList);
+  
+      // Make sure the cached decl gets a valid start location.
+      PDecl->setAtStartLoc(AtProtoInterfaceLoc);
+      PDecl->setLocation(ProtocolLoc);
+      // Since this ObjCProtocolDecl was created by a forward declaration,
+      // we now add it to the DeclContext since it wasn't added before
+      PDecl->setLexicalDeclContext(CurContext);
+      CurContext->addDecl(PDecl);
+      PDecl->completedForwardDecl();
     }
-    ObjCList<ObjCProtocolDecl> PList;
-    PList.set((ObjCProtocolDecl *const*)ProtoRefs, NumProtoRefs, Context);
-    err = CheckForwardProtocolDeclarationForCircularDependency(
-            ProtocolName, ProtocolLoc, PDecl->getLocation(), PList);
-
-    // Make sure the cached decl gets a valid start location.
-    PDecl->setAtStartLoc(AtProtoInterfaceLoc);
-    PDecl->setLocation(ProtocolLoc);
-    // Since this ObjCProtocolDecl was created by a forward declaration,
-    // we now add it to the DeclContext since it wasn't added before
-    PDecl->setLexicalDeclContext(CurContext);
-    CurContext->addDecl(PDecl);
-    PDecl->completedForwardDecl();
   } else {
     PDecl = ObjCProtocolDecl::Create(Context, CurContext, ProtocolName,
                                      ProtocolLoc, AtProtoInterfaceLoc,
index 1f12b76055e883c41f7aa9b8e46bb0bb06ffd55b..0c186885a3e085e353c9ac8f17d7ff17cd32a7d9 100644 (file)
@@ -9,9 +9,9 @@
 
 @compatibility_alias  AliasForSuper Super;
 
-@interface MyAlias : AliasForSuper // expected-error {{duplicate interface definition for class 'MyWpModule'}}
+@implementation MyAlias : AliasForSuper // expected-error {{conflicting super class name 'Super'}}
 @end
 
-@implementation MyAlias : AliasForSuper // expected-error {{conflicting super class name 'Super'}}
+@interface MyAlias : AliasForSuper // expected-error {{duplicate interface definition for class 'MyWpModule'}}
 @end
 
diff --git a/test/SemaObjCXX/objc-extern-c.mm b/test/SemaObjCXX/objc-extern-c.mm
new file mode 100644 (file)
index 0000000..6bd3761
--- /dev/null
@@ -0,0 +1,30 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+@protocol P // expected-note {{previous}}
+-(void)meth1;
+@end
+
+@interface I // expected-note {{previous}}
+@end
+
+@interface I2
+@end
+@interface I2(C) // expected-note {{previous}}
+@end
+
+extern "C" {
+@protocol P // expected-warning {{duplicate protocol definition of 'P' is ignored}}
+-(void)meth2;
+@end
+
+@interface I // expected-error {{duplicate}}
+@end
+
+@interface I2(C) // expected-warning {{duplicate}}
+@end
+}
+
+void test(id<P> p) {
+  [p meth1];
+  [p meth2]; // expected-warning {{not found}}
+}