summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/AST/ASTContext.cpp2
-rw-r--r--clang/lib/AST/DeclBase.cpp99
-rw-r--r--clang/lib/Sema/IdentifierResolver.cpp2
-rw-r--r--clang/lib/Sema/SemaExceptionSpec.cpp6
-rw-r--r--clang/lib/Sema/SemaLookup.cpp40
-rw-r--r--clang/lib/Serialization/ASTReader.cpp40
-rw-r--r--clang/lib/Serialization/ASTReaderDecl.cpp77
-rw-r--r--clang/lib/Serialization/ASTWriter.cpp48
8 files changed, 176 insertions, 138 deletions
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..1f08a64d3ab 100644
--- a/clang/lib/AST/DeclBase.cpp
+++ b/clang/lib/AST/DeclBase.cpp
@@ -1011,10 +1011,10 @@ DeclContext::BuildDeclChain(ArrayRef<Decl*> Decls,
/// built a lookup map. For every name in the map, pull in the new names from
/// the external storage.
void DeclContext::reconcileExternalVisibleStorage() const {
- assert(NeedToReconcileExternalVisibleStorage && LookupPtr.getPointer());
+ assert(NeedToReconcileExternalVisibleStorage && LookupPtr);
NeedToReconcileExternalVisibleStorage = false;
- for (auto &Lookup : *LookupPtr.getPointer())
+ for (auto &Lookup : *LookupPtr)
Lookup.second.setHasExternalDecls();
}
@@ -1027,10 +1027,13 @@ DeclContext::LoadLexicalDeclsFromExternalStorage() const {
// Notify that we have a DeclContext that is initializing.
ExternalASTSource::Deserializing ADeclContext(Source);
-
+
+ ExternalLexicalStorage = false;
+ bool HadLazyExternalLexicalLookups = HasLazyExternalLexicalLookups;
+ HasLazyExternalLexicalLookups = false;
+
// Load the external declarations, if any.
SmallVector<Decl*, 64> Decls;
- ExternalLexicalStorage = false;
switch (Source->FindExternalLexicalDecls(this, Decls)) {
case ELR_Success:
break;
@@ -1043,6 +1046,9 @@ DeclContext::LoadLexicalDeclsFromExternalStorage() const {
if (Decls.empty())
return;
+ if (HadLazyExternalLexicalLookups)
+ HasLazyLocalLexicalLookups = true;
+
// We may have already loaded just the fields of this record, in which case
// we need to ignore them.
bool FieldsAlreadyLoaded = false;
@@ -1065,7 +1071,7 @@ ExternalASTSource::SetNoExternalVisibleDeclsForName(const DeclContext *DC,
DeclarationName Name) {
ASTContext &Context = DC->getParentASTContext();
StoredDeclsMap *Map;
- if (!(Map = DC->LookupPtr.getPointer()))
+ if (!(Map = DC->LookupPtr))
Map = DC->CreateStoredDeclsMap(Context);
if (DC->NeedToReconcileExternalVisibleStorage)
DC->reconcileExternalVisibleStorage();
@@ -1081,7 +1087,7 @@ ExternalASTSource::SetExternalVisibleDeclsForName(const DeclContext *DC,
ArrayRef<NamedDecl*> Decls) {
ASTContext &Context = DC->getParentASTContext();
StoredDeclsMap *Map;
- if (!(Map = DC->LookupPtr.getPointer()))
+ if (!(Map = DC->LookupPtr))
Map = DC->CreateStoredDeclsMap(Context);
if (DC->NeedToReconcileExternalVisibleStorage)
DC->reconcileExternalVisibleStorage();
@@ -1175,7 +1181,7 @@ void DeclContext::removeDecl(Decl *D) {
// Remove only decls that have a name
if (!ND->getDeclName()) return;
- StoredDeclsMap *Map = getPrimaryContext()->LookupPtr.getPointer();
+ StoredDeclsMap *Map = getPrimaryContext()->LookupPtr;
if (!Map) return;
StoredDeclsMap::iterator Pos = Map->find(ND->getDeclName());
@@ -1263,32 +1269,28 @@ 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();
+ if (!HasLazyLocalLexicalLookups && !HasLazyExternalLexicalLookups)
+ return LookupPtr;
+
+ if (HasLazyExternalLexicalLookups)
+ LoadLexicalDeclsFromExternalStorage();
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);
- return LookupPtr.getPointer();
+ HasLazyLocalLexicalLookups = false;
+ return LookupPtr;
}
/// buildLookupImpl - Build part of the lookup data structure for the
/// 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 +1311,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);
}
}
@@ -1337,9 +1339,9 @@ DeclContext::lookup(DeclarationName Name) const {
if (NeedToReconcileExternalVisibleStorage)
reconcileExternalVisibleStorage();
- StoredDeclsMap *Map = LookupPtr.getPointer();
+ StoredDeclsMap *Map = LookupPtr;
- if (LookupPtr.getInt())
+ if (HasLazyLocalLexicalLookups || HasLazyExternalLexicalLookups)
// FIXME: Make buildLookup const?
Map = const_cast<DeclContext*>(this)->buildLookup();
@@ -1353,7 +1355,7 @@ DeclContext::lookup(DeclarationName Name) const {
return R.first->second.getLookupResult();
if (Source->FindExternalVisibleDeclsByName(this, Name) || !R.second) {
- if (StoredDeclsMap *Map = LookupPtr.getPointer()) {
+ if (StoredDeclsMap *Map = LookupPtr) {
StoredDeclsMap::iterator I = Map->find(Name);
if (I != Map->end())
return I->second.getLookupResult();
@@ -1363,8 +1365,8 @@ DeclContext::lookup(DeclarationName Name) const {
return lookup_result();
}
- StoredDeclsMap *Map = LookupPtr.getPointer();
- if (LookupPtr.getInt())
+ StoredDeclsMap *Map = LookupPtr;
+ if (HasLazyLocalLexicalLookups || HasLazyExternalLexicalLookups)
Map = const_cast<DeclContext*>(this)->buildLookup();
if (!Map)
@@ -1388,26 +1390,18 @@ 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.
+ // If we have any lazy lexical declarations not in our lookup map, add them
+ // now. Don't import any external declarations, not even if we know we have
+ // some missing from the external visible lookups.
+ if (HasLazyLocalLexicalLookups) {
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();
+ buildLookupImpl(Contexts[I], hasExternalVisibleStorage());
+ HasLazyLocalLexicalLookups = false;
}
+ StoredDeclsMap *Map = LookupPtr;
if (!Map)
return lookup_result();
@@ -1429,8 +1423,9 @@ void DeclContext::localUncachedLookup(DeclarationName Name,
}
// If we have a lookup table, check there first. Maybe we'll get lucky.
- if (Name && !LookupPtr.getInt()) {
- if (StoredDeclsMap *Map = LookupPtr.getPointer()) {
+ // FIXME: Should we be checking these flags on the primary context?
+ if (Name && !HasLazyLocalLexicalLookups && !HasLazyExternalLexicalLookups) {
+ if (StoredDeclsMap *Map = LookupPtr) {
StoredDeclsMap::iterator Pos = Map->find(Name);
if (Pos != Map->end()) {
Results.insert(Results.end(),
@@ -1443,6 +1438,8 @@ void DeclContext::localUncachedLookup(DeclarationName Name,
// Slow case: grovel through the declarations in our chain looking for
// matches.
+ // FIXME: If we have lazy external declarations, this will not find them!
+ // FIXME: Should we CollectAllContexts and walk them all here?
for (Decl *D = FirstDecl; D; D = D->getNextDeclInContext()) {
if (NamedDecl *ND = dyn_cast<NamedDecl>(D))
if (ND->getDeclName() == Name)
@@ -1523,7 +1520,7 @@ void DeclContext::makeDeclVisibleInContextWithFlags(NamedDecl *D, bool Internal,
// FIXME: As a performance hack, don't add such decls into the translation
// unit unless we're in C++, since qualified lookup into the TU is never
// performed.
- if (LookupPtr.getPointer() || hasExternalVisibleStorage() ||
+ if (LookupPtr || hasExternalVisibleStorage() ||
((!Recoverable || D->getDeclContext() != D->getLexicalDeclContext()) &&
(getParentASTContext().getLangOpts().CPlusPlus ||
!isTranslationUnit()))) {
@@ -1533,7 +1530,7 @@ void DeclContext::makeDeclVisibleInContextWithFlags(NamedDecl *D, bool Internal,
buildLookup();
makeDeclVisibleInContextImpl(D, Internal);
} else {
- LookupPtr.setInt(true);
+ HasLazyLocalLexicalLookups = true;
}
// If we are a transparent context or inline namespace, insert into our
@@ -1551,7 +1548,7 @@ void DeclContext::makeDeclVisibleInContextWithFlags(NamedDecl *D, bool Internal,
void DeclContext::makeDeclVisibleInContextImpl(NamedDecl *D, bool Internal) {
// Find or create the stored declaration map.
- StoredDeclsMap *Map = LookupPtr.getPointer();
+ StoredDeclsMap *Map = LookupPtr;
if (!Map) {
ASTContext *C = &getParentASTContext();
Map = CreateStoredDeclsMap(*C);
@@ -1613,7 +1610,7 @@ DeclContext::udir_range DeclContext::using_directives() const {
//===----------------------------------------------------------------------===//
StoredDeclsMap *DeclContext::CreateStoredDeclsMap(ASTContext &C) const {
- assert(!LookupPtr.getPointer() && "context already has a decls map");
+ assert(!LookupPtr && "context already has a decls map");
assert(getPrimaryContext() == this &&
"creating decls map on non-primary context");
@@ -1625,7 +1622,7 @@ StoredDeclsMap *DeclContext::CreateStoredDeclsMap(ASTContext &C) const {
M = new StoredDeclsMap();
M->Previous = C.LastSDM;
C.LastSDM = llvm::PointerIntPair<StoredDeclsMap*,1>(M, Dependent);
- LookupPtr.setPointer(M);
+ LookupPtr = M;
return M;
}
@@ -1657,11 +1654,11 @@ DependentDiagnostic *DependentDiagnostic::Create(ASTContext &C,
assert(Parent->isDependentContext()
&& "cannot iterate dependent diagnostics of non-dependent context");
Parent = Parent->getPrimaryContext();
- if (!Parent->LookupPtr.getPointer())
+ if (!Parent->LookupPtr)
Parent->CreateStoredDeclsMap(C);
- DependentStoredDeclsMap *Map
- = static_cast<DependentStoredDeclsMap*>(Parent->LookupPtr.getPointer());
+ DependentStoredDeclsMap *Map =
+ static_cast<DependentStoredDeclsMap *>(Parent->LookupPtr);
// Allocate the copy of the PartialDiagnostic via the ASTContext's
// BumpPtrAllocator, rather than the ASTContext itself.
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/SemaExceptionSpec.cpp b/clang/lib/Sema/SemaExceptionSpec.cpp
index 41abd49627b..51d6acebada 100644
--- a/clang/lib/Sema/SemaExceptionSpec.cpp
+++ b/clang/lib/Sema/SemaExceptionSpec.cpp
@@ -167,13 +167,13 @@ Sema::ResolveExceptionSpec(SourceLocation Loc, const FunctionProtoType *FPT) {
void
Sema::UpdateExceptionSpec(FunctionDecl *FD,
const FunctionProtoType::ExceptionSpecInfo &ESI) {
- for (auto *Redecl : FD->redecls())
- Context.adjustExceptionSpec(cast<FunctionDecl>(Redecl), ESI);
-
// If we've fully resolved the exception specification, notify listeners.
if (!isUnresolvedExceptionSpec(ESI.Type))
if (auto *Listener = getASTMutationListener())
Listener->ResolvedExceptionSpec(FD);
+
+ for (auto *Redecl : FD->redecls())
+ Context.adjustExceptionSpec(cast<FunctionDecl>(Redecl), ESI);
}
/// Determine whether a function has an implicitly-generated exception
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..a26f251cbdb 100644
--- a/clang/lib/Serialization/ASTReader.cpp
+++ b/clang/lib/Serialization/ASTReader.cpp
@@ -1,4 +1,4 @@
-//===--- ASTReader.cpp - AST File Reader ----------------------------------===//
+//===-- ASTReader.cpp - AST File Reader ----------------------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -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);
@@ -8618,6 +8617,13 @@ void ASTReader::FinishedDeserializing() {
--NumCurrentElementsDeserializing;
if (NumCurrentElementsDeserializing == 0) {
+ // Propagate exception specification updates along redeclaration chains.
+ for (auto Update : PendingExceptionSpecUpdates) {
+ auto *FPT = Update.second->getType()->castAs<FunctionProtoType>();
+ SemaObj->UpdateExceptionSpec(Update.second,
+ FPT->getExtProtoInfo().ExceptionSpec);
+ }
+
diagnoseOdrViolations();
// We are not in recursive loading, so it's safe to pass the "interesting"
@@ -8628,7 +8634,15 @@ void ASTReader::FinishedDeserializing() {
}
void ASTReader::pushExternalDeclIntoScope(NamedDecl *D, DeclarationName Name) {
- D = D->getMostRecentDecl();
+ if (IdentifierInfo *II = Name.getAsIdentifierInfo()) {
+ // Remove any fake results before adding any real ones.
+ auto It = PendingFakeLookupResults.find(II);
+ if (It != PendingFakeLookupResults.end()) {
+ for (auto *ND : PendingFakeLookupResults[II])
+ SemaObj->IdResolver.RemoveDecl(ND);
+ PendingFakeLookupResults.erase(It);
+ }
+ }
if (SemaObj->IdResolver.tryAddTopLevelDecl(D, Name) && SemaObj->TUScope) {
SemaObj->TUScope->AddDecl(D);
diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp
index 83882a83693..5c6820f4834 100644
--- a/clang/lib/Serialization/ASTReaderDecl.cpp
+++ b/clang/lib/Serialization/ASTReaderDecl.cpp
@@ -228,9 +228,11 @@ namespace clang {
template <typename DeclT>
static void attachPreviousDeclImpl(ASTReader &Reader,
- Redeclarable<DeclT> *D, Decl *Previous);
+ Redeclarable<DeclT> *D, Decl *Previous,
+ Decl *Canon);
static void attachPreviousDeclImpl(ASTReader &Reader, ...);
- static void attachPreviousDecl(ASTReader &Reader, Decl *D, Decl *Previous);
+ static void attachPreviousDecl(ASTReader &Reader, Decl *D, Decl *Previous,
+ Decl *Canon);
template <typename DeclT>
static void attachLatestDeclImpl(Redeclarable<DeclT> *D, Decl *Latest);
@@ -2621,8 +2623,11 @@ ASTDeclReader::FindExistingResult::~FindExistingResult() {
if (needsAnonymousDeclarationNumber(New)) {
setAnonymousDeclForMerging(Reader, New->getLexicalDeclContext(),
AnonymousDeclNumber, New);
- } else if (DC->isTranslationUnit() && Reader.SemaObj) {
- Reader.SemaObj->IdResolver.tryAddTopLevelDecl(New, Name);
+ } else if (DC->isTranslationUnit() && Reader.SemaObj &&
+ !Reader.getContext().getLangOpts().CPlusPlus) {
+ if (Reader.SemaObj->IdResolver.tryAddTopLevelDecl(New, Name))
+ Reader.PendingFakeLookupResults[Name.getAsIdentifierInfo()]
+ .push_back(New);
} else if (DeclContext *MergeDC = getPrimaryContextForMerging(Reader, DC)) {
// Add the declaration to its redeclaration context so later merging
// lookups will find it.
@@ -2727,7 +2732,8 @@ ASTDeclReader::FindExistingResult ASTDeclReader::findExisting(NamedDecl *D) {
if (isSameEntity(Existing, D))
return FindExistingResult(Reader, D, Existing, AnonymousDeclNumber,
TypedefNameForLinkage);
- } else if (DC->isTranslationUnit() && Reader.SemaObj) {
+ } else if (DC->isTranslationUnit() && Reader.SemaObj &&
+ !Reader.getContext().getLangOpts().CPlusPlus) {
IdentifierResolver &IdResolver = Reader.SemaObj->IdResolver;
// Temporarily consider the identifier to be up-to-date. We don't want to
@@ -2816,14 +2822,14 @@ Decl *ASTReader::getMostRecentExistingDecl(Decl *D) {
template<typename DeclT>
void ASTDeclReader::attachPreviousDeclImpl(ASTReader &Reader,
Redeclarable<DeclT> *D,
- Decl *Previous) {
+ Decl *Previous, Decl *Canon) {
D->RedeclLink.setPrevious(cast<DeclT>(Previous));
}
namespace clang {
template<>
void ASTDeclReader::attachPreviousDeclImpl(ASTReader &Reader,
Redeclarable<FunctionDecl> *D,
- Decl *Previous) {
+ Decl *Previous, Decl *Canon) {
FunctionDecl *FD = static_cast<FunctionDecl*>(D);
FunctionDecl *PrevFD = cast<FunctionDecl>(Previous);
@@ -2850,25 +2856,17 @@ void ASTDeclReader::attachPreviousDeclImpl(ASTReader &Reader,
FD->IsInline = true;
}
- // If this declaration has an unresolved exception specification but the
- // previous declaration had a resolved one, resolve the exception
- // specification now. If this declaration has a resolved exception
- // specification but the previous declarations did not, apply our exception
- // specification to all prior ones now.
+ // If we need to propagate an exception specification along the redecl
+ // chain, make a note of that so that we can do so later.
auto *FPT = FD->getType()->getAs<FunctionProtoType>();
auto *PrevFPT = PrevFD->getType()->getAs<FunctionProtoType>();
if (FPT && PrevFPT) {
- bool WasUnresolved = isUnresolvedExceptionSpec(FPT->getExceptionSpecType());
- bool IsUnresolved = isUnresolvedExceptionSpec(PrevFPT->getExceptionSpecType());
- if (WasUnresolved && !IsUnresolved) {
- Reader.Context.adjustExceptionSpec(
- FD, PrevFPT->getExtProtoInfo().ExceptionSpec);
- } else if (!WasUnresolved && IsUnresolved) {
- FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo();
- for (FunctionDecl *PrevFDToUpdate = PrevFD; PrevFDToUpdate;
- PrevFDToUpdate = PrevFDToUpdate->getPreviousDecl())
- Reader.Context.adjustExceptionSpec(PrevFDToUpdate, EPI.ExceptionSpec);
- }
+ bool IsUnresolved = isUnresolvedExceptionSpec(FPT->getExceptionSpecType());
+ bool WasUnresolved =
+ isUnresolvedExceptionSpec(PrevFPT->getExceptionSpecType());
+ if (IsUnresolved != WasUnresolved)
+ Reader.PendingExceptionSpecUpdates.insert(
+ std::make_pair(Canon, IsUnresolved ? PrevFD : FD));
}
}
}
@@ -2877,14 +2875,14 @@ void ASTDeclReader::attachPreviousDeclImpl(ASTReader &Reader, ...) {
}
void ASTDeclReader::attachPreviousDecl(ASTReader &Reader, Decl *D,
- Decl *Previous) {
+ Decl *Previous, Decl *Canon) {
assert(D && Previous);
switch (D->getKind()) {
#define ABSTRACT_DECL(TYPE)
-#define DECL(TYPE, BASE) \
- case Decl::TYPE: \
- attachPreviousDeclImpl(Reader, cast<TYPE##Decl>(D), Previous); \
+#define DECL(TYPE, BASE) \
+ case Decl::TYPE: \
+ attachPreviousDeclImpl(Reader, cast<TYPE##Decl>(D), Previous, Canon); \
break;
#include "clang/AST/DeclNodes.inc"
}
@@ -3388,7 +3386,7 @@ void ASTReader::loadPendingDeclChain(Decl *CanonDecl) {
if (Chain[I] == CanonDecl)
continue;
- ASTDeclReader::attachPreviousDecl(*this, Chain[I], MostRecent);
+ ASTDeclReader::attachPreviousDecl(*this, Chain[I], MostRecent, CanonDecl);
MostRecent = Chain[I];
}
ASTDeclReader::attachLatestDecl(CanonDecl, MostRecent);
@@ -3732,23 +3730,24 @@ void ASTDeclReader::UpdateDecl(Decl *D, ModuleFile &ModuleFile,
}
case UPD_CXX_RESOLVED_EXCEPTION_SPEC: {
- // FIXME: This doesn't send the right notifications if there are
- // ASTMutationListeners other than an ASTWriter.
FunctionProtoType::ExceptionSpecInfo ESI;
SmallVector<QualType, 8> ExceptionStorage;
Reader.readExceptionSpec(ModuleFile, ExceptionStorage, ESI, Record, Idx);
- for (auto *Redecl : merged_redecls(D)) {
- auto *FD = cast<FunctionDecl>(Redecl);
- auto *FPT = FD->getType()->castAs<FunctionProtoType>();
- if (!isUnresolvedExceptionSpec(FPT->getExceptionSpecType())) {
- // AST invariant: if any exception spec in the redecl chain is
- // resolved, all are resolved. We don't need to go any further.
- // FIXME: If the exception spec is resolved, check that it matches.
- break;
- }
+
+ // Update this declaration's exception specification, if needed.
+ auto *FD = cast<FunctionDecl>(D);
+ auto *FPT = FD->getType()->castAs<FunctionProtoType>();
+ // FIXME: If the exception specification is already present, check that it
+ // matches.
+ if (isUnresolvedExceptionSpec(FPT->getExceptionSpecType())) {
FD->setType(Reader.Context.getFunctionType(
FPT->getReturnType(), FPT->getParamTypes(),
FPT->getExtProtoInfo().withExceptionSpec(ESI)));
+
+ // When we get to the end of deserializing, see if there are other decls
+ // that we need to propagate this exception specification onto.
+ Reader.PendingExceptionSpecUpdates.insert(
+ std::make_pair(FD->getCanonicalDecl(), FD));
}
break;
}
diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp
index a8e92b8151c..e992685a83d 100644
--- a/clang/lib/Serialization/ASTWriter.cpp
+++ b/clang/lib/Serialization/ASTWriter.cpp
@@ -3731,7 +3731,9 @@ void ASTWriter::AddUpdatedDeclContext(const DeclContext *DC) {
uint32_t
ASTWriter::GenerateNameLookupTable(const DeclContext *DC,
llvm::SmallVectorImpl<char> &LookupTable) {
- assert(!DC->LookupPtr.getInt() && "must call buildLookups first");
+ assert(!DC->HasLazyLocalLexicalLookups &&
+ !DC->HasLazyExternalLexicalLookups &&
+ "must call buildLookups first");
llvm::OnDiskChainedHashTableGenerator<ASTDeclContextNameLookupTrait>
Generator;
@@ -5804,37 +5806,36 @@ void ASTWriter::AddedCXXTemplateSpecialization(const FunctionTemplateDecl *TD,
}
void ASTWriter::ResolvedExceptionSpec(const FunctionDecl *FD) {
- assert(!WritingAST && "Already writing the AST!");
- FD = FD->getCanonicalDecl();
- if (!FD->isFromASTFile())
- return; // Not a function declared in PCH and defined outside.
-
- DeclUpdates[FD].push_back(UPD_CXX_RESOLVED_EXCEPTION_SPEC);
+ assert(!DoneWritingDeclsAndTypes && "Already done writing updates!");
+ if (!Chain) return;
+ Chain->forEachFormerlyCanonicalImportedDecl(FD, [&](const Decl *D) {
+ // If we don't already know the exception specification for this redecl
+ // chain, add an update record for it.
+ if (isUnresolvedExceptionSpec(cast<FunctionDecl>(D)
+ ->getType()
+ ->castAs<FunctionProtoType>()
+ ->getExceptionSpecType()))
+ DeclUpdates[D].push_back(UPD_CXX_RESOLVED_EXCEPTION_SPEC);
+ });
}
void ASTWriter::DeducedReturnType(const FunctionDecl *FD, QualType ReturnType) {
assert(!WritingAST && "Already writing the AST!");
- FD = FD->getCanonicalDecl();
- if (!FD->isFromASTFile())
- return; // Not a function declared in PCH and defined outside.
-
- DeclUpdates[FD].push_back(DeclUpdate(UPD_CXX_DEDUCED_RETURN_TYPE, ReturnType));
+ if (!Chain) return;
+ Chain->forEachFormerlyCanonicalImportedDecl(FD, [&](const Decl *D) {
+ DeclUpdates[D].push_back(
+ DeclUpdate(UPD_CXX_DEDUCED_RETURN_TYPE, ReturnType));
+ });
}
void ASTWriter::ResolvedOperatorDelete(const CXXDestructorDecl *DD,
const FunctionDecl *Delete) {
assert(!WritingAST && "Already writing the AST!");
assert(Delete && "Not given an operator delete");
- for (auto *D : DD->redecls()) {
- if (D->isFromASTFile()) {
- // We added an operator delete that some imported destructor didn't
- // know about. Add an update record to let importers of us and that
- // declaration know about it.
- DeclUpdates[DD].push_back(
- DeclUpdate(UPD_CXX_RESOLVED_DTOR_DELETE, Delete));
- return;
- }
- }
+ if (!Chain) return;
+ Chain->forEachFormerlyCanonicalImportedDecl(DD, [&](const Decl *D) {
+ DeclUpdates[D].push_back(DeclUpdate(UPD_CXX_RESOLVED_DTOR_DELETE, Delete));
+ });
}
void ASTWriter::CompletedImplicitDefinition(const FunctionDecl *D) {
@@ -5851,8 +5852,7 @@ void ASTWriter::FunctionDefinitionInstantiated(const FunctionDecl *D) {
if (!D->isFromASTFile())
return;
- DeclUpdates[D].push_back(
- DeclUpdate(UPD_CXX_ADDED_FUNCTION_DEFINITION));
+ DeclUpdates[D].push_back(DeclUpdate(UPD_CXX_ADDED_FUNCTION_DEFINITION));
}
void ASTWriter::StaticDataMemberInstantiated(const VarDecl *D) {
OpenPOWER on IntegriCloud