diff options
author | Argyrios Kyrtzidis <akyrtzi@gmail.com> | 2013-06-18 21:26:33 +0000 |
---|---|---|
committer | Argyrios Kyrtzidis <akyrtzi@gmail.com> | 2013-06-18 21:26:33 +0000 |
commit | dd7106375c2c7de682bf2997d2ef7bb55113219f (patch) | |
tree | 6f0e0d1fceb071c8d76abf57a693734f45be2d5c /clang/lib/Sema/SemaDeclObjC.cpp | |
parent | a721731fdd0ab07d66e1f143181c6d8de66b3188 (diff) | |
download | bcm5719-llvm-dd7106375c2c7de682bf2997d2ef7bb55113219f.tar.gz bcm5719-llvm-dd7106375c2c7de682bf2997d2ef7bb55113219f.zip |
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
Diffstat (limited to 'clang/lib/Sema/SemaDeclObjC.cpp')
-rw-r--r-- | clang/lib/Sema/SemaDeclObjC.cpp | 37 |
1 files changed, 36 insertions, 1 deletions
diff --git a/clang/lib/Sema/SemaDeclObjC.cpp b/clang/lib/Sema/SemaDeclObjC.cpp index 9f10b7bb7ea..526e479af08 100644 --- a/clang/lib/Sema/SemaDeclObjC.cpp +++ b/clang/lib/Sema/SemaDeclObjC.cpp @@ -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); |