diff --git a/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h index fac0668efd..119db2ee21 100644 --- a/include/clang/AST/DeclBase.h +++ b/include/clang/AST/DeclBase.h @@ -425,6 +425,12 @@ public: /// information needed to perform name lookup into this context. DeclContext *getPrimaryContext(ASTContext &Context); + /// getLookupContext - Retrieve the innermost non-transparent + /// context of this context, which corresponds to the innermost + /// location from which name lookup can find the entities in this + /// context. + DeclContext *getLookupContext(); + /// getNextContext - If this is a DeclContext that may have other /// DeclContexts that are semantically connected but syntactically /// different, such as C++ namespaces, this routine retrieves the diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp index a21d5db11a..faaa1045de 100644 --- a/lib/AST/DeclBase.cpp +++ b/lib/AST/DeclBase.cpp @@ -567,6 +567,13 @@ DeclContext::lookup(ASTContext &Context, DeclarationName Name) const { return const_cast(this)->lookup(Context, Name); } +DeclContext *DeclContext::getLookupContext() { + DeclContext *Ctx = this; + while (Ctx->isTransparentContext()) + Ctx = Ctx->getParent(); + return Ctx; +} + void DeclContext::insert(ASTContext &Context, ScopedDecl *D) { DeclContext *PrimaryContext = getPrimaryContext(Context); if (PrimaryContext != this) { diff --git a/lib/Sema/IdentifierResolver.cpp b/lib/Sema/IdentifierResolver.cpp index 18e78a0d17..08c9bdeb31 100644 --- a/lib/Sema/IdentifierResolver.cpp +++ b/lib/Sema/IdentifierResolver.cpp @@ -60,8 +60,7 @@ DeclContext *IdentifierResolver::LookupContext::getContext(Decl *D) { else return TUCtx(); - while (Ctx->isTransparentContext()) - Ctx = Ctx->getParent(); + Ctx = Ctx->getLookupContext(); if (isa(Ctx)) return TUCtx(); @@ -132,8 +131,7 @@ IdentifierResolver::~IdentifierResolver() { /// true if 'D' belongs to the given declaration context. bool IdentifierResolver::isDeclInScope(Decl *D, DeclContext *Ctx, ASTContext &Context, Scope *S) const { - while (Ctx->isTransparentContext()) - Ctx = Ctx->getParent(); + Ctx = Ctx->getLookupContext(); if (Ctx->isFunctionOrMethod()) { // Ignore the scopes associated within transparent declaration contexts. diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 0e14150021..79e443d0b4 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -156,9 +156,7 @@ void Sema::PushOnScopeChains(NamedDecl *D, Scope *S) { // We are pushing the name of a function, which might be an // overloaded name. FunctionDecl *FD = cast(D); - DeclContext *DC = FD->getDeclContext(); - while (DC->isTransparentContext()) - DC = DC->getParent(); + DeclContext *DC = FD->getDeclContext()->getLookupContext(); IdentifierResolver::iterator Redecl = std::find_if(IdResolver.begin(FD->getDeclName(), DC, false/*LookInParentCtx*/), diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp index cf1a5259f2..c32a806b7d 100644 --- a/lib/Sema/SemaDeclObjC.cpp +++ b/lib/Sema/SemaDeclObjC.cpp @@ -1647,7 +1647,7 @@ Sema::DeclTy *Sema::ActOnPropertyImplDecl(SourceLocation AtLoc, } bool Sema::CheckObjCDeclScope(Decl *D) { - if (isa(CurContext)) + if (isa(CurContext->getLookupContext())) return false; Diag(D->getLocation(), diag::err_objc_decls_may_only_appear_in_global_scope); diff --git a/test/SemaObjCXX/linkage-spec.mm b/test/SemaObjCXX/linkage-spec.mm new file mode 100644 index 0000000000..c8221d470e --- /dev/null +++ b/test/SemaObjCXX/linkage-spec.mm @@ -0,0 +1,4 @@ +// RUN: clang -fsyntax-only -verify %s +extern "C" { +@class Protocol; +}