summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/include/clang/AST/DeclBase.h2
-rw-r--r--clang/lib/AST/ASTContext.cpp2
-rw-r--r--clang/lib/AST/DeclBase.cpp35
-rw-r--r--clang/lib/Sema/IdentifierResolver.cpp2
-rw-r--r--clang/lib/Sema/SemaLookup.cpp40
-rw-r--r--clang/lib/Serialization/ASTReader.cpp21
-rw-r--r--clang/test/Modules/cxx-templates.cpp10
-rw-r--r--clang/test/Modules/odr.cpp8
-rw-r--r--clang/test/Modules/redecl-add-after-load.cpp4
9 files changed, 62 insertions, 62 deletions
diff --git a/clang/include/clang/AST/DeclBase.h b/clang/include/clang/AST/DeclBase.h
index 121bd005353..30ce2601a16 100644
--- a/clang/include/clang/AST/DeclBase.h
+++ b/clang/include/clang/AST/DeclBase.h
@@ -1722,8 +1722,6 @@ private:
friend class DependentDiagnostic;
StoredDeclsMap *CreateStoredDeclsMap(ASTContext &C) const;
- template<decl_iterator (DeclContext::*Begin)() const,
- decl_iterator (DeclContext::*End)() const>
void buildLookupImpl(DeclContext *DCtx, bool Internal);
void makeDeclVisibleInContextWithFlags(NamedDecl *D, bool Internal,
bool Rediscoverable);
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index 89e1d52c643..57621a7b1f6 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -7946,7 +7946,7 @@ static GVALinkage basicGVALinkageForVariable(const ASTContext &Context,
while (LexicalContext && !isa<FunctionDecl>(LexicalContext))
LexicalContext = LexicalContext->getLexicalParent();
- // Let the static local variable inherit it's linkage from the nearest
+ // Let the static local variable inherit its linkage from the nearest
// enclosing function.
if (LexicalContext)
StaticLocalLinkage =
diff --git a/clang/lib/AST/DeclBase.cpp b/clang/lib/AST/DeclBase.cpp
index a8e151cc937..0053c3da8bc 100644
--- a/clang/lib/AST/DeclBase.cpp
+++ b/clang/lib/AST/DeclBase.cpp
@@ -1263,15 +1263,13 @@ static bool shouldBeHidden(NamedDecl *D) {
StoredDeclsMap *DeclContext::buildLookup() {
assert(this == getPrimaryContext() && "buildLookup called on non-primary DC");
- // FIXME: Should we keep going if hasExternalVisibleStorage?
if (!LookupPtr.getInt())
return LookupPtr.getPointer();
SmallVector<DeclContext *, 2> Contexts;
collectAllContexts(Contexts);
for (unsigned I = 0, N = Contexts.size(); I != N; ++I)
- buildLookupImpl<&DeclContext::decls_begin,
- &DeclContext::decls_end>(Contexts[I], false);
+ buildLookupImpl(Contexts[I], hasExternalVisibleStorage());
// We no longer have any lazy decls.
LookupPtr.setInt(false);
@@ -1282,13 +1280,8 @@ StoredDeclsMap *DeclContext::buildLookup() {
/// declarations contained within DCtx, which will either be this
/// DeclContext, a DeclContext linked to it, or a transparent context
/// nested within it.
-template<DeclContext::decl_iterator (DeclContext::*Begin)() const,
- DeclContext::decl_iterator (DeclContext::*End)() const>
void DeclContext::buildLookupImpl(DeclContext *DCtx, bool Internal) {
- for (decl_iterator I = (DCtx->*Begin)(), E = (DCtx->*End)();
- I != E; ++I) {
- Decl *D = *I;
-
+ for (Decl *D : DCtx->noload_decls()) {
// Insert this declaration into the lookup structure, but only if
// it's semantically within its decl context. Any other decls which
// should be found in this context are added eagerly.
@@ -1309,7 +1302,7 @@ void DeclContext::buildLookupImpl(DeclContext *DCtx, bool Internal) {
// context (recursively).
if (DeclContext *InnerCtx = dyn_cast<DeclContext>(D))
if (InnerCtx->isTransparentContext() || InnerCtx->isInlineNamespace())
- buildLookupImpl<Begin, End>(InnerCtx, Internal);
+ buildLookupImpl(InnerCtx, Internal);
}
}
@@ -1388,26 +1381,8 @@ DeclContext::noload_lookup(DeclarationName Name) {
if (PrimaryContext != this)
return PrimaryContext->noload_lookup(Name);
- StoredDeclsMap *Map = LookupPtr.getPointer();
- if (LookupPtr.getInt()) {
- // Carefully build the lookup map, without deserializing anything.
- SmallVector<DeclContext *, 2> Contexts;
- collectAllContexts(Contexts);
- for (unsigned I = 0, N = Contexts.size(); I != N; ++I)
- buildLookupImpl<&DeclContext::noload_decls_begin,
- &DeclContext::noload_decls_end>(Contexts[I], true);
-
- // We no longer have any lazy decls.
- LookupPtr.setInt(false);
-
- // There may now be names for which we have local decls but are
- // missing the external decls. FIXME: Just set the hasExternalDecls
- // flag on those names that have external decls.
- NeedToReconcileExternalVisibleStorage = true;
-
- Map = LookupPtr.getPointer();
- }
-
+ // Note that buildLookups does not trigger any deserialization.
+ StoredDeclsMap *Map = buildLookup();
if (!Map)
return lookup_result();
diff --git a/clang/lib/Sema/IdentifierResolver.cpp b/clang/lib/Sema/IdentifierResolver.cpp
index a6efe96573a..53263bac546 100644
--- a/clang/lib/Sema/IdentifierResolver.cpp
+++ b/clang/lib/Sema/IdentifierResolver.cpp
@@ -98,7 +98,7 @@ bool IdentifierResolver::isDeclInScope(Decl *D, DeclContext *Ctx, Scope *S,
bool AllowInlineNamespace) const {
Ctx = Ctx->getRedeclContext();
- if (Ctx->isFunctionOrMethod() || S->isFunctionPrototypeScope()) {
+ if (Ctx->isFunctionOrMethod() || (S && S->isFunctionPrototypeScope())) {
// Ignore the scopes associated within transparent declaration contexts.
while (S->getEntity() && S->getEntity()->isTransparentContext())
S = S->getParent();
diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp
index e15e532be19..0b406184058 100644
--- a/clang/lib/Sema/SemaLookup.cpp
+++ b/clang/lib/Sema/SemaLookup.cpp
@@ -3021,17 +3021,45 @@ static void LookupVisibleDecls(DeclContext *Ctx, LookupResult &Result,
if (Visited.visitedContext(Ctx->getPrimaryContext()))
return;
+ // Outside C++, lookup results for the TU live on identifiers.
+ if (isa<TranslationUnitDecl>(Ctx) &&
+ !Result.getSema().getLangOpts().CPlusPlus) {
+ auto &S = Result.getSema();
+ auto &Idents = S.Context.Idents;
+
+ // Ensure all external identifiers are in the identifier table.
+ if (IdentifierInfoLookup *External = Idents.getExternalIdentifierLookup()) {
+ std::unique_ptr<IdentifierIterator> Iter(External->getIdentifiers());
+ for (StringRef Name = Iter->Next(); !Name.empty(); Name = Iter->Next())
+ Idents.get(Name);
+ }
+
+ // Walk all lookup results in the TU for each identifier.
+ for (const auto &Ident : Idents) {
+ for (auto I = S.IdResolver.begin(Ident.getValue()),
+ E = S.IdResolver.end();
+ I != E; ++I) {
+ if (S.IdResolver.isDeclInScope(*I, Ctx)) {
+ if (NamedDecl *ND = Result.getAcceptableDecl(*I)) {
+ Consumer.FoundDecl(ND, Visited.checkHidden(ND), Ctx, InBaseClass);
+ Visited.add(ND);
+ }
+ }
+ }
+ }
+
+ return;
+ }
+
if (CXXRecordDecl *Class = dyn_cast<CXXRecordDecl>(Ctx))
Result.getSema().ForceDeclarationOfImplicitMembers(Class);
// Enumerate all of the results in this context.
for (const auto &R : Ctx->lookups()) {
- for (auto *I : R) {
- if (NamedDecl *ND = dyn_cast<NamedDecl>(I)) {
- if ((ND = Result.getAcceptableDecl(ND))) {
- Consumer.FoundDecl(ND, Visited.checkHidden(ND), Ctx, InBaseClass);
- Visited.add(ND);
- }
+ for (auto *D : R) {
+ if (auto *ND = Result.getAcceptableDecl(D)) {
+ Consumer.FoundDecl(ND, Visited.checkHidden(ND), Ctx, InBaseClass);
+ Visited.add(ND);
}
}
}
diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp
index f4b4c4b9879..93544ef20fc 100644
--- a/clang/lib/Serialization/ASTReader.cpp
+++ b/clang/lib/Serialization/ASTReader.cpp
@@ -2835,6 +2835,8 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
}
case EAGERLY_DESERIALIZED_DECLS:
+ // FIXME: Skip reading this record if our ASTConsumer doesn't care
+ // about "interesting" decls (for instance, if we're building a module).
for (unsigned I = 0, N = Record.size(); I != N; ++I)
EagerlyDeserializedDecls.push_back(getGlobalDeclID(F, Record[I]));
break;
@@ -6832,6 +6834,12 @@ void ASTReader::PassInterestingDeclsToConsumer() {
SaveAndRestore<bool> GuardPassingDeclsToConsumer(PassingDeclsToConsumer,
true);
+ // Ensure that we've loaded all potentially-interesting declarations
+ // that need to be eagerly loaded.
+ for (auto ID : EagerlyDeserializedDecls)
+ GetDecl(ID);
+ EagerlyDeserializedDecls.clear();
+
while (!InterestingDecls.empty()) {
Decl *D = InterestingDecls.front();
InterestingDecls.pop_front();
@@ -6850,17 +6858,8 @@ void ASTReader::PassInterestingDeclToConsumer(Decl *D) {
void ASTReader::StartTranslationUnit(ASTConsumer *Consumer) {
this->Consumer = Consumer;
- if (!Consumer)
- return;
-
- for (unsigned I = 0, N = EagerlyDeserializedDecls.size(); I != N; ++I) {
- // Force deserialization of this decl, which will cause it to be queued for
- // passing to the consumer.
- GetDecl(EagerlyDeserializedDecls[I]);
- }
- EagerlyDeserializedDecls.clear();
-
- PassInterestingDeclsToConsumer();
+ if (Consumer)
+ PassInterestingDeclsToConsumer();
if (DeserializationListener)
DeserializationListener->ReaderInitialized(this);
diff --git a/clang/test/Modules/cxx-templates.cpp b/clang/test/Modules/cxx-templates.cpp
index 46c2f33ef15..41b0f2cd92d 100644
--- a/clang/test/Modules/cxx-templates.cpp
+++ b/clang/test/Modules/cxx-templates.cpp
@@ -1,7 +1,7 @@
// RUN: rm -rf %t
// RUN: not %clang_cc1 -x objective-c++ -fmodules -fno-modules-error-recovery -fmodules-cache-path=%t -I %S/Inputs %s -std=c++11 -ast-dump-lookups | FileCheck %s --check-prefix=CHECK-GLOBAL
// RUN: not %clang_cc1 -x objective-c++ -fmodules -fno-modules-error-recovery -fmodules-cache-path=%t -I %S/Inputs %s -std=c++11 -ast-dump-lookups -ast-dump-filter N | FileCheck %s --check-prefix=CHECK-NAMESPACE-N
-// RUN: not %clang_cc1 -x objective-c++ -fmodules -fno-modules-error-recovery -fmodules-cache-path=%t -I %S/Inputs %s -std=c++11 -ast-dump | FileCheck %s --check-prefix=CHECK-DUMP
+// RUN: not %clang_cc1 -x objective-c++ -fmodules -fno-modules-error-recovery -fmodules-cache-path=%t -I %S/Inputs %s -std=c++11 -ast-dump -ast-dump-filter SomeTemplate | FileCheck %s --check-prefix=CHECK-DUMP
// RUN: %clang_cc1 -x objective-c++ -fmodules -fno-modules-error-recovery -fmodules-cache-path=%t -I %S/Inputs %s -verify -std=c++11
// RUN: %clang_cc1 -x objective-c++ -fmodules -fno-modules-error-recovery -fmodules-cache-path=%t -I %S/Inputs %s -verify -std=c++11 -DEARLY_IMPORT
@@ -125,9 +125,10 @@ void g() {
static_assert(Outer<int>::Inner<int>::f() == 1, "");
static_assert(Outer<int>::Inner<int>::g() == 2, "");
-#ifndef EARLY_IMPORT
-// FIXME: The textual inclusion above shouldn't cause this to fail!
-static_assert(MergeTemplateDefinitions<int>::f() == 1, "");
+// FIXME: We're too lazy in merging class definitions to find the definition
+// of this function.
+static_assert(MergeTemplateDefinitions<int>::f() == 1, ""); // expected-error {{constant expression}} expected-note {{undefined}}
+// expected-note@cxx-templates-c.h:10 {{here}}
static_assert(MergeTemplateDefinitions<int>::g() == 2, "");
RedeclaredAsFriend<int> raf1;
@@ -140,7 +141,6 @@ MergeSpecializations<int[]>::partially_specialized_in_c spec_in_c_1;
MergeSpecializations<char>::explicitly_specialized_in_a spec_in_a_2;
MergeSpecializations<double>::explicitly_specialized_in_b spec_in_b_2;
MergeSpecializations<bool>::explicitly_specialized_in_c spec_in_c_2;
-#endif
MergeAnonUnionMember<> maum_main;
typedef DontWalkPreviousDeclAfterMerging<int> dwpdam_typedef_2;
diff --git a/clang/test/Modules/odr.cpp b/clang/test/Modules/odr.cpp
index 120ca20e0a8..4ac257cd03a 100644
--- a/clang/test/Modules/odr.cpp
+++ b/clang/test/Modules/odr.cpp
@@ -15,9 +15,9 @@ bool b = F<int>{0} == F<int>{1};
int x = f() + g();
// expected-note@a.h:5 {{definition has no member 'e2'}}
-// expected-note@a.h:3 {{declaration of 'f' does not match}}
-// expected-note@a.h:1 {{definition has no member 'm'}}
+// expected-note@b.h:3 {{declaration of 'f' does not match}}
+// expected-note@b.h:1 {{definition has no member 'n'}}
// expected-error@b.h:5 {{'E::e2' from module 'b' is not present in definition of 'E' in module 'a'}}
-// expected-error@b.h:3 {{'Y::f' from module 'b' is not present in definition of 'Y' in module 'a'}}
-// expected-error@b.h:2 {{'Y::m' from module 'b' is not present in definition of 'Y' in module 'a'}}
+// expected-error@a.h:3 {{'Y::f' from module 'a' is not present in definition of 'Y' in module 'b'}}
+// expected-error@a.h:2 {{'Y::n' from module 'a' is not present in definition of 'Y' in module 'b'}}
diff --git a/clang/test/Modules/redecl-add-after-load.cpp b/clang/test/Modules/redecl-add-after-load.cpp
index 68deaf8b4ef..53e54c84cc3 100644
--- a/clang/test/Modules/redecl-add-after-load.cpp
+++ b/clang/test/Modules/redecl-add-after-load.cpp
@@ -29,7 +29,7 @@ struct D {
static constexpr int function(); // expected-note {{here}}
};
typedef D::A DB;
-constexpr int D_test(bool b) { return b ? D::variable : D::function(); } // expected-note {{subexpression}} expected-note {{undefined}}
+constexpr int D_test(bool b) { return b ? D::variable : D::function(); } // expected-note {{undefined}}
#endif
@import redecl_add_after_load;
@@ -54,6 +54,6 @@ constexpr int merged_struct_variable_test = D_test(true);
constexpr int merged_struct_function_test = D_test(false);
#ifndef IMPORT_DECLS
// expected-error@-4 {{incomplete}}
-// expected-error@-4 {{constant}} expected-note@-4 {{in call to}}
+// @-4: definition of D::variable must be emitted, so it gets imported eagerly
// expected-error@-4 {{constant}} expected-note@-4 {{in call to}}
#endif
OpenPOWER on IntegriCloud