summaryrefslogtreecommitdiffstats
path: root/clang/lib/Serialization/ASTWriter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Serialization/ASTWriter.cpp')
-rw-r--r--clang/lib/Serialization/ASTWriter.cpp395
1 files changed, 135 insertions, 260 deletions
diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp
index b522dadb9dc..bdeeae0a51c 100644
--- a/clang/lib/Serialization/ASTWriter.cpp
+++ b/clang/lib/Serialization/ASTWriter.cpp
@@ -940,8 +940,9 @@ void ASTWriter::WriteBlockInfoBlock() {
// Preprocessor Block.
BLOCK(PREPROCESSOR_BLOCK);
RECORD(PP_MACRO_DIRECTIVE_HISTORY);
- RECORD(PP_MACRO_OBJECT_LIKE);
RECORD(PP_MACRO_FUNCTION_LIKE);
+ RECORD(PP_MACRO_OBJECT_LIKE);
+ RECORD(PP_MODULE_MACRO);
RECORD(PP_TOKEN);
// Decls and Types block.
@@ -1971,46 +1972,6 @@ void ASTWriter::WriteSourceManagerBlock(SourceManager &SourceMgr,
// Preprocessor Serialization
//===----------------------------------------------------------------------===//
-namespace {
-class ASTMacroTableTrait {
-public:
- typedef IdentID key_type;
- typedef key_type key_type_ref;
-
- struct Data {
- uint32_t MacroDirectivesOffset;
- };
-
- typedef Data data_type;
- typedef const data_type &data_type_ref;
- typedef unsigned hash_value_type;
- typedef unsigned offset_type;
-
- static hash_value_type ComputeHash(IdentID IdID) {
- return llvm::hash_value(IdID);
- }
-
- std::pair<unsigned,unsigned>
- static EmitKeyDataLength(raw_ostream& Out,
- key_type_ref Key, data_type_ref Data) {
- unsigned KeyLen = 4; // IdentID.
- unsigned DataLen = 4; // MacroDirectivesOffset.
- return std::make_pair(KeyLen, DataLen);
- }
-
- static void EmitKey(raw_ostream& Out, key_type_ref Key, unsigned KeyLen) {
- using namespace llvm::support;
- endian::Writer<little>(Out).write<uint32_t>(Key);
- }
-
- static void EmitData(raw_ostream& Out, key_type_ref Key, data_type_ref Data,
- unsigned) {
- using namespace llvm::support;
- endian::Writer<little>(Out).write<uint32_t>(Data.MacroDirectivesOffset);
- }
-};
-} // end anonymous namespace
-
static bool shouldIgnoreMacro(MacroDirective *MD, bool IsModule,
const Preprocessor &PP) {
if (MacroInfo *MI = MD->getMacroInfo())
@@ -2032,6 +1993,69 @@ static bool shouldIgnoreMacro(MacroDirective *MD, bool IsModule,
return false;
}
+static void addOverriddenSubmodules(ASTWriter &Writer, const Preprocessor &PP,
+ MacroDirective *MD,
+ SmallVectorImpl<uint64_t> &Result) {
+ assert(!isa<VisibilityMacroDirective>(MD) &&
+ "only #define and #undef can override");
+
+ if (MD->isImported()) {
+ auto ModIDs = MD->getOverriddenModules();
+ Result.insert(Result.end(), ModIDs.begin(), ModIDs.end());
+ return;
+ }
+
+ unsigned Start = Result.size();
+
+ SubmoduleID ModID = Writer.inferSubmoduleIDFromLocation(MD->getLocation());
+ for (MD = MD->getPrevious(); MD; MD = MD->getPrevious()) {
+ if (shouldIgnoreMacro(MD, /*IsModule*/true, PP))
+ break;
+
+ // If this is a definition from a submodule import, that submodule's
+ // definition is overridden by the definition or undefinition that we
+ // started with.
+ if (MD->isImported()) {
+ if (auto *DefMD = dyn_cast<DefMacroDirective>(MD)) {
+ SubmoduleID DefModuleID = DefMD->getInfo()->getOwningModuleID();
+ assert(DefModuleID && "imported macro has no owning module");
+ Result.push_back(DefModuleID);
+ } else if (auto *UndefMD = dyn_cast<UndefMacroDirective>(MD)) {
+ // If we override a #undef, we override anything that #undef overrides.
+ // We don't need to override it, since an active #undef doesn't affect
+ // the meaning of a macro.
+ // FIXME: Overriding the #undef directly might be simpler.
+ auto Overrides = UndefMD->getOverriddenModules();
+ Result.insert(Result.end(), Overrides.begin(), Overrides.end());
+ }
+ }
+
+ // Stop once we leave the original macro's submodule.
+ //
+ // Either this submodule #included another submodule of the same
+ // module or it just happened to be built after the other module.
+ // In the former case, we override the submodule's macro.
+ //
+ // FIXME: In the latter case, we shouldn't do so, but we can't tell
+ // these cases apart.
+ //
+ // FIXME: We can leave this submodule and re-enter it if it #includes a
+ // header within a different submodule of the same module. In such cases
+ // the overrides list will be incomplete.
+ SubmoduleID DirectiveModuleID =
+ Writer.inferSubmoduleIDFromLocation(MD->getLocation());
+ if (DirectiveModuleID != ModID) {
+ if (DirectiveModuleID && !MD->isImported())
+ Result.push_back(DirectiveModuleID);
+ break;
+ }
+ }
+
+ // Weed out any duplicate overrides.
+ std::sort(Result.begin() + Start, Result.end());
+ Result.erase(std::unique(Result.begin() + Start, Result.end()), Result.end());
+}
+
/// \brief Writes the block containing the serialized form of the
/// preprocessor.
///
@@ -2041,6 +2065,7 @@ void ASTWriter::WritePreprocessor(const Preprocessor &PP, bool IsModule) {
WritePreprocessorDetail(*PPRec);
RecordData Record;
+ RecordData ModuleMacroRecord;
// If the preprocessor __COUNTER__ value has been bumped, remember it.
if (PP.getCounterValue() != 0) {
@@ -2092,10 +2117,26 @@ void ASTWriter::WritePreprocessor(const Preprocessor &PP, bool IsModule) {
Name->isFromAST() && !Name->hasChangedSinceDeserialization())
continue;
+ // State of this macro within each submodule.
+ enum class SubmoduleMacroState {
+ /// We've seen nothing about this macro.
+ None,
+ /// We've seen a public visibility directive.
+ Public,
+ /// We've either exported a macro for this module or found that the
+ /// module's definition of this macro is private.
+ Done
+ };
+ llvm::DenseMap<SubmoduleID, SubmoduleMacroState> State;
+
+ auto StartOffset = Stream.GetCurrentBitNo();
+
// Emit the macro directives in reverse source order.
for (; MD; MD = MD->getPrevious()) {
+ // Once we hit an ignored macro, we're done: the rest of the chain
+ // will all be ignored macros.
if (shouldIgnoreMacro(MD, IsModule, PP))
- continue;
+ break;
AddSourceLocation(MD->getLocation(), Record);
Record.push_back(MD->getKind());
@@ -2116,11 +2157,46 @@ void ASTWriter::WritePreprocessor(const Preprocessor &PP, bool IsModule) {
Record.push_back(Overrides.size());
Record.append(Overrides.begin(), Overrides.end());
}
+
+ // If this is the final definition in some module, and it's not
+ // module-private, add a module macro record for it.
+ if (IsModule) {
+ SubmoduleID ModID =
+ MD->isImported() ? MD->getOwningModuleID()
+ : inferSubmoduleIDFromLocation(MD->getLocation());
+ assert(ModID && "found macro in no submodule");
+
+ auto &S = State[ModID];
+ if (S == SubmoduleMacroState::Done) {
+ // We've already handled the final macro from this submodule, or seen
+ // a private visibility directive.
+ } else if (auto *VisMD = dyn_cast<VisibilityMacroDirective>(MD)) {
+ // The latest visibility directive for a name in a submodule affects
+ // all the directives that come before it.
+ if (S == SubmoduleMacroState::None)
+ S = VisMD->isPublic() ? SubmoduleMacroState::Public
+ : SubmoduleMacroState::Done;
+ } else {
+ S = SubmoduleMacroState::Done;
+
+ // Emit a record indicating this submodule exports this macro.
+ ModuleMacroRecord.push_back(ModID);
+ if (DefMacroDirective *DefMD = dyn_cast<DefMacroDirective>(MD))
+ ModuleMacroRecord.push_back(getMacroID(DefMD->getInfo()));
+ else
+ ModuleMacroRecord.push_back(0);
+ addOverriddenSubmodules(*this, PP, MD, ModuleMacroRecord);
+
+ Stream.EmitRecord(PP_MODULE_MACRO, ModuleMacroRecord);
+ ModuleMacroRecord.clear();
+ }
+ }
}
+
if (Record.empty())
continue;
- IdentMacroDirectivesOffsetMap[Name] = Stream.GetCurrentBitNo();
+ IdentMacroDirectivesOffsetMap[Name] = StartOffset;
Stream.EmitRecord(PP_MACRO_DIRECTIVE_HISTORY, Record);
Record.clear();
}
@@ -3130,106 +3206,18 @@ static NamedDecl *getDeclForLocalLookup(const LangOptions &LangOpts,
}
namespace {
-class PublicMacroIterator {
- ASTWriter &Writer;
- Preprocessor &PP;
- bool IsModule;
- MacroDirective *Macro;
-
- enum class SubmoduleMacroState {
- /// We've seen nothing about this macro.
- None,
- /// We've seen a public visibility directive.
- Public,
- /// We've either exported a macro for this module or found that the
- /// module's definition of this macro is private.
- Done
- };
- llvm::DenseMap<SubmoduleID, SubmoduleMacroState> State;
-
-public:
- PublicMacroIterator(ASTWriter &Writer, Preprocessor &PP, bool IsModule,
- IdentifierInfo *II)
- : Writer(Writer), PP(PP), IsModule(IsModule), Macro(nullptr) {
- if (!II->hadMacroDefinition())
- return;
-
- Macro = PP.getMacroDirectiveHistory(II);
-
- if (IsModule)
- Macro = skipUnexportedMacros(Macro);
- else if (shouldIgnoreMacro(Macro, IsModule, PP))
- Macro = nullptr;
- }
-
- MacroDirective *operator*() const { return Macro; }
- PublicMacroIterator &operator++() {
- Macro = skipUnexportedMacros(Macro->getPrevious());
- return *this;
- }
-
- explicit operator bool() const { return Macro; }
-
-private:
- /// \brief Traverses the macro directives history and returns the next
- /// public macro definition or undefinition that has not been found so far.
- ///
- /// A macro that is defined in submodule A and undefined in submodule B
- /// will still be considered as defined/exported from submodule A.
- MacroDirective *skipUnexportedMacros(MacroDirective *MD) {
- if (!MD || !IsModule)
- return nullptr;
-
- Optional<bool> IsPublic;
- for (; MD; MD = MD->getPrevious()) {
- // Once we hit an ignored macro, we're done: the rest of the chain
- // will all be ignored macros.
- if (shouldIgnoreMacro(MD, IsModule, PP))
- break;
-
- // If this macro was imported, re-export it.
- if (MD->isImported())
- return MD;
-
- SubmoduleID ModID =
- Writer.inferSubmoduleIDFromLocation(MD->getLocation());
- auto &S = State[ModID];
- assert(ModID && "found macro in no submodule");
-
- if (S == SubmoduleMacroState::Done)
- continue;
-
- if (auto *VisMD = dyn_cast<VisibilityMacroDirective>(MD)) {
- // The latest visibility directive for a name in a submodule affects all
- // the directives that come before it.
- if (S == SubmoduleMacroState::None)
- S = VisMD->isPublic() ? SubmoduleMacroState::Public
- : SubmoduleMacroState::Done;
- } else {
- S = SubmoduleMacroState::Done;
- return MD;
- }
- }
-
- return nullptr;
- }
-};
-
class ASTIdentifierTableTrait {
ASTWriter &Writer;
Preprocessor &PP;
IdentifierResolver &IdResolver;
- bool IsModule;
/// \brief Determines whether this is an "interesting" identifier that needs a
/// full IdentifierInfo structure written into the hash table. Notably, this
/// doesn't check whether the name has macros defined; use PublicMacroIterator
/// to check that.
- bool isInterestingIdentifier(IdentifierInfo *II) {
- if (PublicMacroIterator(Writer, PP, IsModule, II))
- return true;
-
- if (II->isPoisoned() ||
+ bool isInterestingIdentifier(IdentifierInfo *II, uint64_t MacroOffset) {
+ if (MacroOffset ||
+ II->isPoisoned() ||
II->isExtensionToken() ||
II->getObjCOrBuiltinID() ||
II->hasRevertedTokenIDToIdentifier() ||
@@ -3239,68 +3227,6 @@ class ASTIdentifierTableTrait {
return false;
}
- ArrayRef<SubmoduleID>
- getOverriddenSubmodules(MacroDirective *MD,
- SmallVectorImpl<SubmoduleID> &ScratchSpace) {
- assert(!isa<VisibilityMacroDirective>(MD) &&
- "only #define and #undef can override");
- if (MD->isImported())
- return MD->getOverriddenModules();
-
- ScratchSpace.clear();
- SubmoduleID ModID = getSubmoduleID(MD);
- for (MD = MD->getPrevious(); MD; MD = MD->getPrevious()) {
- if (shouldIgnoreMacro(MD, IsModule, PP))
- break;
-
- // If this is a definition from a submodule import, that submodule's
- // definition is overridden by the definition or undefinition that we
- // started with.
- if (MD->isImported()) {
- if (auto *DefMD = dyn_cast<DefMacroDirective>(MD)) {
- SubmoduleID DefModuleID = DefMD->getInfo()->getOwningModuleID();
- assert(DefModuleID && "imported macro has no owning module");
- ScratchSpace.push_back(DefModuleID);
- } else if (auto *UndefMD = dyn_cast<UndefMacroDirective>(MD)) {
- // If we override a #undef, we override anything that #undef overrides.
- // We don't need to override it, since an active #undef doesn't affect
- // the meaning of a macro.
- auto Overrides = UndefMD->getOverriddenModules();
- ScratchSpace.insert(ScratchSpace.end(),
- Overrides.begin(), Overrides.end());
- }
- }
-
- // Stop once we leave the original macro's submodule.
- //
- // Either this submodule #included another submodule of the same
- // module or it just happened to be built after the other module.
- // In the former case, we override the submodule's macro.
- //
- // FIXME: In the latter case, we shouldn't do so, but we can't tell
- // these cases apart.
- //
- // FIXME: We can leave this submodule and re-enter it if it #includes a
- // header within a different submodule of the same module. In such cases
- // the overrides list will be incomplete.
- SubmoduleID DirectiveModuleID = getSubmoduleID(MD);
- if (DirectiveModuleID != ModID) {
- if (DirectiveModuleID && !MD->isImported())
- ScratchSpace.push_back(DirectiveModuleID);
- break;
- }
- }
-
- std::sort(ScratchSpace.begin(), ScratchSpace.end());
- ScratchSpace.erase(std::unique(ScratchSpace.begin(), ScratchSpace.end()),
- ScratchSpace.end());
- return ScratchSpace;
- }
-
- SubmoduleID getSubmoduleID(MacroDirective *MD) {
- return Writer.inferSubmoduleIDFromLocation(MD->getLocation());
- }
-
public:
typedef IdentifierInfo* key_type;
typedef key_type key_type_ref;
@@ -3311,9 +3237,9 @@ public:
typedef unsigned hash_value_type;
typedef unsigned offset_type;
- ASTIdentifierTableTrait(ASTWriter &Writer, Preprocessor &PP,
- IdentifierResolver &IdResolver, bool IsModule)
- : Writer(Writer), PP(PP), IdResolver(IdResolver), IsModule(IsModule) { }
+ ASTIdentifierTableTrait(ASTWriter &Writer, Preprocessor &PP,
+ IdentifierResolver &IdResolver)
+ : Writer(Writer), PP(PP), IdResolver(IdResolver) {}
static hash_value_type ComputeHash(const IdentifierInfo* II) {
return llvm::HashString(II->getName());
@@ -3323,23 +3249,12 @@ public:
EmitKeyDataLength(raw_ostream& Out, IdentifierInfo* II, IdentID ID) {
unsigned KeyLen = II->getLength() + 1;
unsigned DataLen = 4; // 4 bytes for the persistent ID << 1
- PublicMacroIterator Macros(Writer, PP, IsModule, II);
- if (Macros || isInterestingIdentifier(II)) {
+ auto MacroOffset = Writer.getMacroDirectivesOffset(II);
+ if (isInterestingIdentifier(II, MacroOffset)) {
DataLen += 2; // 2 bytes for builtin ID
DataLen += 2; // 2 bytes for flags
- if (Macros) {
+ if (MacroOffset)
DataLen += 4; // MacroDirectives offset.
- if (IsModule) {
- SmallVector<SubmoduleID, 16> Scratch;
- for (; Macros; ++Macros) {
- DataLen += 4; // MacroInfo ID or ModuleID.
- if (unsigned NumOverrides =
- getOverriddenSubmodules(*Macros, Scratch).size())
- DataLen += 4 * (1 + NumOverrides);
- }
- DataLen += 4; // 0 terminator.
- }
- }
for (IdentifierResolver::iterator D = IdResolver.begin(II),
DEnd = IdResolver.end();
@@ -3366,26 +3281,13 @@ public:
Out.write(II->getNameStart(), KeyLen);
}
- static void emitMacroOverrides(raw_ostream &Out,
- ArrayRef<SubmoduleID> Overridden) {
- if (!Overridden.empty()) {
- using namespace llvm::support;
- endian::Writer<little> LE(Out);
- LE.write<uint32_t>(Overridden.size() | 0x80000000U);
- for (unsigned I = 0, N = Overridden.size(); I != N; ++I) {
- assert(Overridden[I] && "zero module ID for override");
- LE.write<uint32_t>(Overridden[I]);
- }
- }
- }
-
void EmitData(raw_ostream& Out, IdentifierInfo* II,
IdentID ID, unsigned) {
using namespace llvm::support;
endian::Writer<little> LE(Out);
- PublicMacroIterator Macros(Writer, PP, IsModule, II);
- if (!Macros && !isInterestingIdentifier(II)) {
+ auto MacroOffset = Writer.getMacroDirectivesOffset(II);
+ if (!isInterestingIdentifier(II, MacroOffset)) {
LE.write<uint32_t>(ID << 1);
return;
}
@@ -3395,41 +3297,16 @@ public:
assert((Bits & 0xffff) == Bits && "ObjCOrBuiltinID too big for ASTReader.");
LE.write<uint16_t>(Bits);
Bits = 0;
- bool HadMacroDefinition = !!Macros;
+ bool HadMacroDefinition = MacroOffset != 0;
Bits = (Bits << 1) | unsigned(HadMacroDefinition);
- Bits = (Bits << 1) | unsigned(IsModule);
Bits = (Bits << 1) | unsigned(II->isExtensionToken());
Bits = (Bits << 1) | unsigned(II->isPoisoned());
Bits = (Bits << 1) | unsigned(II->hasRevertedTokenIDToIdentifier());
Bits = (Bits << 1) | unsigned(II->isCPlusPlusOperatorKeyword());
LE.write<uint16_t>(Bits);
- if (HadMacroDefinition) {
- LE.write<uint32_t>(Writer.getMacroDirectivesOffset(II));
- if (IsModule) {
- // Write the IDs of macros coming from different submodules.
- SmallVector<SubmoduleID, 16> Scratch;
- for (; Macros; ++Macros) {
- if (DefMacroDirective *DefMD = dyn_cast<DefMacroDirective>(*Macros)) {
- // FIXME: If this macro directive was created by #pragma pop_macros,
- // or if it was created implicitly by resolving conflicting macros,
- // it may be for a different submodule from the one in the MacroInfo
- // object. If so, we should write out its owning ModuleID.
- MacroID InfoID = Writer.getMacroID(DefMD->getInfo());
- assert(InfoID);
- LE.write<uint32_t>(InfoID << 1);
- } else {
- auto *UndefMD = cast<UndefMacroDirective>(*Macros);
- SubmoduleID Mod = UndefMD->isImported()
- ? UndefMD->getOwningModuleID()
- : getSubmoduleID(UndefMD);
- LE.write<uint32_t>((Mod << 1) | 1);
- }
- emitMacroOverrides(Out, getOverriddenSubmodules(*Macros, Scratch));
- }
- LE.write<uint32_t>((uint32_t)-1);
- }
- }
+ if (HadMacroDefinition)
+ LE.write<uint32_t>(MacroOffset);
// Emit the declaration IDs in reverse order, because the
// IdentifierResolver provides the declarations as they would be
@@ -3461,7 +3338,7 @@ void ASTWriter::WriteIdentifierTable(Preprocessor &PP,
// strings.
{
llvm::OnDiskChainedHashTableGenerator<ASTIdentifierTableTrait> Generator;
- ASTIdentifierTableTrait Trait(*this, PP, IdResolver, IsModule);
+ ASTIdentifierTableTrait Trait(*this, PP, IdResolver);
// Look for any identifiers that were named while processing the
// headers, but are otherwise not needed. We add these to the hash
@@ -3495,7 +3372,6 @@ void ASTWriter::WriteIdentifierTable(Preprocessor &PP,
uint32_t BucketOffset;
{
using namespace llvm::support;
- ASTIdentifierTableTrait Trait(*this, PP, IdResolver, IsModule);
llvm::raw_svector_ostream Out(IdentifierTable);
// Make sure that no bucket is at offset 0
endian::Writer<little>(Out).write<uint32_t>(0);
@@ -4941,8 +4817,7 @@ MacroID ASTWriter::getMacroID(MacroInfo *MI) {
}
uint64_t ASTWriter::getMacroDirectivesOffset(const IdentifierInfo *Name) {
- assert(IdentMacroDirectivesOffsetMap[Name] && "not set!");
- return IdentMacroDirectivesOffsetMap[Name];
+ return IdentMacroDirectivesOffsetMap.lookup(Name);
}
void ASTWriter::AddSelectorRef(const Selector SelRef, RecordDataImpl &Record) {
OpenPOWER on IntegriCloud