If a visibility update record is found for a DeclContext after that Decl has

already been loaded, apply that update record to the Decl immediately, rather
than adding it to a pending list and never applying it.

llvm-svn: 203534
This commit is contained in:
Richard Smith 2014-03-11 03:10:46 +00:00
parent 1108cb3682
commit d91747980a
9 changed files with 42 additions and 25 deletions
clang
include/clang/Serialization
lib/Serialization
test/Modules

View File

@ -44,13 +44,21 @@ enum ModuleKind {
MK_MainFile ///< File is a PCH file treated as the actual main file. MK_MainFile ///< File is a PCH file treated as the actual main file.
}; };
/// A custom deleter for DeclContextInfo::NameLookupTableData, to allow
/// an incomplete type to be used there.
struct NameLookupTableDataDeleter {
void operator()(
OnDiskChainedHashTable<reader::ASTDeclContextNameLookupTrait> *Ptr) const;
};
/// \brief Information about the contents of a DeclContext. /// \brief Information about the contents of a DeclContext.
struct DeclContextInfo { struct DeclContextInfo {
DeclContextInfo() DeclContextInfo()
: NameLookupTableData(), LexicalDecls(), NumLexicalDecls() {} : NameLookupTableData(), LexicalDecls(), NumLexicalDecls() {}
OnDiskChainedHashTable<reader::ASTDeclContextNameLookupTrait> /// An ASTDeclContextNameLookupTable.
*NameLookupTableData; // an ASTDeclContextNameLookupTable. std::unique_ptr<OnDiskChainedHashTable<reader::ASTDeclContextNameLookupTrait>,
NameLookupTableDataDeleter> NameLookupTableData;
const KindDeclIDPair *LexicalDecls; const KindDeclIDPair *LexicalDecls;
unsigned NumLexicalDecls; unsigned NumLexicalDecls;
}; };

View File

@ -457,6 +457,11 @@ ASTReader::setDeserializationListener(ASTDeserializationListener *Listener) {
} }
void NameLookupTableDataDeleter::
operator()(ASTDeclContextNameLookupTable *Ptr) const {
delete Ptr;
}
unsigned ASTSelectorLookupTrait::ComputeHash(Selector Sel) { unsigned ASTSelectorLookupTrait::ComputeHash(Selector Sel) {
return serialization::ComputeHash(Sel); return serialization::ComputeHash(Sel);
@ -836,11 +841,10 @@ bool ASTReader::ReadDeclContextStorage(ModuleFile &M,
Error("Expected visible lookup table block"); Error("Expected visible lookup table block");
return true; return true;
} }
Info.NameLookupTableData Info.NameLookupTableData.reset(ASTDeclContextNameLookupTable::Create(
= ASTDeclContextNameLookupTable::Create(
(const unsigned char *)Blob.data() + Record[0], (const unsigned char *)Blob.data() + Record[0],
(const unsigned char *)Blob.data(), (const unsigned char *)Blob.data(),
ASTDeclContextNameLookupTrait(*this, M)); ASTDeclContextNameLookupTrait(*this, M)));
} }
return false; return false;
@ -2493,8 +2497,12 @@ bool ASTReader::ReadASTBlock(ModuleFile &F) {
ASTDeclContextNameLookupTrait(*this, F)); ASTDeclContextNameLookupTrait(*this, F));
if (ID == PREDEF_DECL_TRANSLATION_UNIT_ID) { // Is it the TU? if (ID == PREDEF_DECL_TRANSLATION_UNIT_ID) { // Is it the TU?
DeclContext *TU = Context.getTranslationUnitDecl(); DeclContext *TU = Context.getTranslationUnitDecl();
F.DeclContextInfos[TU].NameLookupTableData = Table; F.DeclContextInfos[TU].NameLookupTableData.reset(Table);
TU->setHasExternalVisibleStorage(true); TU->setHasExternalVisibleStorage(true);
} else if (Decl *D = DeclsLoaded[ID - NUM_PREDEF_DECL_IDS]) {
auto *DC = cast<DeclContext>(D);
DC->getPrimaryContext()->setHasExternalVisibleStorage(true);
F.DeclContextInfos[DC].NameLookupTableData.reset(Table);
} else } else
PendingVisibleUpdates[ID].push_back(std::make_pair(Table, &F)); PendingVisibleUpdates[ID].push_back(std::make_pair(Table, &F));
break; break;
@ -6078,7 +6086,7 @@ namespace {
return false; return false;
// Look for this name within this module. // Look for this name within this module.
ASTDeclContextNameLookupTable *LookupTable = const auto &LookupTable =
Info->second.NameLookupTableData; Info->second.NameLookupTableData;
ASTDeclContextNameLookupTable::iterator Pos ASTDeclContextNameLookupTable::iterator Pos
= LookupTable->find(This->Name); = LookupTable->find(This->Name);
@ -6208,7 +6216,7 @@ namespace {
if (!FoundInfo) if (!FoundInfo)
return false; return false;
ASTDeclContextNameLookupTable *LookupTable = const auto &LookupTable =
Info->second.NameLookupTableData; Info->second.NameLookupTableData;
bool FoundAnything = false; bool FoundAnything = false;
for (ASTDeclContextNameLookupTable::data_iterator for (ASTDeclContextNameLookupTable::data_iterator

View File

@ -2609,13 +2609,9 @@ Decl *ASTReader::ReadDeclRecord(DeclID ID) {
// There are updates. This means the context has external visible // There are updates. This means the context has external visible
// storage, even if the original stored version didn't. // storage, even if the original stored version didn't.
LookupDC->setHasExternalVisibleStorage(true); LookupDC->setHasExternalVisibleStorage(true);
DeclContextVisibleUpdates &U = I->second; for (const auto &Update : I->second)
for (DeclContextVisibleUpdates::iterator UI = U.begin(), UE = U.end(); Update.second->DeclContextInfos[DC].NameLookupTableData.reset(
UI != UE; ++UI) { Update.first);
DeclContextInfo &Info = UI->second->DeclContextInfos[DC];
delete Info.NameLookupTableData;
Info.NameLookupTableData = UI->first;
}
PendingVisibleUpdates.erase(I); PendingVisibleUpdates.erase(I);
} }
} }

View File

@ -45,13 +45,6 @@ ModuleFile::ModuleFile(ModuleKind Kind, unsigned Generation)
{} {}
ModuleFile::~ModuleFile() { ModuleFile::~ModuleFile() {
for (DeclContextInfosMap::iterator I = DeclContextInfos.begin(),
E = DeclContextInfos.end();
I != E; ++I) {
if (I->second.NameLookupTableData)
delete I->second.NameLookupTableData;
}
delete static_cast<ASTIdentifierLookupTable *>(IdentifierLookupTable); delete static_cast<ASTIdentifierLookupTable *>(IdentifierLookupTable);
delete static_cast<HeaderFileInfoLookupTable *>(HeaderFileInfoTable); delete static_cast<HeaderFileInfoLookupTable *>(HeaderFileInfoTable);
delete static_cast<ASTSelectorLookupTable *>(SelectorLookupTable); delete static_cast<ASTSelectorLookupTable *>(SelectorLookupTable);

View File

@ -0,0 +1 @@
namespace llvm {}

View File

@ -0,0 +1,2 @@
#include "a.h"
namespace llvm { void f(); }

View File

@ -0,0 +1 @@
module a { header "a.h" } module b { header "b.h" }

View File

@ -0,0 +1,8 @@
// RUN: rm -rf %t
// RUN: %clang_cc1 -fmodules -I %S/Inputs/update-after-load -verify -fmodules-cache-path=%t %s
// expected-no-diagnostics
#include "a.h"
namespace llvm {}
#include "b.h"
void llvm::f() {}