aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/AST/DeclBase.h13
-rw-r--r--lib/AST/DeclBase.cpp150
-rw-r--r--lib/Sema/SemaDecl.cpp4
-rw-r--r--lib/Sema/SemaDeclCXX.cpp15
-rw-r--r--lib/Sema/SemaDeclObjC.cpp4
-rw-r--r--lib/Sema/SemaLookup.cpp3
-rw-r--r--lib/Sema/SemaObjCProperty.cpp2
-rw-r--r--lib/Sema/SemaTemplate.cpp2
-rw-r--r--lib/Sema/SemaTemplateInstantiateDecl.cpp4
-rw-r--r--test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p11.cpp10
-rw-r--r--test/Modules/namespaces.cpp4
-rw-r--r--test/SemaCXX/PR10447.cpp22
12 files changed, 109 insertions, 124 deletions
diff --git a/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h
index 351f77cef1..28dc1b4fe9 100644
--- a/include/clang/AST/DeclBase.h
+++ b/include/clang/AST/DeclBase.h
@@ -1432,11 +1432,7 @@ public:
/// visible from this context, as determined by
/// NamedDecl::declarationReplaces, the previous declaration will be
/// replaced with D.
- ///
- /// @param Recoverable true if it's okay to not add this decl to
- /// the lookup tables because it can be easily recovered by walking
- /// the declaration chains.
- void makeDeclVisibleInContext(NamedDecl *D, bool Recoverable = true);
+ void makeDeclVisibleInContext(NamedDecl *D);
/// udir_iterator - Iterates through the using-directives stored
/// within this context.
@@ -1509,15 +1505,12 @@ private:
///
/// Analogous to makeDeclVisibleInContext, but for the exclusive
/// use of addDeclInternal().
- void makeDeclVisibleInContextInternal(NamedDecl *D,
- bool Recoverable = true);
+ void makeDeclVisibleInContextInternal(NamedDecl *D);
friend class DependentDiagnostic;
StoredDeclsMap *CreateStoredDeclsMap(ASTContext &C) const;
- void buildLookup(DeclContext *DCtx);
- void makeDeclVisibleInContextWithFlags(NamedDecl *D, bool Internal,
- bool Recoverable);
+ void makeDeclVisibleInContextWithFlags(NamedDecl *D, bool Internal);
void makeDeclVisibleInContextImpl(NamedDecl *D, bool Internal);
};
diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp
index baba97d815..9171d2792c 100644
--- a/lib/AST/DeclBase.cpp
+++ b/lib/AST/DeclBase.cpp
@@ -1082,64 +1082,28 @@ void DeclContext::addDeclInternal(Decl *D) {
ND->getDeclContext()->makeDeclVisibleInContextInternal(ND);
}
-/// buildLookup - Build the lookup data structure with all of the
-/// declarations in DCtx (and any other contexts linked to it or
-/// transparent contexts nested within it).
-void DeclContext::buildLookup(DeclContext *DCtx) {
- llvm::SmallVector<DeclContext *, 2> Contexts;
- DCtx->collectAllContexts(Contexts);
- for (unsigned I = 0, N = Contexts.size(); I != N; ++I) {
- for (decl_iterator D = Contexts[I]->decls_begin(),
- DEnd = Contexts[I]->decls_end();
- D != DEnd; ++D) {
- // Insert this declaration into the lookup structure, but only
- // if it's semantically in its decl context. During non-lazy
- // lookup building, this is implicitly enforced by addDecl.
- if (NamedDecl *ND = dyn_cast<NamedDecl>(*D))
- if (D->getDeclContext() == Contexts[I])
- makeDeclVisibleInContextImpl(ND, false);
-
- // If this declaration is itself a transparent declaration context or
- // inline namespace, add its members (recursively).
- if (DeclContext *InnerCtx = dyn_cast<DeclContext>(*D))
- if (InnerCtx->isTransparentContext() || InnerCtx->isInlineNamespace())
- buildLookup(InnerCtx->getPrimaryContext());
- }
- }
-}
-
DeclContext::lookup_result
DeclContext::lookup(DeclarationName Name) {
DeclContext *PrimaryContext = getPrimaryContext();
if (PrimaryContext != this)
return PrimaryContext->lookup(Name);
- if (hasExternalVisibleStorage()) {
- // Check to see if we've already cached the lookup results.
- if (LookupPtr) {
- StoredDeclsMap::iterator I = LookupPtr->find(Name);
- if (I != LookupPtr->end())
- return I->second.getLookupResult();
- }
+ if (LookupPtr) {
+ StoredDeclsMap::iterator I = LookupPtr->find(Name);
+ if (I != LookupPtr->end())
+ return I->second.getLookupResult();
+ }
+ // If a PCH has a result for this name, and we have a local declaration, we
+ // will have imported the PCH result when adding the local declaration.
+ // FIXME: For modules, we could have had more declarations added by module
+ // imoprts since we saw the declaration of the local name.
+ if (hasExternalVisibleStorage()) {
ExternalASTSource *Source = getParentASTContext().getExternalSource();
return Source->FindExternalVisibleDeclsByName(this, Name);
}
- /// If there is no lookup data structure, build one now by walking
- /// all of the linked DeclContexts (in declaration order!) and
- /// inserting their values.
- if (!LookupPtr) {
- buildLookup(this);
-
- if (!LookupPtr)
- return lookup_result(lookup_iterator(0), lookup_iterator(0));
- }
-
- StoredDeclsMap::iterator Pos = LookupPtr->find(Name);
- if (Pos == LookupPtr->end())
- return lookup_result(lookup_iterator(0), lookup_iterator(0));
- return Pos->second.getLookupResult();
+ return lookup_result(lookup_iterator(0), lookup_iterator(0));
}
DeclContext::lookup_const_result
@@ -1213,60 +1177,53 @@ bool DeclContext::InEnclosingNamespaceSetOf(const DeclContext *O) const {
return false;
}
-void DeclContext::makeDeclVisibleInContext(NamedDecl *D, bool Recoverable)
+void DeclContext::makeDeclVisibleInContext(NamedDecl *D)
{
- makeDeclVisibleInContextWithFlags(D, false, Recoverable);
+ makeDeclVisibleInContextWithFlags(D, false);
}
-void DeclContext::makeDeclVisibleInContextInternal(NamedDecl *D, bool Recoverable)
+void DeclContext::makeDeclVisibleInContextInternal(NamedDecl *D)
{
- makeDeclVisibleInContextWithFlags(D, true, Recoverable);
+ makeDeclVisibleInContextWithFlags(D, true);
}
-void DeclContext::makeDeclVisibleInContextWithFlags(NamedDecl *D, bool Internal, bool Recoverable) {
+void DeclContext::makeDeclVisibleInContextWithFlags(NamedDecl *D,
+ bool Internal) {
+ // Skip unnamed declarations.
+ if (!D->getDeclName())
+ return;
+
+ // Skip entities that can't be found by name lookup into a particular
+ // context.
+ if ((D->getIdentifierNamespace() == 0 && !isa<UsingDirectiveDecl>(D)) ||
+ D->isTemplateParameter())
+ return;
+
+ // Skip template specializations.
// FIXME: This feels like a hack. Should DeclarationName support
// template-ids, or is there a better way to keep specializations
// from being visible?
- if (isa<ClassTemplateSpecializationDecl>(D) || D->isTemplateParameter())
+ if (isa<ClassTemplateSpecializationDecl>(D))
return;
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
if (FD->isFunctionTemplateSpecialization())
return;
- DeclContext *PrimaryContext = getPrimaryContext();
- if (PrimaryContext != this) {
- PrimaryContext->makeDeclVisibleInContextWithFlags(D, Internal, Recoverable);
- return;
- }
-
- // If we already have a lookup data structure, perform the insertion
- // into it. If we haven't deserialized externally stored decls, deserialize
- // them so we can add the decl. Otherwise, be lazy and don't build that
- // structure until someone asks for it.
- if (LookupPtr || !Recoverable || hasExternalVisibleStorage())
- makeDeclVisibleInContextImpl(D, Internal);
-
- // If we are a transparent context or inline namespace, insert into our
- // parent context, too. This operation is recursive.
- if (isTransparentContext() || isInlineNamespace())
- getParent()->makeDeclVisibleInContextWithFlags(D, Internal, Recoverable);
-
- Decl *DCAsDecl = cast<Decl>(this);
- // Notify that a decl was made visible unless it's a Tag being defined.
- if (!(isa<TagDecl>(DCAsDecl) && cast<TagDecl>(DCAsDecl)->isBeingDefined()))
- if (ASTMutationListener *L = DCAsDecl->getASTMutationListener())
- L->AddedVisibleDecl(this, D);
+ // Add the declaration into our lookup table (and those of containing
+ // contexts).
+ getPrimaryContext()->makeDeclVisibleInContextImpl(D, Internal);
}
void DeclContext::makeDeclVisibleInContextImpl(NamedDecl *D, bool Internal) {
- // Skip unnamed declarations.
- if (!D->getDeclName())
- return;
-
- // Skip entities that can't be found by name lookup into a particular
- // context.
- if ((D->getIdentifierNamespace() == 0 && !isa<UsingDirectiveDecl>(D)) ||
- D->isTemplateParameter())
+ // Skip declarations within functions.
+ // FIXME: We shouldn't need to build lookup tables for function declarations
+ // ever, and we can't do so correctly because we can't model the nesting of
+ // scopes which occurs within functions. We use "qualified" lookup into
+ // function declarations when handling friend declarations inside nested
+ // classes, and consequently accept the following invalid code:
+ //
+ // void f() { void g(); { int g; struct S { friend void g(); }; } }
+ if (isFunctionOrMethod() && !isa<FunctionDecl>(D))
return;
ASTContext *C = 0;
@@ -1289,23 +1246,32 @@ void DeclContext::makeDeclVisibleInContextImpl(NamedDecl *D, bool Internal) {
StoredDeclsList &DeclNameEntries = (*LookupPtr)[D->getDeclName()];
if (DeclNameEntries.isNull()) {
DeclNameEntries.setOnlyValue(D);
- return;
+ } else if (DeclNameEntries.HandleRedeclaration(D)) {
+ // This declaration has replaced an existing one for which
+ // declarationReplaces returns true.
+ } else {
+ // Put this declaration into the appropriate slot.
+ DeclNameEntries.AddSubsequentDecl(D);
}
- // If it is possible that this is a redeclaration, check to see if there is
- // already a decl for which declarationReplaces returns true. If there is
- // one, just replace it and return.
- if (DeclNameEntries.HandleRedeclaration(D))
- return;
+ // If we are a transparent context or inline namespace, insert into our
+ // parent context, too. This operation is recursive.
+ if (isTransparentContext() || isInlineNamespace())
+ getParent()->getPrimaryContext()->makeDeclVisibleInContextImpl(D, Internal);
- // Put this declaration into the appropriate slot.
- DeclNameEntries.AddSubsequentDecl(D);
+ Decl *DCAsDecl = cast<Decl>(this);
+ // Notify that a decl was made visible unless we are a Tag being defined.
+ if (!(isa<TagDecl>(DCAsDecl) && cast<TagDecl>(DCAsDecl)->isBeingDefined()))
+ if (ASTMutationListener *L = DCAsDecl->getASTMutationListener())
+ L->AddedVisibleDecl(this, D);
}
/// Returns iterator range [First, Last) of UsingDirectiveDecls stored within
/// this context.
DeclContext::udir_iterator_range
DeclContext::getUsingDirectives() const {
+ // FIXME: Use something more efficient than normal lookup for using
+ // directives. In C++, using directives are looked up more than anything else.
lookup_const_result Result = lookup(UsingDirectiveDecl::getName());
return udir_iterator_range(reinterpret_cast<udir_iterator>(Result.first),
reinterpret_cast<udir_iterator>(Result.second));
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index a9c1ec1cd6..bee542234b 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -8514,7 +8514,7 @@ CreateNewDecl:
New->setAccess(PrevDecl->getAccess());
DeclContext *DC = New->getDeclContext()->getRedeclContext();
- DC->makeDeclVisibleInContext(New, /* Recoverable = */ false);
+ DC->makeDeclVisibleInContext(New);
if (Name) // can be null along some error paths
if (Scope *EnclosingScope = getScopeForDeclContext(S, DC))
PushOnScopeChains(New, EnclosingScope, /* AddToContext = */ false);
@@ -8522,7 +8522,7 @@ CreateNewDecl:
S = getNonFieldDeclScope(S);
PushOnScopeChains(New, S, !IsForwardReference);
if (IsForwardReference)
- SearchDC->makeDeclVisibleInContext(New, /* Recoverable = */ false);
+ SearchDC->makeDeclVisibleInContext(New);
} else {
CurContext->addDecl(New);
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index abbbe11561..b6866d04e4 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -5829,14 +5829,15 @@ Decl *Sema::ActOnUsingDirective(Scope *S,
}
void Sema::PushUsingDirective(Scope *S, UsingDirectiveDecl *UDir) {
- // If scope has associated entity, then using directive is at namespace
- // or translation unit scope. We add UsingDirectiveDecls, into
- // it's lookup structure.
- if (DeclContext *Ctx = static_cast<DeclContext*>(S->getEntity()))
+ // If the scope has an associated entity and the using directive is at
+ // namespace or translation unit scope, add the UsingDirectiveDecl into
+ // its lookup structure so qualified name lookup can find it.
+ DeclContext *Ctx = static_cast<DeclContext*>(S->getEntity());
+ if (Ctx && !Ctx->isFunctionOrMethod())
Ctx->addDecl(UDir);
else
- // Otherwise it is block-sope. using-directives will affect lookup
- // only to the end of scope.
+ // Otherwise, it is at block sope. The using-directives will affect lookup
+ // only to the end of the scope.
S->PushUsingDirective(UDir);
}
@@ -10195,7 +10196,7 @@ Decl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D,
// lookup context is in lexical scope.
if (!CurContext->isDependentContext()) {
DC = DC->getRedeclContext();
- DC->makeDeclVisibleInContext(ND, /* Recoverable=*/ false);
+ DC->makeDeclVisibleInContext(ND);
if (Scope *EnclosingScope = getScopeForDeclContext(S, DC))
PushOnScopeChains(ND, EnclosingScope, /*AddToContext=*/ false);
}
diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp
index d224f1058a..268ab368ce 100644
--- a/lib/Sema/SemaDeclObjC.cpp
+++ b/lib/Sema/SemaDeclObjC.cpp
@@ -1026,7 +1026,7 @@ void Sema::CheckImplementationIvars(ObjCImplementationDecl *ImpDecl,
// Add ivar's to class's DeclContext.
for (unsigned i = 0, e = numIvars; i != e; ++i) {
ivars[i]->setLexicalDeclContext(ImpDecl);
- IDecl->makeDeclVisibleInContext(ivars[i], false);
+ IDecl->makeDeclVisibleInContext(ivars[i]);
ImpDecl->addDecl(ivars[i]);
}
@@ -1050,7 +1050,7 @@ void Sema::CheckImplementationIvars(ObjCImplementationDecl *ImpDecl,
}
// Instance ivar to Implementation's DeclContext.
ImplIvar->setLexicalDeclContext(ImpDecl);
- IDecl->makeDeclVisibleInContext(ImplIvar, false);
+ IDecl->makeDeclVisibleInContext(ImplIvar);
ImpDecl->addDecl(ImplIvar);
}
return;
diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp
index f1eb522415..fbb0dc6b0f 100644
--- a/lib/Sema/SemaLookup.cpp
+++ b/lib/Sema/SemaLookup.cpp
@@ -106,7 +106,8 @@ namespace {
assert(InnermostFileDC && InnermostFileDC->isFileContext());
for (; S; S = S->getParent()) {
- if (DeclContext *Ctx = static_cast<DeclContext*>(S->getEntity())) {
+ DeclContext *Ctx = static_cast<DeclContext*>(S->getEntity());
+ if (Ctx && !Ctx->isFunctionOrMethod()) {
DeclContext *EffectiveDC = (Ctx->isFileContext() ? Ctx : InnermostFileDC);
visit(Ctx, EffectiveDC);
} else {
diff --git a/lib/Sema/SemaObjCProperty.cpp b/lib/Sema/SemaObjCProperty.cpp
index 5c28db4c5e..5ece8f11e7 100644
--- a/lib/Sema/SemaObjCProperty.cpp
+++ b/lib/Sema/SemaObjCProperty.cpp
@@ -740,7 +740,7 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S,
ObjCIvarDecl::Private,
(Expr *)0, true);
ClassImpDecl->addDecl(Ivar);
- IDecl->makeDeclVisibleInContext(Ivar, false);
+ IDecl->makeDeclVisibleInContext(Ivar);
property->setPropertyIvarDecl(Ivar);
if (!getLangOpts().ObjCNonFragileABI)
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index af6b319e90..e76a253869 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -1088,7 +1088,7 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,
// Friend templates are visible in fairly strange ways.
if (!CurContext->isDependentContext()) {
DeclContext *DC = SemanticContext->getRedeclContext();
- DC->makeDeclVisibleInContext(NewTemplate, /* Recoverable = */ false);
+ DC->makeDeclVisibleInContext(NewTemplate);
if (Scope *EnclosingScope = getScopeForDeclContext(S, DC))
PushOnScopeChains(NewTemplate, EnclosingScope,
/* AddToContext = */ false);
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 56ce50e592..f10670c47a 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -817,7 +817,7 @@ Decl *TemplateDeclInstantiator::VisitClassTemplateDecl(ClassTemplateDecl *D) {
// Finish handling of friends.
if (isFriend) {
- DC->makeDeclVisibleInContext(Inst, /*Recoverable*/ false);
+ DC->makeDeclVisibleInContext(Inst);
Inst->setLexicalDeclContext(Owner);
RecordInst->setLexicalDeclContext(Owner);
return Inst;
@@ -1189,7 +1189,7 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D,
PrevDecl = Function->getPreviousDecl();
PrincipalDecl->setObjectOfFriendDecl(PrevDecl != 0);
- DC->makeDeclVisibleInContext(PrincipalDecl, /*Recoverable=*/ false);
+ DC->makeDeclVisibleInContext(PrincipalDecl);
bool queuedInstantiation = false;
diff --git a/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p11.cpp b/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p11.cpp
index 99903b57bf..c7966ce643 100644
--- a/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p11.cpp
+++ b/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p11.cpp
@@ -70,10 +70,8 @@ namespace test4 {
}
// FIXME: we should be able to diagnose both of these, but we can't.
-// ...I'm actually not sure why we can diagnose either of them; it's
-// probably a bug.
namespace test5 {
- namespace ns { void foo(int); } // expected-note {{target of using declaration}}
+ namespace ns { void foo(int); }
template <typename T> class Test0 {
void test() {
int foo(T);
@@ -83,11 +81,11 @@ namespace test5 {
template <typename T> class Test1 {
void test() {
- using ns::foo; // expected-note {{using declaration}}
- int foo(T); // expected-error {{declaration conflicts with target of using declaration already in scope}}
+ using ns::foo;
+ int foo(T);
}
};
template class Test0<int>;
- template class Test1<int>; // expected-note {{in instantiation of member function}}
+ template class Test1<int>;
}
diff --git a/test/Modules/namespaces.cpp b/test/Modules/namespaces.cpp
index a51c65992e..19e0c5a991 100644
--- a/test/Modules/namespaces.cpp
+++ b/test/Modules/namespaces.cpp
@@ -1,6 +1,10 @@
// RUN: rm -rf %t
// RUN: %clang_cc1 -x objective-c++ -fmodules -fmodule-cache-path %t -I %S/Inputs %s -verify
+// Importing modules which add declarations to a pre-existing non-imported
+// overload set does not currently work.
+// XFAIL: *
+
namespace N6 {
char &f(char);
}
diff --git a/test/SemaCXX/PR10447.cpp b/test/SemaCXX/PR10447.cpp
new file mode 100644
index 0000000000..08644ada4a
--- /dev/null
+++ b/test/SemaCXX/PR10447.cpp
@@ -0,0 +1,22 @@
+// RUN: %clang_cc1 -verify %s
+
+// PR12223
+namespace test1 {
+ namespace N {
+ extern "C" void f(struct S*);
+ void g(S*);
+ }
+ namespace N {
+ void f(struct S *s) {
+ g(s);
+ }
+ }
+}
+
+// PR10447
+namespace test2 {
+ extern "C" {
+ void f(struct Bar*) { }
+ test2::Bar *ptr;
+ }
+}