aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTed Kremenek <kremenek@apple.com>2009-11-17 22:58:30 +0000
committerTed Kremenek <kremenek@apple.com>2009-11-17 22:58:30 +0000
commitc32b1d82c1f6d0f0d6c615beb3b6bdfbfbea7098 (patch)
treeb7363884ffd3825b3d6d67f8deb4b4cc16378e9d
parent269f8bc10a33e29e2951df7720cad0abb45c74cb (diff)
Do not register ObjCInterfaceDecls implicitly created by @class in the
current DeclContext. These "imaginary" declarations pose issues for clients searching DeclContext for actual declarations. Instead, register them for name lookup, and add the ObjCInterfaceDecl later to the DeclContext when we hit an actual @interface declaration. This also fixes a bug where the invariant that the Decls in a DeclContext are sorted in order of their appearance is no longer violated. What could happen is that an @class causes an ObjCInterfaceDecl to get added first to the DeclContext, then the ObjCClassDecl itself is added, and then later the SourceLocation of the ObjCInterfaceDecl is updated with the correct location (which is later in the file). This breaks an assumed invariant in ResolveLocation.cpp (and possibly other clients). git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@89160 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/AST/DeclBase.cpp7
-rw-r--r--lib/Sema/SemaDeclObjC.cpp15
2 files changed, 21 insertions, 1 deletions
diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp
index da3b19df5b..c3c506e5ba 100644
--- a/lib/AST/DeclBase.cpp
+++ b/lib/AST/DeclBase.cpp
@@ -673,6 +673,13 @@ void DeclContext::buildLookup(DeclContext *DCtx) {
if (D->getDeclContext() == DCtx)
makeDeclVisibleInContextImpl(ND);
+ // Insert any forward-declared Objective-C interfaces into the lookup
+ // data structure.
+ if (ObjCClassDecl *Class = dyn_cast<ObjCClassDecl>(*D))
+ for (ObjCClassDecl::iterator I = Class->begin(), IEnd = Class->end();
+ I != IEnd; ++I)
+ makeDeclVisibleInContextImpl(*I);
+
// If this declaration is itself a transparent declaration context,
// add its members (recursively).
if (DeclContext *InnerCtx = dyn_cast<DeclContext>(*D))
diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp
index a5fdb8725c..54b0c3afab 100644
--- a/lib/Sema/SemaDeclObjC.cpp
+++ b/lib/Sema/SemaDeclObjC.cpp
@@ -112,6 +112,12 @@ ActOnStartClassInterface(SourceLocation AtInterfaceLoc,
IDecl->setLocation(AtInterfaceLoc);
IDecl->setForwardDecl(false);
IDecl->setClassLoc(ClassLoc);
+
+ // Since this ObjCInterfaceDecl was created by a forward declaration,
+ // we now add it to the DeclContext since it wasn't added before
+ // (see ActOnForwardClassDeclaration).
+ CurContext->addDecl(IDecl);
+
if (AttrList)
ProcessDeclAttributeList(TUScope, IDecl, AttrList);
}
@@ -1194,7 +1200,14 @@ Sema::ActOnForwardClassDeclaration(SourceLocation AtClassLoc,
// FIXME: need to get the 'real'
// identifier loc from the parser.
AtClassLoc, true);
- PushOnScopeChains(IDecl, TUScope);
+
+ // Push the ObjCInterfaceDecl on the scope chain but do *not* add it to
+ // the current DeclContext. This prevents clients that walk DeclContext
+ // from seeing the imaginary ObjCInterfaceDecl until it is actually
+ // declared later (if at all). We also take care to explicitly make
+ // sure this declaration is visible for name lookup.
+ PushOnScopeChains(IDecl, TUScope, false);
+ CurContext->makeDeclVisibleInContext(IDecl, true);
}
Interfaces.push_back(IDecl);