diff options
-rw-r--r-- | clang/include/clang/AST/DeclBase.h | 6 | ||||
-rw-r--r-- | clang/lib/AST/ASTDumper.cpp | 2 | ||||
-rw-r--r-- | clang/lib/AST/DeclBase.cpp | 5 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTReader.cpp | 41 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTReaderDecl.cpp | 4 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTWriter.cpp | 16 | ||||
-rw-r--r-- | clang/test/Modules/Inputs/cxx-lookup/a.h | 2 | ||||
-rw-r--r-- | clang/test/Modules/Inputs/cxx-lookup/b.h | 3 | ||||
-rw-r--r-- | clang/test/Modules/Inputs/cxx-lookup/c1.h | 3 | ||||
-rw-r--r-- | clang/test/Modules/Inputs/cxx-lookup/c2.h | 2 | ||||
-rw-r--r-- | clang/test/Modules/Inputs/cxx-lookup/module.modulemap | 8 | ||||
-rw-r--r-- | clang/test/Modules/Inputs/cxx-lookup/x.h | 2 | ||||
-rw-r--r-- | clang/test/Modules/Inputs/cxx-lookup/y.h | 5 | ||||
-rw-r--r-- | clang/test/Modules/cxx-lookup.cpp | 6 | ||||
-rw-r--r-- | clang/test/Modules/cxx-templates.cpp | 4 |
15 files changed, 82 insertions, 27 deletions
diff --git a/clang/include/clang/AST/DeclBase.h b/clang/include/clang/AST/DeclBase.h index 3fb68a47c04..551a883a8fa 100644 --- a/clang/include/clang/AST/DeclBase.h +++ b/clang/include/clang/AST/DeclBase.h @@ -515,9 +515,13 @@ public: /// indicating the declaration is used. void markUsed(ASTContext &C); - /// \brief Whether this declaration was referenced. + /// \brief Whether any declaration of this entity was referenced. bool isReferenced() const; + /// \brief Whether this declaration was referenced. This should not be relied + /// upon for anything other than debugging. + bool isThisDeclarationReferenced() const { return Referenced; } + void setReferenced(bool R = true) { Referenced = R; } /// \brief Whether this declaration is a top-level declaration (function, diff --git a/clang/lib/AST/ASTDumper.cpp b/clang/lib/AST/ASTDumper.cpp index 5d6e18a4506..d9dc8b57dfb 100644 --- a/clang/lib/AST/ASTDumper.cpp +++ b/clang/lib/AST/ASTDumper.cpp @@ -826,7 +826,7 @@ void ASTDumper::dumpDecl(const Decl *D) { OS << " implicit"; if (D->isUsed()) OS << " used"; - else if (D->isReferenced()) + else if (D->isThisDeclarationReferenced()) OS << " referenced"; if (D->isInvalidDecl()) OS << " invalid"; diff --git a/clang/lib/AST/DeclBase.cpp b/clang/lib/AST/DeclBase.cpp index 2b1506d191d..49d05d0d407 100644 --- a/clang/lib/AST/DeclBase.cpp +++ b/clang/lib/AST/DeclBase.cpp @@ -1296,6 +1296,11 @@ DeclContext::lookup(DeclarationName Name) { if (PrimaryContext != this) return PrimaryContext->lookup(Name); + // If this is a namespace, ensure that any later redeclarations of it have + // been loaded, since they may add names to the result of this lookup. + if (auto *ND = dyn_cast<NamespaceDecl>(this)) + (void)ND->getMostRecentDecl(); + if (hasExternalVisibleStorage()) { if (NeedToReconcileExternalVisibleStorage) reconcileExternalVisibleStorage(); diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index 1cce383f2d0..d3d1e48ccbb 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -1898,16 +1898,20 @@ void ASTReader::removeOverriddenMacros(IdentifierInfo *II, SubmoduleID OwnerID = Overrides[OI]; // If this macro is not yet visible, remove it from the hidden names list. + // It won't be there if we're in the middle of making the owner visible. Module *Owner = getSubmodule(OwnerID); - HiddenNames &Hidden = HiddenNamesMap[Owner]; - HiddenMacrosMap::iterator HI = Hidden.HiddenMacros.find(II); - if (HI != Hidden.HiddenMacros.end()) { - // Register the macro now so we don't lose it when we re-export. - PP.appendMacroDirective(II, HI->second->import(PP, ImportLoc)); - - auto SubOverrides = HI->second->getOverriddenSubmodules(); - Hidden.HiddenMacros.erase(HI); - removeOverriddenMacros(II, ImportLoc, Ambig, SubOverrides); + auto HiddenIt = HiddenNamesMap.find(Owner); + if (HiddenIt != HiddenNamesMap.end()) { + HiddenNames &Hidden = HiddenIt->second; + HiddenMacrosMap::iterator HI = Hidden.HiddenMacros.find(II); + if (HI != Hidden.HiddenMacros.end()) { + // Register the macro now so we don't lose it when we re-export. + PP.appendMacroDirective(II, HI->second->import(PP, ImportLoc)); + + auto SubOverrides = HI->second->getOverriddenSubmodules(); + Hidden.HiddenMacros.erase(HI); + removeOverriddenMacros(II, ImportLoc, Ambig, SubOverrides); + } } // If this macro is already in our list of conflicts, remove it from there. @@ -2675,7 +2679,6 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) { auto *DC = cast<DeclContext>(D); DC->getPrimaryContext()->setHasExternalVisibleStorage(true); auto *&LookupTable = F.DeclContextInfos[DC].NameLookupTableData; - // FIXME: There should never be an existing lookup table. delete LookupTable; LookupTable = Table; } else @@ -6051,12 +6054,6 @@ void ASTReader::CompleteRedeclChain(const Decl *D) { const DeclContext *DC = D->getDeclContext()->getRedeclContext(); - // Recursively ensure that the decl context itself is complete - // (in particular, this matters if the decl context is a namespace). - // - // FIXME: This should be performed by lookup instead of here. - cast<Decl>(DC)->getMostRecentDecl(); - // If this is a named declaration, complete it by looking it up // within its context. // @@ -8246,9 +8243,16 @@ void ASTReader::finishPendingActions() { } void ASTReader::diagnoseOdrViolations() { + if (PendingOdrMergeFailures.empty() && PendingOdrMergeChecks.empty()) + return; + // Trigger the import of the full definition of each class that had any // odr-merging problems, so we can produce better diagnostics for them. - for (auto &Merge : PendingOdrMergeFailures) { + // These updates may in turn find and diagnose some ODR failures, so take + // ownership of the set first. + auto OdrMergeFailures = std::move(PendingOdrMergeFailures); + PendingOdrMergeFailures.clear(); + for (auto &Merge : OdrMergeFailures) { Merge.first->buildLookup(); Merge.first->decls_begin(); Merge.first->bases_begin(); @@ -8322,7 +8326,7 @@ void ASTReader::diagnoseOdrViolations() { } // Issue any pending ODR-failure diagnostics. - for (auto &Merge : PendingOdrMergeFailures) { + for (auto &Merge : OdrMergeFailures) { // If we've already pointed out a specific problem with this class, don't // bother issuing a general "something's different" diagnostic. if (!DiagnosedOdrMergeFailures.insert(Merge.first)) @@ -8361,7 +8365,6 @@ void ASTReader::diagnoseOdrViolations() { << Merge.first; } } - PendingOdrMergeFailures.clear(); } void ASTReader::FinishedDeserializing() { diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp index b153043082f..46f6106c13a 100644 --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -2619,11 +2619,11 @@ ASTReader::combineStoredMergedDecls(Decl *Canon, GlobalDeclID CanonID) { // Append the stored merged declarations to the merged declarations set. MergedDeclsMap::iterator Pos = MergedDecls.find(Canon); if (Pos == MergedDecls.end()) - Pos = MergedDecls.insert(std::make_pair(Canon, + Pos = MergedDecls.insert(std::make_pair(Canon, SmallVector<DeclID, 2>())).first; Pos->second.append(StoredPos->second.begin(), StoredPos->second.end()); StoredMergedDecls.erase(StoredPos); - + // Sort and uniquify the set of merged declarations. llvm::array_pod_sort(Pos->second.begin(), Pos->second.end()); Pos->second.erase(std::unique(Pos->second.begin(), Pos->second.end()), diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index ccd57086c38..e8c3177cb86 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -3479,6 +3479,18 @@ void ASTWriter::WriteIdentifierTable(Preprocessor &PP, // DeclContext's Name Lookup Table Serialization //===----------------------------------------------------------------------===// +/// Determine the declaration that should be put into the name lookup table to +/// represent the given declaration in this module. This is usually D itself, +/// but if D was imported and merged into a local declaration, we want the most +/// recent local declaration instead. The chosen declaration will be the most +/// recent declaration in any module that imports this one. +static NamedDecl *getDeclForLocalLookup(NamedDecl *D) { + for (Decl *Redecl = D; Redecl; Redecl = Redecl->getPreviousDecl()) + if (!Redecl->isFromASTFile()) + return cast<NamedDecl>(Redecl); + return D; +} + namespace { // Trait used for the on-disk hash table used in the method pool. class ASTDeclContextNameLookupTrait { @@ -3596,7 +3608,7 @@ public: LE.write<uint16_t>(Lookup.size()); for (DeclContext::lookup_iterator I = Lookup.begin(), E = Lookup.end(); I != E; ++I) - LE.write<uint32_t>(Writer.GetDeclRef(*I)); + LE.write<uint32_t>(Writer.GetDeclRef(getDeclForLocalLookup(*I))); assert(Out.tell() - Start == DataLen && "Data length is wrong"); } @@ -3642,7 +3654,7 @@ void ASTWriter::AddUpdatedDeclContext(const DeclContext *DC) { [&](DeclarationName Name, DeclContext::lookup_const_result Result) { for (auto *Decl : Result) - GetDeclRef(Decl); + GetDeclRef(getDeclForLocalLookup(Decl)); }); } } diff --git a/clang/test/Modules/Inputs/cxx-lookup/a.h b/clang/test/Modules/Inputs/cxx-lookup/a.h new file mode 100644 index 00000000000..25f614fe50b --- /dev/null +++ b/clang/test/Modules/Inputs/cxx-lookup/a.h @@ -0,0 +1,2 @@ +// a +namespace llvm { class GlobalValue; } diff --git a/clang/test/Modules/Inputs/cxx-lookup/b.h b/clang/test/Modules/Inputs/cxx-lookup/b.h new file mode 100644 index 00000000000..c2ede9f28dc --- /dev/null +++ b/clang/test/Modules/Inputs/cxx-lookup/b.h @@ -0,0 +1,3 @@ +// b +namespace llvm { class GlobalValue; } +#include "y.h" diff --git a/clang/test/Modules/Inputs/cxx-lookup/c1.h b/clang/test/Modules/Inputs/cxx-lookup/c1.h new file mode 100644 index 00000000000..dba4a4c0a00 --- /dev/null +++ b/clang/test/Modules/Inputs/cxx-lookup/c1.h @@ -0,0 +1,3 @@ +// c1 +#include "a.h" +#include "b.h" diff --git a/clang/test/Modules/Inputs/cxx-lookup/c2.h b/clang/test/Modules/Inputs/cxx-lookup/c2.h new file mode 100644 index 00000000000..463e270e267 --- /dev/null +++ b/clang/test/Modules/Inputs/cxx-lookup/c2.h @@ -0,0 +1,2 @@ +// c2 +namespace llvm { class GlobalValue; } diff --git a/clang/test/Modules/Inputs/cxx-lookup/module.modulemap b/clang/test/Modules/Inputs/cxx-lookup/module.modulemap new file mode 100644 index 00000000000..6d397af250c --- /dev/null +++ b/clang/test/Modules/Inputs/cxx-lookup/module.modulemap @@ -0,0 +1,8 @@ +module A { header "a.h" export * } +module B { header "b.h" export * } +module C { + module C2 { header "c2.h" export * } + module C1 { header "c1.h" export * } +} +module X { header "x.h" export * } +module Y { header "y.h" export * } diff --git a/clang/test/Modules/Inputs/cxx-lookup/x.h b/clang/test/Modules/Inputs/cxx-lookup/x.h new file mode 100644 index 00000000000..a8826e00581 --- /dev/null +++ b/clang/test/Modules/Inputs/cxx-lookup/x.h @@ -0,0 +1,2 @@ +template <class T> class allocator; +struct X { virtual allocator<char> f(); }; diff --git a/clang/test/Modules/Inputs/cxx-lookup/y.h b/clang/test/Modules/Inputs/cxx-lookup/y.h new file mode 100644 index 00000000000..8867e8a8bec --- /dev/null +++ b/clang/test/Modules/Inputs/cxx-lookup/y.h @@ -0,0 +1,5 @@ +#include "x.h" +namespace llvm { + struct ulittle32_t; + extern allocator<ulittle32_t> *x; +} diff --git a/clang/test/Modules/cxx-lookup.cpp b/clang/test/Modules/cxx-lookup.cpp new file mode 100644 index 00000000000..47c879dbb63 --- /dev/null +++ b/clang/test/Modules/cxx-lookup.cpp @@ -0,0 +1,6 @@ +// RUN: rm -rf %t +// RUN: %clang_cc1 -fmodules -fmodules-cache-path=%t %s -I%S/Inputs/cxx-lookup -verify +// expected-no-diagnostics +namespace llvm {} +#include "c2.h" +llvm::GlobalValue *p; diff --git a/clang/test/Modules/cxx-templates.cpp b/clang/test/Modules/cxx-templates.cpp index 1b7c045fae9..6f5d319a8e5 100644 --- a/clang/test/Modules/cxx-templates.cpp +++ b/clang/test/Modules/cxx-templates.cpp @@ -29,8 +29,8 @@ void g() { N::f<double>(1.0); N::f<int>(); N::f(); // expected-error {{no matching function}} - // expected-note@Inputs/cxx-templates-a.h:6 {{couldn't infer template argument}} - // expected-note@Inputs/cxx-templates-a.h:7 {{requires 1 argument}} + // expected-note@Inputs/cxx-templates-b.h:6 {{couldn't infer template argument}} + // expected-note@Inputs/cxx-templates-b.h:7 {{requires single argument}} template_param_kinds_1<0>(); // ok, from cxx-templates-a.h template_param_kinds_1<int>(); // ok, from cxx-templates-b.h |