summaryrefslogtreecommitdiffstats
path: root/clang/lib/Serialization/ASTReader.cpp
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2015-08-06 04:23:48 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2015-08-06 04:23:48 +0000
commit0f4e2c4d0f46b5edb4159b2d982327475b797efe (patch)
treec893a8277ae403c41609130361a3d4d2fe141a6c /clang/lib/Serialization/ASTReader.cpp
parent9b000812a44316016abe214ae98212b3cdd079fc (diff)
downloadbcm5719-llvm-0f4e2c4d0f46b5edb4159b2d982327475b797efe.tar.gz
bcm5719-llvm-0f4e2c4d0f46b5edb4159b2d982327475b797efe.zip
[modules] Defer setting up the lookup table for a DeclContext until we can
determine the primary context, rather than sometimes registering the lookup table on the wrong context. This exposed a couple of bugs: * the odr violation check didn't deal properly with mergeable declarations if the declaration retained by name lookup wasn't in the canonical definition of the class * the (broken) RewriteDecl mechanism would emit two name lookup tables for the same DeclContext into the same module file (one as part of the rewritten declaration and one as a visible update for the old declaration) These are both fixed too. llvm-svn: 244192
Diffstat (limited to 'clang/lib/Serialization/ASTReader.cpp')
-rw-r--r--clang/lib/Serialization/ASTReader.cpp143
1 files changed, 69 insertions, 74 deletions
diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp
index abc91e771ec..41294a82b26 100644
--- a/clang/lib/Serialization/ASTReader.cpp
+++ b/clang/lib/Serialization/ASTReader.cpp
@@ -955,48 +955,54 @@ ASTDeclContextNameLookupTrait::ReadData(internal_key_type,
return std::make_pair(Start, Start + NumDecls);
}
-bool ASTReader::ReadDeclContextStorage(ModuleFile &M,
- BitstreamCursor &Cursor,
- const std::pair<uint64_t, uint64_t> &Offsets,
- DeclContextInfo &Info) {
- SavedStreamPosition SavedPosition(Cursor);
- // First the lexical decls.
- if (Offsets.first != 0) {
- Cursor.JumpToBit(Offsets.first);
+bool ASTReader::ReadLexicalDeclContextStorage(ModuleFile &M,
+ BitstreamCursor &Cursor,
+ uint64_t Offset,
+ DeclContext *DC) {
+ assert(Offset != 0);
- RecordData Record;
- StringRef Blob;
- unsigned Code = Cursor.ReadCode();
- unsigned RecCode = Cursor.readRecord(Code, Record, &Blob);
- if (RecCode != DECL_CONTEXT_LEXICAL) {
- Error("Expected lexical block");
- return true;
- }
+ SavedStreamPosition SavedPosition(Cursor);
+ Cursor.JumpToBit(Offset);
- Info.LexicalDecls = llvm::makeArrayRef(
- reinterpret_cast<const KindDeclIDPair *>(Blob.data()),
- Blob.size() / sizeof(KindDeclIDPair));
+ RecordData Record;
+ StringRef Blob;
+ unsigned Code = Cursor.ReadCode();
+ unsigned RecCode = Cursor.readRecord(Code, Record, &Blob);
+ if (RecCode != DECL_CONTEXT_LEXICAL) {
+ Error("Expected lexical block");
+ return true;
}
- // Now the lookup table.
- if (Offsets.second != 0) {
- Cursor.JumpToBit(Offsets.second);
+ M.DeclContextInfos[DC].LexicalDecls = llvm::makeArrayRef(
+ reinterpret_cast<const KindDeclIDPair *>(Blob.data()),
+ Blob.size() / sizeof(KindDeclIDPair));
+ DC->setHasExternalLexicalStorage(true);
+ return false;
+}
- RecordData Record;
- StringRef Blob;
- unsigned Code = Cursor.ReadCode();
- unsigned RecCode = Cursor.readRecord(Code, Record, &Blob);
- if (RecCode != DECL_CONTEXT_VISIBLE) {
- Error("Expected visible lookup table block");
- return true;
- }
- Info.NameLookupTableData = ASTDeclContextNameLookupTable::Create(
- (const unsigned char *)Blob.data() + Record[0],
- (const unsigned char *)Blob.data() + sizeof(uint32_t),
- (const unsigned char *)Blob.data(),
- ASTDeclContextNameLookupTrait(*this, M));
+bool ASTReader::ReadVisibleDeclContextStorage(ModuleFile &M,
+ BitstreamCursor &Cursor,
+ uint64_t Offset,
+ DeclID ID) {
+ assert(Offset != 0);
+
+ SavedStreamPosition SavedPosition(Cursor);
+ Cursor.JumpToBit(Offset);
+
+ RecordData Record;
+ StringRef Blob;
+ unsigned Code = Cursor.ReadCode();
+ unsigned RecCode = Cursor.readRecord(Code, Record, &Blob);
+ if (RecCode != DECL_CONTEXT_VISIBLE) {
+ Error("Expected visible lookup table block");
+ return true;
}
+ // We can't safely determine the primary context yet, so delay attaching the
+ // lookup table until we're done with recursive deserialization.
+ unsigned BucketOffset = Record[0];
+ PendingVisibleUpdates[ID].push_back(PendingVisibleUpdate{
+ &M, (const unsigned char *)Blob.data(), BucketOffset});
return false;
}
@@ -2503,20 +2509,14 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
case UPDATE_VISIBLE: {
unsigned Idx = 0;
serialization::DeclID ID = ReadDeclID(F, Record, Idx);
- ASTDeclContextNameLookupTable *Table =
- ASTDeclContextNameLookupTable::Create(
- (const unsigned char *)Blob.data() + Record[Idx++],
- (const unsigned char *)Blob.data() + sizeof(uint32_t),
- (const unsigned char *)Blob.data(),
- ASTDeclContextNameLookupTrait(*this, F));
- if (Decl *D = GetExistingDecl(ID)) {
- auto *DC = cast<DeclContext>(D);
- DC->getPrimaryContext()->setHasExternalVisibleStorage(true);
- auto *&LookupTable = F.DeclContextInfos[DC].NameLookupTableData;
- delete LookupTable;
- LookupTable = Table;
- } else
- PendingVisibleUpdates[ID].push_back(std::make_pair(Table, &F));
+ auto *Data = (const unsigned char*)Blob.data();
+ unsigned BucketOffset = Record[Idx++];
+ PendingVisibleUpdates[ID].push_back(
+ PendingVisibleUpdate{&F, Data, BucketOffset});
+ // If we've already loaded the decl, perform the updates when we finish
+ // loading this block.
+ if (Decl *D = GetExistingDecl(ID))
+ PendingUpdateRecords.push_back(std::make_pair(ID, D));
break;
}
@@ -8331,21 +8331,26 @@ void ASTReader::diagnoseOdrViolations() {
if (Found)
continue;
+ // Quick check failed, time to do the slow thing. Note, we can't just
+ // look up the name of D in CanonDef here, because the member that is
+ // in CanonDef might not be found by name lookup (it might have been
+ // replaced by a more recent declaration in the lookup table), and we
+ // can't necessarily find it in the redeclaration chain because it might
+ // be merely mergeable, not redeclarable.
llvm::SmallVector<const NamedDecl*, 4> Candidates;
- DeclContext::lookup_result R = CanonDef->lookup(D->getDeclName());
- for (DeclContext::lookup_iterator I = R.begin(), E = R.end();
- !Found && I != E; ++I) {
- for (auto RI : (*I)->redecls()) {
- if (RI->getLexicalDeclContext() == CanonDef) {
- // This declaration is present in the canonical definition. If it's
- // in the same redecl chain, it's the one we're looking for.
- if (RI->getCanonicalDecl() == DCanon)
- Found = true;
- else
- Candidates.push_back(cast<NamedDecl>(RI));
- break;
- }
+ for (auto *CanonMember : CanonDef->decls()) {
+ if (CanonMember->getCanonicalDecl() == DCanon) {
+ // This can happen if the declaration is merely mergeable and not
+ // actually redeclarable (we looked for redeclarations earlier).
+ //
+ // FIXME: We should be able to detect this more efficiently, without
+ // pulling in all of the members of CanonDef.
+ Found = true;
+ break;
}
+ if (auto *ND = dyn_cast<NamedDecl>(CanonMember))
+ if (ND->getDeclName() == D->getDeclName())
+ Candidates.push_back(ND);
}
if (!Found) {
@@ -8454,11 +8459,11 @@ void ASTReader::FinishedDeserializing() {
}
}
- diagnoseOdrViolations();
-
if (ReadTimer)
ReadTimer->stopTimer();
+ diagnoseOdrViolations();
+
// We are not in recursive loading, so it's safe to pass the "interesting"
// decls to the consumer.
if (Consumer)
@@ -8527,14 +8532,4 @@ ASTReader::ASTReader(Preprocessor &PP, ASTContext &Context,
ASTReader::~ASTReader() {
if (OwnsDeserializationListener)
delete DeserializationListener;
-
- for (DeclContextVisibleUpdatesPending::iterator
- I = PendingVisibleUpdates.begin(),
- E = PendingVisibleUpdates.end();
- I != E; ++I) {
- for (DeclContextVisibleUpdates::iterator J = I->second.begin(),
- F = I->second.end();
- J != F; ++J)
- delete J->first;
- }
}
OpenPOWER on IntegriCloud