diff options
author | Argyrios Kyrtzidis <akyrtzi@gmail.com> | 2013-03-26 17:17:01 +0000 |
---|---|---|
committer | Argyrios Kyrtzidis <akyrtzi@gmail.com> | 2013-03-26 17:17:01 +0000 |
commit | c56fff7fd231aebf4b152f60f8f11ef91835c48a (patch) | |
tree | 22119f54c12ae692e50e7ed4930160f950e37f2f /lib/Serialization/ASTWriter.cpp | |
parent | 1232e279b4a0d98885b9672d3bb5905488360e49 (diff) |
[Preprocessor/Modules] Separate the macro directives kinds into their own MacroDirective's subclasses.
For each macro directive (define, undefine, visibility) have a separate object that gets chained
to the macro directive history. This has several benefits:
-No need to mutate a MacroDirective when there is a undefine/visibility directive. Stuff like
PPMutationListener become unnecessary.
-No need to keep extra source locations for the undef/visibility locations for the define directive object
(which is the majority of the directives)
-Much easier to hide/unhide a section in the macro directive history.
-Easier to track the effects of the directives across different submodules.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@178037 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Serialization/ASTWriter.cpp')
-rw-r--r-- | lib/Serialization/ASTWriter.cpp | 136 |
1 files changed, 87 insertions, 49 deletions
diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp index 725896309e..95e32a37fe 100644 --- a/lib/Serialization/ASTWriter.cpp +++ b/lib/Serialization/ASTWriter.cpp @@ -1833,8 +1833,9 @@ static int compareMacroDirectives(const void *XPtr, const void *YPtr) { static bool shouldIgnoreMacro(MacroDirective *MD, bool IsModule, const Preprocessor &PP) { - if (MD->getInfo()->isBuiltinMacro()) - return true; + if (MacroInfo *MI = MD->getMacroInfo()) + if (MI->isBuiltinMacro()) + return true; if (IsModule) { SourceLocation Loc = MD->getLocation(); @@ -1902,25 +1903,30 @@ void ASTWriter::WritePreprocessor(const Preprocessor &PP, bool IsModule) { // If the macro or identifier need no updates, don't write the macro history // for this one. - if (MD->isFromPCH() && !MD->hasChangedAfterLoad() && + // FIXME: Chain the macro history instead of re-writing it. + if (MD->isFromPCH() && Name->isFromAST() && !Name->hasChangedSinceDeserialization()) continue; // Emit the macro directives in reverse source order. for (; MD; MD = MD->getPrevious()) { - if (shouldIgnoreMacro(MD, IsModule, PP)) + if (MD->isHidden()) continue; - MacroID InfoID = getMacroRef(MD->getInfo(), Name); - if (InfoID == 0) + if (shouldIgnoreMacro(MD, IsModule, PP)) continue; - Record.push_back(InfoID); AddSourceLocation(MD->getLocation(), Record); - AddSourceLocation(MD->getUndefLoc(), Record); - AddSourceLocation(MD->getVisibilityLocation(), Record); - Record.push_back(MD->isImported()); - Record.push_back(MD->isPublic()); - Record.push_back(MD->isAmbiguous()); + Record.push_back(MD->getKind()); + if (DefMacroDirective *DefMD = dyn_cast<DefMacroDirective>(MD)) { + MacroID InfoID = getMacroRef(DefMD->getInfo(), Name); + Record.push_back(InfoID); + Record.push_back(DefMD->isImported()); + Record.push_back(DefMD->isAmbiguous()); + + } else if (VisibilityMacroDirective * + VisMD = dyn_cast<VisibilityMacroDirective>(MD)) { + Record.push_back(VisMD->isPublic()); + } } if (Record.empty()) continue; @@ -2898,48 +2904,78 @@ class ASTIdentifierTableTrait { return false; } - MacroDirective *getFirstPublicSubmoduleMacro(MacroDirective *MD, - SubmoduleID &ModID) { - if (shouldIgnoreMacro(MD, IsModule, PP)) - return 0; - ModID = getSubmoduleID(MD); - if (ModID == 0) - return 0; - if (MD->isDefined() && MD->isPublic()) - return MD; - return getNextPublicSubmoduleMacro(MD, ModID); + DefMacroDirective *getFirstPublicSubmoduleMacro(MacroDirective *MD, + SubmoduleID &ModID) { + ModID = 0; + if (DefMacroDirective *DefMD = getPublicSubmoduleMacro(MD, ModID)) + if (!shouldIgnoreMacro(DefMD, IsModule, PP)) + return DefMD; + return 0; } - MacroDirective *getNextPublicSubmoduleMacro(MacroDirective *MD, - SubmoduleID &ModID) { - while (MD) { - MD = getNextSubmoduleMacro(MD, ModID); - if (MD && MD->isDefined() && MD->isPublic()) - return MD; - } + DefMacroDirective *getNextPublicSubmoduleMacro(DefMacroDirective *MD, + SubmoduleID &ModID) { + if (DefMacroDirective * + DefMD = getPublicSubmoduleMacro(MD->getPrevious(), ModID)) + if (!shouldIgnoreMacro(DefMD, IsModule, PP)) + return DefMD; return 0; } - MacroDirective *getNextSubmoduleMacro(MacroDirective *CurrMD, - SubmoduleID &CurrModID) { - SubmoduleID OrigID = CurrModID; - while ((CurrMD = CurrMD->getPrevious())) { - if (shouldIgnoreMacro(CurrMD, IsModule, PP)) - return 0; - CurrModID = getSubmoduleID(CurrMD); - if (CurrModID == 0) - return 0; - if (CurrModID != OrigID) - return CurrMD; + /// \brief Traverses the macro directives history and returns the latest + /// macro that is public and not undefined in the same submodule. + /// A macro that is defined in submodule A and undefined in submodule B, + /// will still be considered as defined/exported from submodule A. + DefMacroDirective *getPublicSubmoduleMacro(MacroDirective *MD, + SubmoduleID &ModID) { + if (!MD) + return 0; + + bool isUndefined = false; + Optional<bool> isPublic; + for (; MD; MD = MD->getPrevious()) { + if (MD->isHidden()) + continue; + + SubmoduleID ThisModID = getSubmoduleID(MD); + if (ThisModID == 0) { + isUndefined = false; + isPublic = Optional<bool>(); + continue; + } + if (ThisModID != ModID){ + ModID = ThisModID; + isUndefined = false; + isPublic = Optional<bool>(); + } + + if (DefMacroDirective *DefMD = dyn_cast<DefMacroDirective>(MD)) { + if (!isUndefined && (!isPublic.hasValue() || isPublic.getValue())) + return DefMD; + continue; + } + + if (isa<UndefMacroDirective>(MD)) { + isUndefined = true; + continue; + } + + VisibilityMacroDirective *VisMD = cast<VisibilityMacroDirective>(MD); + if (!isPublic.hasValue()) + isPublic = VisMD->isPublic(); } + return 0; } SubmoduleID getSubmoduleID(MacroDirective *MD) { - MacroInfo *MI = MD->getInfo(); - if (unsigned ID = MI->getOwningModuleID()) - return ID; - return Writer.inferSubmoduleIDFromLocation(MI->getDefinitionLoc()); + if (DefMacroDirective *DefMD = dyn_cast<DefMacroDirective>(MD)) { + MacroInfo *MI = DefMD->getInfo(); + if (unsigned ID = MI->getOwningModuleID()) + return ID; + return Writer.inferSubmoduleIDFromLocation(MI->getDefinitionLoc()); + } + return Writer.inferSubmoduleIDFromLocation(MD->getLocation()); } public: @@ -2969,8 +3005,9 @@ public: DataLen += 4; // MacroDirectives offset. if (IsModule) { SubmoduleID ModID; - for (MacroDirective *MD = getFirstPublicSubmoduleMacro(Macro, ModID); - MD; MD = getNextPublicSubmoduleMacro(MD, ModID)) { + for (DefMacroDirective * + DefMD = getFirstPublicSubmoduleMacro(Macro, ModID); + DefMD; DefMD = getNextPublicSubmoduleMacro(DefMD, ModID)) { DataLen += 4; // MacroInfo ID. } DataLen += 4; @@ -3025,9 +3062,10 @@ public: if (IsModule) { // Write the IDs of macros coming from different submodules. SubmoduleID ModID; - for (MacroDirective *MD = getFirstPublicSubmoduleMacro(Macro, ModID); - MD; MD = getNextPublicSubmoduleMacro(MD, ModID)) { - MacroID InfoID = Writer.getMacroID(MD->getInfo()); + for (DefMacroDirective * + DefMD = getFirstPublicSubmoduleMacro(Macro, ModID); + DefMD; DefMD = getNextPublicSubmoduleMacro(DefMD, ModID)) { + MacroID InfoID = Writer.getMacroID(DefMD->getInfo()); assert(InfoID); clang::io::Emit32(Out, InfoID); } |