From: Argyrios Kyrtzidis Date: Sun, 13 Nov 2011 22:08:30 +0000 (+0000) Subject: Don't crash when a duplicate interface/protocol is inside an extern "C" context. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=4fc04da71ed46d63dc991dbea4fd52341e56c0a1;p=clang Don't crash when a duplicate interface/protocol is inside an extern "C" context. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@144508 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp index 592d7c231e..fe9a7841cf 100644 --- a/lib/Sema/SemaDeclObjC.cpp +++ b/lib/Sema/SemaDeclObjC.cpp @@ -373,9 +373,15 @@ ActOnStartClassInterface(SourceLocation AtInterfaceLoc, Diag(AtInterfaceLoc, diag::err_duplicate_class_def)<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 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 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, diff --git a/test/SemaObjC/alias-test-2.m b/test/SemaObjC/alias-test-2.m index 1f12b76055..0c186885a3 100644 --- a/test/SemaObjC/alias-test-2.m +++ b/test/SemaObjC/alias-test-2.m @@ -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 index 0000000000..6bd37610ae --- /dev/null +++ b/test/SemaObjCXX/objc-extern-c.mm @@ -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 meth1]; + [p meth2]; // expected-warning {{not found}} +}