aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2012-10-11 00:46:49 +0000
committerDouglas Gregor <dgregor@apple.com>2012-10-11 00:46:49 +0000
commit6c6c54a59a6e7dbe63ff6a9bbab76f6e0c7c8462 (patch)
treecea015c280d1666e0a42bdb2f208d8829a5f4cc9 /lib
parent8b03277b0bc18ab73be11b6067474d515fdad271 (diff)
Deserialize macro history when we deserialize an identifier that has
macro history. When deserializing macro history, we arrange history such that the macros that have definitions (that haven't been #undef'd) and are visible come at the beginning of the list, which is what the preprocessor and other clients of Preprocessor::getMacroInfo() expect. If additional macro definitions become visible later, they'll be moved toward the front of the list. Note that it's possible to have ambiguities, but we don't diagnose them yet. There is a partially-implemented design decision here that, if a particular identifier has been defined or #undef'd within the translation unit, that definition (or #undef) hides any macro definitions that come from imported modules. There's still a little work to do to ensure that the right #undef'ing happens. Additionally, we'll need to scope the update records for #undefs, so they only kick in when the submodule containing that update record becomes visible. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@165682 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r--lib/Lex/MacroInfo.cpp6
-rw-r--r--lib/Lex/PPMacroExpansion.cpp101
-rw-r--r--lib/Serialization/ASTReader.cpp135
-rw-r--r--lib/Serialization/ASTWriter.cpp21
4 files changed, 173 insertions, 90 deletions
diff --git a/lib/Lex/MacroInfo.cpp b/lib/Lex/MacroInfo.cpp
index ffe31f24d3..7e538fabf4 100644
--- a/lib/Lex/MacroInfo.cpp
+++ b/lib/Lex/MacroInfo.cpp
@@ -31,7 +31,8 @@ MacroInfo::MacroInfo(SourceLocation DefLoc)
IsUsed(false),
IsAllowRedefinitionsWithoutWarning(false),
IsWarnIfUnused(false),
- IsPublic(true) {
+ IsPublic(true),
+ IsHidden(false) {
}
MacroInfo::MacroInfo(const MacroInfo &MI, llvm::BumpPtrAllocator &PPAllocator)
@@ -54,7 +55,8 @@ MacroInfo::MacroInfo(const MacroInfo &MI, llvm::BumpPtrAllocator &PPAllocator)
IsUsed(MI.IsUsed),
IsAllowRedefinitionsWithoutWarning(MI.IsAllowRedefinitionsWithoutWarning),
IsWarnIfUnused(MI.IsWarnIfUnused),
- IsPublic(MI.IsPublic) {
+ IsPublic(MI.IsPublic),
+ IsHidden(MI.IsHidden) {
setArgumentList(MI.ArgumentList, MI.NumArguments, PPAllocator);
}
diff --git a/lib/Lex/PPMacroExpansion.cpp b/lib/Lex/PPMacroExpansion.cpp
index 1ef534daa7..013178c555 100644
--- a/lib/Lex/PPMacroExpansion.cpp
+++ b/lib/Lex/PPMacroExpansion.cpp
@@ -36,29 +36,106 @@ MacroInfo *Preprocessor::getMacroInfoHistory(IdentifierInfo *II) const {
assert(II->hadMacroDefinition() && "Identifier has not been not a macro!");
macro_iterator Pos = Macros.find(II);
- if (Pos == Macros.end()) {
- // Load this macro from the external source.
- getExternalSource()->LoadMacroDefinition(II);
- Pos = Macros.find(II);
- }
assert(Pos != Macros.end() && "Identifier macro info is missing!");
return Pos->second;
}
/// setMacroInfo - Specify a macro for this identifier.
///
-void Preprocessor::setMacroInfo(IdentifierInfo *II, MacroInfo *MI,
- bool LoadedFromAST) {
+void Preprocessor::setMacroInfo(IdentifierInfo *II, MacroInfo *MI) {
assert(MI && "MacroInfo should be non-zero!");
- assert((LoadedFromAST || MI->getUndefLoc().isInvalid()) &&
- "Undefined macros can only be registered when just LoadedFromAST");
- MI->setPreviousDefinition(Macros[II]);
- Macros[II] = MI;
+ assert(MI->getUndefLoc().isInvalid() &&
+ "Undefined macros cannot be registered");
+
+ MacroInfo *&StoredMI = Macros[II];
+ MI->setPreviousDefinition(StoredMI);
+ StoredMI = MI;
II->setHasMacroDefinition(MI->getUndefLoc().isInvalid());
- if (II->isFromAST() && !LoadedFromAST)
+ if (II->isFromAST())
II->setChangedSinceDeserialization();
}
+void Preprocessor::addLoadedMacroInfo(IdentifierInfo *II, MacroInfo *MI) {
+ assert(MI && "Missing macro?");
+ assert(MI->isFromAST() && "Macro is not from an AST?");
+ assert(!MI->getPreviousDefinition() && "Macro already in chain?");
+
+ MacroInfo *&StoredMI = Macros[II];
+
+ // Easy case: this is the first macro definition for this macro.
+ if (!StoredMI) {
+ StoredMI = MI;
+
+ if (MI->isDefined())
+ II->setHasMacroDefinition(true);
+ return;
+ }
+
+ // If this macro is a definition and this identifier has been neither
+ // defined nor undef'd in the current translation unit, add this macro
+ // to the end of the chain of definitions.
+ if (MI->isDefined() && StoredMI->isFromAST()) {
+ // Simple case: if this is the first actual definition, just put it at
+ // th beginning.
+ if (!StoredMI->isDefined()) {
+ MI->setPreviousDefinition(StoredMI);
+ StoredMI = MI;
+
+ II->setHasMacroDefinition(true);
+ return;
+ }
+
+ // Find the end of the definition chain.
+ MacroInfo *Prev = StoredMI;
+ MacroInfo *PrevPrev;
+ bool Ambiguous = false;
+ do {
+ // If the macros are not identical, we have an ambiguity.
+ if (!Prev->isIdenticalTo(*MI, *this))
+ Ambiguous = true;
+ } while ((PrevPrev = Prev->getPreviousDefinition()) &&
+ PrevPrev->isDefined());
+
+ // FIXME: Actually use the ambiguity information for something.
+
+ // Wire this macro information into the chain.
+ MI->setPreviousDefinition(Prev->getPreviousDefinition());
+ Prev->setPreviousDefinition(MI);
+ return;
+ }
+
+ // The macro is not a definition; put it at the end of the list.
+ // FIXME: Adding macro history is quadratic, but a hint could fix this.
+ MacroInfo *Prev = StoredMI;
+ while (Prev->getPreviousDefinition())
+ Prev = Prev->getPreviousDefinition();
+ Prev->setPreviousDefinition(MI);
+}
+
+void Preprocessor::makeLoadedMacroInfoVisible(IdentifierInfo *II,
+ MacroInfo *MI) {
+ assert(MI->isFromAST() && "Macro must be from the AST");
+ assert(MI->isDefined() && "Macro is not visible");
+
+ MacroInfo *&StoredMI = Macros[II];
+ if (StoredMI == MI) {
+ // Easy case: this is the first macro anyway.
+ II->setHasMacroDefinition(true);
+ return;
+ }
+
+ // Go find the macro and pull it out of the list.
+ // FIXME: Yes, this is O(N), and making a pile of macros visible would be
+ // quadratic.
+ MacroInfo *Prev = StoredMI;
+ while (Prev->getPreviousDefinition() != MI)
+ Prev = Prev->getPreviousDefinition();
+ Prev->setPreviousDefinition(MI->getPreviousDefinition());
+
+ // Add the macro back to the list.
+ addLoadedMacroInfo(II, MI);
+}
+
/// \brief Undefine a macro for this identifier.
void Preprocessor::clearMacroInfo(IdentifierInfo *II) {
assert(II->hasMacroDefinition() && "Macro is not defined!");
diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp
index 4e6673bedd..6e3eee9533 100644
--- a/lib/Serialization/ASTReader.cpp
+++ b/lib/Serialization/ASTReader.cpp
@@ -573,31 +573,13 @@ IdentifierInfo *ASTIdentifierLookupTrait::ReadData(const internal_key_type& k,
// If this identifier is a macro, deserialize the macro
// definition.
if (hadMacroDefinition) {
- // FIXME: Check for conflicts?
- uint32_t LocalID = ReadUnalignedLE32(d);
- unsigned LocalSubmoduleID = ReadUnalignedLE32(d);
-
- // Determine whether this macro definition should be visible now, or
- // whether it is in a hidden submodule.
- bool Visible = true;
- if (SubmoduleID GlobalSubmoduleID
- = Reader.getGlobalSubmoduleID(F, LocalSubmoduleID)) {
- if (Module *Owner = Reader.getSubmodule(GlobalSubmoduleID)) {
- if (Owner->NameVisibility == Module::Hidden) {
- // The owning module is not visible, and this macro definition should
- // not be, either.
- Visible = false;
-
- // Note that this macro definition was hidden because its owning
- // module is not yet visible.
- Reader.HiddenNamesMap[Owner].push_back(II);
- }
- }
+ SmallVector<MacroID, 4> MacroIDs;
+ while (uint32_t LocalID = ReadUnalignedLE32(d)) {
+ MacroIDs.push_back(Reader.getGlobalMacroID(F, LocalID));
+ DataLen -= 4;
}
-
- Reader.setIdentifierIsMacro(II, Reader.getGlobalMacroID(F, LocalID),
- Visible && hasMacroDefinition);
- DataLen -= 8;
+ DataLen -= 4;
+ Reader.setIdentifierIsMacro(II, MacroIDs);
}
Reader.SetIdentifierInfo(ID, II);
@@ -1322,7 +1304,8 @@ void ASTReader::ReadMacroRecord(ModuleFile &F, uint64_t Offset) {
if (MacrosLoaded[GlobalID - NUM_PREDEF_MACRO_IDS])
return;
- unsigned NextIndex = 2;
+ SubmoduleID GlobalSubmoduleID = getGlobalSubmoduleID(F, Record[2]);
+ unsigned NextIndex = 3;
SourceLocation Loc = ReadSourceLocation(F, Record, NextIndex);
MacroInfo *MI = PP.AllocateMacroInfo(Loc);
@@ -1360,6 +1343,7 @@ void ASTReader::ReadMacroRecord(ModuleFile &F, uint64_t Offset) {
DeserializationListener->MacroRead(GlobalID, MI);
// If an update record marked this as undefined, do so now.
+ // FIXME: Only if the submodule this update came from is visible?
MacroUpdatesMap::iterator Update = MacroUpdates.find(GlobalID);
if (Update != MacroUpdates.end()) {
if (MI->getUndefLoc().isInvalid()) {
@@ -1370,8 +1354,25 @@ void ASTReader::ReadMacroRecord(ModuleFile &F, uint64_t Offset) {
MacroUpdates.erase(Update);
}
+ // Determine whether this macro definition is visible.
+ bool Hidden = !MI->isPublic();
+ if (!Hidden && GlobalSubmoduleID) {
+ if (Module *Owner = getSubmodule(GlobalSubmoduleID)) {
+ if (Owner->NameVisibility == Module::Hidden) {
+ // The owning module is not visible, and this macro definition
+ // should not be, either.
+ Hidden = true;
+
+ // Note that this macro definition was hidden because its owning
+ // module is not yet visible.
+ HiddenNamesMap[Owner].push_back(HiddenName(II, MI));
+ }
+ }
+ }
+ MI->setHidden(Hidden);
+
// Finally, install the macro.
- PP.setMacroInfo(II, MI, /*LoadedFromAST=*/true);
+ PP.addLoadedMacroInfo(II, MI);
// Remember that we saw this macro last so that we add the tokens that
// form its body to it.
@@ -1480,21 +1481,16 @@ HeaderFileInfoTrait::ReadData(const internal_key_type, const unsigned char *d,
return HFI;
}
-void ASTReader::setIdentifierIsMacro(IdentifierInfo *II, MacroID ID,
- bool Visible) {
- if (Visible) {
- // Note that this identifier has a macro definition.
- II->setHasMacroDefinition(true);
- } else {
- II->setHadMacroDefinition(true);
- }
-
- // FIXME: This could end up overwriting a previously recording macro
- // definition here, which is not cool at all.
- UnreadMacroIDs[II] = ID;
+void ASTReader::setIdentifierIsMacro(IdentifierInfo *II, ArrayRef<MacroID> IDs){
+ II->setHadMacroDefinition(true);
+ assert(NumCurrentElementsDeserializing > 0 &&"Missing deserialization guard");
+ PendingMacroIDs[II].append(IDs.begin(), IDs.end());
}
void ASTReader::ReadDefinedMacros() {
+ // Note that we are loading defined macros.
+ Deserializing Macros(this);
+
for (ModuleReverseIterator I = ModuleMgr.rbegin(),
E = ModuleMgr.rend(); I != E; ++I) {
llvm::BitstreamCursor &MacroCursor = (*I)->MacroCursor;
@@ -1546,24 +1542,14 @@ void ASTReader::ReadDefinedMacros() {
}
}
}
-
- // Drain the unread macro-record offsets map.
- while (!UnreadMacroIDs.empty())
- LoadMacroDefinition(UnreadMacroIDs.begin());
}
-void ASTReader::LoadMacroDefinition(
- llvm::DenseMap<IdentifierInfo *, MacroID>::iterator Pos) {
- assert(Pos != UnreadMacroIDs.end() && "Unknown macro definition");
- uint64_t GlobalID = Pos->second;
- UnreadMacroIDs.erase(Pos);
- getMacro(GlobalID);
-}
-
-void ASTReader::LoadMacroDefinition(IdentifierInfo *II) {
- llvm::DenseMap<IdentifierInfo *, MacroID>::iterator Pos
- = UnreadMacroIDs.find(II);
- LoadMacroDefinition(Pos);
+void ASTReader::LoadMacroDefinition(PendingMacroIDsMap::iterator Pos) {
+ assert(Pos != PendingMacroIDs.end() && "Unknown macro definition");
+ SmallVector<MacroID, 2> GlobalIDs = Pos->second;
+ PendingMacroIDs.erase(Pos);
+ for (unsigned I = 0, N = GlobalIDs.size(); I != N; ++I)
+ getMacro(GlobalIDs[I]);
}
namespace {
@@ -1612,6 +1598,9 @@ namespace {
}
void ASTReader::updateOutOfDateIdentifier(IdentifierInfo &II) {
+ // Note that we are loading an identifier.
+ Deserializing AnIdentifier(this);
+
unsigned PriorGeneration = 0;
if (getContext().getLangOpts().Modules)
PriorGeneration = IdentifierGeneration[&II];
@@ -2620,22 +2609,17 @@ ASTReader::ASTReadResult ASTReader::validateFileEntries(ModuleFile &M) {
void ASTReader::makeNamesVisible(const HiddenNames &Names) {
for (unsigned I = 0, N = Names.size(); I != N; ++I) {
- if (Decl *D = Names[I].dyn_cast<Decl *>())
- D->Hidden = false;
- else {
- IdentifierInfo *II = Names[I].get<IdentifierInfo *>();
- // FIXME: Check if this works correctly with macro history.
- if (!II->hasMacroDefinition()) {
- // Make sure that this macro hasn't been #undef'd in the mean-time.
- llvm::DenseMap<IdentifierInfo*, MacroInfo*>::iterator Known
- = PP.Macros.find(II);
- if (Known == PP.Macros.end() ||
- Known->second->getUndefLoc().isInvalid()) {
- II->setHasMacroDefinition(true);
- if (DeserializationListener)
- DeserializationListener->MacroVisible(II);
- }
- }
+ if (Names[I].isDecl()) {
+ Names[I].getDecl()->Hidden = false;
+ continue;
+ }
+
+ std::pair<IdentifierInfo *, MacroInfo *> Macro = Names[I].getMacro();
+ Macro.second->setHidden(!Macro.second->isPublic());
+ if (Macro.second->isDefined()) {
+ PP.makeLoadedMacroInfoVisible(Macro.first, Macro.second);
+ if (DeserializationListener)
+ DeserializationListener->MacroVisible(Macro.first);
}
}
}
@@ -5418,6 +5402,9 @@ void ASTReader::InitializeSema(Sema &S) {
}
IdentifierInfo* ASTReader::get(const char *NameStart, const char *NameEnd) {
+ // Note that we are loading an identifier.
+ Deserializing AnIdentifier(this);
+
IdentifierLookupVisitor Visitor(StringRef(NameStart, NameEnd - NameStart),
/*PriorGeneration=*/0);
ModuleMgr.visit(IdentifierLookupVisitor::visit, &Visitor);
@@ -6516,7 +6503,8 @@ void ASTReader::ReadComments() {
}
void ASTReader::finishPendingActions() {
- while (!PendingIdentifierInfos.empty() || !PendingDeclChains.empty()) {
+ while (!PendingIdentifierInfos.empty() || !PendingDeclChains.empty() ||
+ !PendingMacroIDs.empty()) {
// If any identifiers with corresponding top-level declarations have
// been loaded, load those declarations now.
while (!PendingIdentifierInfos.empty()) {
@@ -6531,6 +6519,11 @@ void ASTReader::finishPendingActions() {
PendingDeclChainsKnown.erase(PendingDeclChains[I]);
}
PendingDeclChains.clear();
+
+ // Load any pending macro definitions.
+ // FIXME: Non-determinism here.
+ while (!PendingMacroIDs.empty())
+ LoadMacroDefinition(PendingMacroIDs.begin());
}
// If we deserialized any C++ or Objective-C class definitions, any
diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp
index 76eb1a1a8a..98e841cb2b 100644
--- a/lib/Serialization/ASTWriter.cpp
+++ b/lib/Serialization/ASTWriter.cpp
@@ -1744,6 +1744,7 @@ void ASTWriter::WritePreprocessor(const Preprocessor &PP, bool IsModule) {
AddIdentifierRef(Name, Record);
addMacroRef(MI, Record);
+ Record.push_back(inferSubmoduleIDFromLocation(MI->getDefinitionLoc()));
AddSourceLocation(MI->getDefinitionLoc(), Record);
AddSourceLocation(MI->getUndefLoc(), Record);
Record.push_back(MI->isUsed());
@@ -2587,8 +2588,14 @@ public:
if (isInterestingIdentifier(II, Macro)) {
DataLen += 2; // 2 bytes for builtin ID
DataLen += 2; // 2 bytes for flags
- if (hadMacroDefinition(II, Macro))
- DataLen += 8;
+ if (hadMacroDefinition(II, Macro)) {
+ for (MacroInfo *M = Macro; M; M = M->getPreviousDefinition()) {
+ if (Writer.getMacroRef(M) != 0)
+ DataLen += 4;
+ }
+
+ DataLen += 4;
+ }
for (IdentifierResolver::iterator D = IdResolver.begin(II),
DEnd = IdResolver.end();
@@ -2635,9 +2642,13 @@ public:
clang::io::Emit16(Out, Bits);
if (HadMacroDefinition) {
- clang::io::Emit32(Out, Writer.getMacroRef(Macro));
- clang::io::Emit32(Out,
- Writer.inferSubmoduleIDFromLocation(Macro->getDefinitionLoc()));
+ // Write all of the macro IDs associated with this identifier.
+ for (MacroInfo *M = Macro; M; M = M->getPreviousDefinition()) {
+ if (MacroID ID = Writer.getMacroRef(M))
+ clang::io::Emit32(Out, ID);
+ }
+
+ clang::io::Emit32(Out, 0);
}
// Emit the declaration IDs in reverse order, because the