diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2015-08-06 04:23:48 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2015-08-06 04:23:48 +0000 |
commit | 0f4e2c4d0f46b5edb4159b2d982327475b797efe (patch) | |
tree | c893a8277ae403c41609130361a3d4d2fe141a6c /clang/lib/Serialization/ASTReaderDecl.cpp | |
parent | 9b000812a44316016abe214ae98212b3cdd079fc (diff) | |
download | bcm5719-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/ASTReaderDecl.cpp')
-rw-r--r-- | clang/lib/Serialization/ASTReaderDecl.cpp | 72 |
1 files changed, 33 insertions, 39 deletions
diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp index 06f7acaf785..0585234f150 100644 --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -3339,37 +3339,13 @@ Decl *ASTReader::ReadDeclRecord(DeclID ID) { // If this declaration is also a declaration context, get the // offsets for its tables of lexical and visible declarations. if (DeclContext *DC = dyn_cast<DeclContext>(D)) { - // FIXME: This should really be - // DeclContext *LookupDC = DC->getPrimaryContext(); - // but that can walk the redeclaration chain, which might not work yet. - DeclContext *LookupDC = DC; - if (isa<NamespaceDecl>(DC)) - LookupDC = DC->getPrimaryContext(); std::pair<uint64_t, uint64_t> Offsets = Reader.VisitDeclContext(DC); - if (Offsets.first || Offsets.second) { - if (Offsets.first != 0) - DC->setHasExternalLexicalStorage(true); - if (Offsets.second != 0) - LookupDC->setHasExternalVisibleStorage(true); - if (ReadDeclContextStorage(*Loc.F, DeclsCursor, Offsets, - Loc.F->DeclContextInfos[DC])) - return nullptr; - } - - // Now add the pending visible updates for this decl context, if it has any. - DeclContextVisibleUpdatesPending::iterator I = - PendingVisibleUpdates.find(ID); - if (I != PendingVisibleUpdates.end()) { - // There are updates. This means the context has external visible - // storage, even if the original stored version didn't. - LookupDC->setHasExternalVisibleStorage(true); - for (const auto &Update : I->second) { - DeclContextInfo &Info = Update.second->DeclContextInfos[DC]; - delete Info.NameLookupTableData; - Info.NameLookupTableData = Update.first; - } - PendingVisibleUpdates.erase(I); - } + if (Offsets.first && + ReadLexicalDeclContextStorage(*Loc.F, DeclsCursor, Offsets.first, DC)) + return nullptr; + if (Offsets.second && + ReadVisibleDeclContextStorage(*Loc.F, DeclsCursor, Offsets.second, ID)) + return nullptr; } assert(Idx == Record.size()); @@ -3392,17 +3368,37 @@ Decl *ASTReader::ReadDeclRecord(DeclID ID) { } void ASTReader::loadDeclUpdateRecords(serialization::DeclID ID, Decl *D) { + // Load the pending visible updates for this decl context, if it has any. + auto I = PendingVisibleUpdates.find(ID); + if (I != PendingVisibleUpdates.end()) { + auto VisibleUpdates = std::move(I->second); + PendingVisibleUpdates.erase(I); + + auto *DC = cast<DeclContext>(D)->getPrimaryContext(); + for (const PendingVisibleUpdate &Update : VisibleUpdates) { + auto *&LookupTable = Update.Mod->DeclContextInfos[DC].NameLookupTableData; + assert(!LookupTable && "multiple lookup tables for DC in module"); + LookupTable = reader::ASTDeclContextNameLookupTable::Create( + Update.Data + Update.BucketOffset, + Update.Data + sizeof(uint32_t), + Update.Data, + reader::ASTDeclContextNameLookupTrait(*this, *Update.Mod)); + } + DC->setHasExternalVisibleStorage(true); + } + // The declaration may have been modified by files later in the chain. // If this is the case, read the record containing the updates from each file // and pass it to ASTDeclReader to make the modifications. DeclUpdateOffsetsMap::iterator UpdI = DeclUpdateOffsets.find(ID); if (UpdI != DeclUpdateOffsets.end()) { - FileOffsetsTy &UpdateOffsets = UpdI->second; + auto UpdateOffsets = std::move(UpdI->second); + DeclUpdateOffsets.erase(UpdI); + bool WasInteresting = isConsumerInterestedIn(D, false); - for (FileOffsetsTy::iterator - I = UpdateOffsets.begin(), E = UpdateOffsets.end(); I != E; ++I) { - ModuleFile *F = I->first; - uint64_t Offset = I->second; + for (auto &FileAndOffset : UpdateOffsets) { + ModuleFile *F = FileAndOffset.first; + uint64_t Offset = FileAndOffset.second; llvm::BitstreamCursor &Cursor = F->DeclsCursor; SavedStreamPosition SavedPosition(Cursor); Cursor.JumpToBit(Offset); @@ -3817,10 +3813,8 @@ void ASTDeclReader::UpdateDecl(Decl *D, ModuleFile &ModuleFile, // Visible update is handled separately. uint64_t LexicalOffset = Record[Idx++]; if (!HadRealDefinition && LexicalOffset) { - RD->setHasExternalLexicalStorage(true); - Reader.ReadDeclContextStorage(ModuleFile, ModuleFile.DeclsCursor, - std::make_pair(LexicalOffset, 0), - ModuleFile.DeclContextInfos[RD]); + Reader.ReadLexicalDeclContextStorage(ModuleFile, ModuleFile.DeclsCursor, + LexicalOffset, RD); Reader.PendingFakeDefinitionData.erase(OldDD); } |