forked from OSchip/llvm-project
When declaring an ObjC interface decl with a @compatibility_alias alias name, change the class name to the "real" one.
If we have something like @class NewImage; @compatibility_alias OldImage NewImage; @class OldImage; the lookup for 'OldImage' will return the 'NewImage' decl ("@class NewImage"). In such a case, when creating the decl for "@class OldImage" use the real declaration name ("NewImage"), instead of the alias one ("OldImage"), otherwise we will break IdentifierResolver and redecls-chain invariants. Fixes crash of rdar://14112291. llvm-svn: 184238
This commit is contained in:
parent
a721731fdd
commit
dd7106375c
|
@ -459,6 +459,23 @@ ActOnStartClassInterface(SourceLocation AtInterfaceLoc,
|
|||
|
||||
// Create a declaration to describe this @interface.
|
||||
ObjCInterfaceDecl* PrevIDecl = dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl);
|
||||
|
||||
if (PrevIDecl && PrevIDecl->getIdentifier() != ClassName) {
|
||||
// A previous decl with a different name is because of
|
||||
// @compatibility_alias, for example:
|
||||
// \code
|
||||
// @class NewImage;
|
||||
// @compatibility_alias OldImage NewImage;
|
||||
// \endcode
|
||||
// A lookup for 'OldImage' will return the 'NewImage' decl.
|
||||
//
|
||||
// In such a case use the real declaration name, instead of the alias one,
|
||||
// otherwise we will break IdentifierResolver and redecls-chain invariants.
|
||||
// FIXME: If necessary, add a bit to indicate that this ObjCInterfaceDecl
|
||||
// has been aliased.
|
||||
ClassName = PrevIDecl->getIdentifier();
|
||||
}
|
||||
|
||||
ObjCInterfaceDecl *IDecl
|
||||
= ObjCInterfaceDecl::Create(Context, CurContext, AtInterfaceLoc, ClassName,
|
||||
PrevIDecl, ClassLoc);
|
||||
|
@ -1938,9 +1955,27 @@ Sema::ActOnForwardClassDeclaration(SourceLocation AtClassLoc,
|
|||
// Create a declaration to describe this forward declaration.
|
||||
ObjCInterfaceDecl *PrevIDecl
|
||||
= dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl);
|
||||
|
||||
IdentifierInfo *ClassName = IdentList[i];
|
||||
if (PrevIDecl && PrevIDecl->getIdentifier() != ClassName) {
|
||||
// A previous decl with a different name is because of
|
||||
// @compatibility_alias, for example:
|
||||
// \code
|
||||
// @class NewImage;
|
||||
// @compatibility_alias OldImage NewImage;
|
||||
// \endcode
|
||||
// A lookup for 'OldImage' will return the 'NewImage' decl.
|
||||
//
|
||||
// In such a case use the real declaration name, instead of the alias one,
|
||||
// otherwise we will break IdentifierResolver and redecls-chain invariants.
|
||||
// FIXME: If necessary, add a bit to indicate that this ObjCInterfaceDecl
|
||||
// has been aliased.
|
||||
ClassName = PrevIDecl->getIdentifier();
|
||||
}
|
||||
|
||||
ObjCInterfaceDecl *IDecl
|
||||
= ObjCInterfaceDecl::Create(Context, CurContext, AtClassLoc,
|
||||
IdentList[i], PrevIDecl, IdentLocs[i]);
|
||||
ClassName, PrevIDecl, IdentLocs[i]);
|
||||
IDecl->setAtEndRange(IdentLocs[i]);
|
||||
|
||||
PushOnScopeChains(IDecl, TUScope);
|
||||
|
|
|
@ -5,3 +5,14 @@
|
|||
- (void)instMethod;
|
||||
@end
|
||||
|
||||
@class NewID1;
|
||||
@compatibility_alias OldID1 NewID1;
|
||||
@class OldID1;
|
||||
@class OldID1;
|
||||
|
||||
@class NewID2;
|
||||
@compatibility_alias OldID2 NewID2;
|
||||
@class OldID2;
|
||||
@interface OldID2
|
||||
-(void)meth;
|
||||
@end
|
||||
|
|
|
@ -15,3 +15,18 @@ void func() {
|
|||
xx = [TestPCH alloc];
|
||||
[xx instMethod];
|
||||
}
|
||||
|
||||
// rdar://14112291
|
||||
@class NewID1;
|
||||
void foo1(NewID1 *p);
|
||||
void bar1(OldID1 *p) {
|
||||
foo1(p);
|
||||
}
|
||||
@class NewID2;
|
||||
void foo2(NewID2 *p) {
|
||||
[p meth];
|
||||
}
|
||||
void bar2(OldID2 *p) {
|
||||
foo2(p);
|
||||
[p meth];
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue