diff options
-rw-r--r-- | include/clang/Lex/MacroInfo.h | 254 | ||||
-rw-r--r-- | include/clang/Lex/Preprocessor.h | 43 | ||||
-rw-r--r-- | lib/Frontend/CompilerInstance.cpp | 39 | ||||
-rw-r--r-- | lib/Frontend/PrintPreprocessedOutput.cpp | 4 | ||||
-rw-r--r-- | lib/Lex/MacroInfo.cpp | 40 | ||||
-rw-r--r-- | lib/Lex/PPDirectives.cpp | 70 | ||||
-rw-r--r-- | lib/Lex/PPExpressions.cpp | 2 | ||||
-rw-r--r-- | lib/Lex/PPMacroExpansion.cpp | 120 | ||||
-rw-r--r-- | lib/Lex/Pragma.cpp | 13 | ||||
-rw-r--r-- | lib/Lex/PreprocessingRecord.cpp | 15 | ||||
-rw-r--r-- | lib/Lex/Preprocessor.cpp | 14 | ||||
-rw-r--r-- | lib/Sema/SemaCodeComplete.cpp | 2 | ||||
-rw-r--r-- | lib/Serialization/ASTReader.cpp | 69 | ||||
-rw-r--r-- | lib/Serialization/ASTWriter.cpp | 136 | ||||
-rw-r--r-- | tools/libclang/CIndex.cpp | 12 |
15 files changed, 440 insertions, 393 deletions
diff --git a/include/clang/Lex/MacroInfo.h b/include/clang/Lex/MacroInfo.h index d83d0cc9f0..d7e72fb5c6 100644 --- a/include/clang/Lex/MacroInfo.h +++ b/include/clang/Lex/MacroInfo.h @@ -299,6 +299,8 @@ private: friend class Preprocessor; }; +class DefMacroDirective; + /// \brief Encapsulates changes to the "macros namespace" (the location where /// the macro name became active, the location where it was undefined, etc.). /// @@ -314,76 +316,56 @@ private: /// will point to the same MacroInfo object. /// class MacroDirective { - MacroInfo *Info; - - /// \brief Previous definition, the identifier of this macro was defined to, - /// or NULL. +public: + enum Kind { + MD_Define, + MD_Undefine, + MD_Visibility + }; + +protected: + /// \brief Previous macro directive for the same identifier, or NULL. MacroDirective *Previous; SourceLocation Loc; - /// \brief The location where the macro was #undef'd, or an invalid location - /// for macros that haven't been undefined. - SourceLocation UndefLocation; - - /// \brief The location at which this macro was either explicitly exported - /// from its module or marked as private. - /// - /// If invalid, this macro has not been explicitly given any visibility. - SourceLocation VisibilityLocation; + /// \brief MacroDirective kind. + unsigned MDKind : 2; /// \brief True if the macro directive was loaded from a PCH file. bool IsFromPCH : 1; - /// \brief True if this macro was imported from a module. - bool IsImported : 1; - - /// \brief Whether the macro has public (when described in a module). - bool IsPublic : 1; - - /// \brief Whether the macro definition is currently "hidden". + /// \brief Whether the macro directive is currently "hidden". /// /// Note that this is transient state that is never serialized to the AST /// file. bool IsHidden : 1; + // Used by DefMacroDirective -----------------------------------------------// + + /// \brief True if this macro was imported from a module. + bool IsImported : 1; + /// \brief Whether the definition of this macro is ambiguous, due to /// multiple definitions coming in from multiple modules. bool IsAmbiguous : 1; - /// \brief Whether this macro changed after it was loaded from an AST file. - bool ChangedAfterLoad : 1; + // Used by VisibilityMacroDirective ----------------------------------------// -public: - explicit MacroDirective(MacroInfo *MI) - : Info(MI), Previous(0), Loc(MI->getDefinitionLoc()), - IsFromPCH(false), IsImported(false), IsPublic(true), IsHidden(false), - IsAmbiguous(false), ChangedAfterLoad(false) { - assert(MI && "MacroInfo is null"); - } - - MacroDirective(MacroInfo *MI, SourceLocation Loc, bool isImported) - : Info(MI), Previous(0), Loc(Loc), - IsFromPCH(false), IsImported(isImported), IsPublic(true), IsHidden(false), - IsAmbiguous(false), ChangedAfterLoad(false) { - assert(MI && "MacroInfo is null"); - } - - SourceLocation getLocation() const { return Loc; } + /// \brief Whether the macro has public visibility (when described in a + /// module). + bool IsPublic : 1; - /// \brief Set the location where macro was undefined. Can only be set once. - void setUndefLoc(SourceLocation UndefLoc) { - assert(UndefLocation.isInvalid() && "UndefLocation is already set!"); - assert(UndefLoc.isValid() && "Invalid UndefLoc!"); - UndefLocation = UndefLoc; + MacroDirective(Kind K, SourceLocation Loc) + : Previous(0), Loc(Loc), MDKind(K), IsFromPCH(false), IsHidden(false), + IsImported(false), IsAmbiguous(false), + IsPublic(true) { } - /// \brief The data for the macro definition. - const MacroInfo *getInfo() const { return Info; } - MacroInfo *getInfo() { return Info; } +public: + Kind getKind() const { return Kind(MDKind); } - /// \brief Get the location where macro was undefined. - SourceLocation getUndefLoc() const { return UndefLocation; } + SourceLocation getLocation() const { return Loc; } /// \brief Set previous definition of the macro with the same name. void setPrevious(MacroDirective *Prev) { @@ -396,42 +378,104 @@ public: /// \brief Get previous definition of the macro with the same name. MacroDirective *getPrevious() { return Previous; } - /// \brief Find macro definition active in the specified source location. If - /// this macro was not defined there, return NULL. - const MacroDirective *findDirectiveAtLoc(SourceLocation L, - SourceManager &SM) const; + /// \brief Return true if the macro directive was loaded from a PCH file. + bool isFromPCH() const { return IsFromPCH; } - /// \brief Set the export location for this macro. - void setVisibility(bool Public, SourceLocation Loc) { - VisibilityLocation = Loc; - IsPublic = Public; + void setIsFromPCH() { IsFromPCH = true; } + + /// \brief Determine whether this macro directive is hidden. + bool isHidden() const { return IsHidden; } + + /// \brief Set whether this macro directive is hidden. + void setHidden(bool Val) { IsHidden = Val; } + + class DefInfo { + DefMacroDirective *DefDirective; + SourceLocation UndefLoc; + bool IsPublic; + + public: + DefInfo() : DefDirective(0) { } + + DefInfo(DefMacroDirective *DefDirective, SourceLocation UndefLoc, + bool isPublic) + : DefDirective(DefDirective), UndefLoc(UndefLoc), IsPublic(isPublic) { } + + const DefMacroDirective *getDirective() const { return DefDirective; } + DefMacroDirective *getDirective() { return DefDirective; } + + inline SourceLocation getLocation() const; + inline MacroInfo *getMacroInfo(); + const MacroInfo *getMacroInfo() const { + return const_cast<DefInfo*>(this)->getMacroInfo(); + } + + SourceLocation getUndefLocation() const { return UndefLoc; } + bool isUndefined() const { return UndefLoc.isValid(); } + + bool isPublic() const { return IsPublic; } + + bool isValid() const { return DefDirective != 0; } + bool isInvalid() const { return !isValid(); } + + operator bool() const { return isValid(); } + + inline DefInfo getPreviousDefinition(bool AllowHidden = false); + const DefInfo getPreviousDefinition(bool AllowHidden = false) const { + return const_cast<DefInfo*>(this)->getPreviousDefinition(AllowHidden); + } + }; + + /// \brief Traverses the macro directives history and returns the next + /// macro definition directive along with info about its undefined location + /// (if there is one) and if it is public or private. + DefInfo getDefinition(bool AllowHidden = false); + const DefInfo getDefinition(bool AllowHidden = false) const { + return const_cast<MacroDirective*>(this)->getDefinition(AllowHidden); } - /// \brief Determine whether this macro is part of the public API of its - /// module. - bool isPublic() const { return IsPublic; } - - /// \brief Determine the location where this macro was explicitly made - /// public or private within its module. - SourceLocation getVisibilityLocation() const { return VisibilityLocation; } + bool isDefined(bool AllowHidden = false) const { + if (const DefInfo Def = getDefinition(AllowHidden)) + return !Def.isUndefined(); + return false; + } - /// \brief Return true if the macro directive was loaded from a PCH file. - bool isFromPCH() const { return IsFromPCH; } + const MacroInfo *getMacroInfo(bool AllowHidden = false) const { + return getDefinition(AllowHidden).getMacroInfo(); + } + MacroInfo *getMacroInfo(bool AllowHidden = false) { + return getDefinition(AllowHidden).getMacroInfo(); + } - void setIsFromPCH() { IsFromPCH = true; } + /// \brief Find macro definition active in the specified source location. If + /// this macro was not defined there, return NULL. + const DefInfo findDirectiveAtLoc(SourceLocation L, SourceManager &SM) const; - /// \brief True if this macro was imported from a module. - bool isImported() const { return IsImported; } + static bool classof(const MacroDirective *) { return true; } +}; - /// \brief Determine whether this macro is currently defined (and has not - /// been #undef'd) or has been hidden. - bool isDefined() const { return UndefLocation.isInvalid() && !IsHidden; } +/// \brief A directive for a defined macro or a macro imported from a module. +class DefMacroDirective : public MacroDirective { + MacroInfo *Info; - /// \brief Determine whether this macro definition is hidden. - bool isHidden() const { return IsHidden; } +public: + explicit DefMacroDirective(MacroInfo *MI) + : MacroDirective(MD_Define, MI->getDefinitionLoc()), Info(MI) { + assert(MI && "MacroInfo is null"); + } - /// \brief Set whether this macro definition is hidden. - void setHidden(bool Val) { IsHidden = Val; } + DefMacroDirective(MacroInfo *MI, SourceLocation Loc, bool isImported) + : MacroDirective(MD_Define, Loc), Info(MI) { + assert(MI && "MacroInfo is null"); + IsImported = isImported; + } + + /// \brief The data for the macro definition. + const MacroInfo *getInfo() const { return Info; } + MacroInfo *getInfo() { return Info; } + + /// \brief True if this macro was imported from a module. + bool isImported() const { return IsImported; } /// \brief Determine whether this macro definition is ambiguous with /// other macro definitions. @@ -440,15 +484,63 @@ public: /// \brief Set whether this macro definition is ambiguous. void setAmbiguous(bool Val) { IsAmbiguous = Val; } - /// \brief Determine whether this macro has changed since it was loaded from - /// an AST file. - bool hasChangedAfterLoad() const { return ChangedAfterLoad; } + static bool classof(const MacroDirective *MD) { + return MD->getKind() == MD_Define; + } + static bool classof(const DefMacroDirective *) { return true; } +}; - /// \brief Note whether this macro has changed after it was loaded from an - /// AST file. - void setChangedAfterLoad(bool CAL = true) { ChangedAfterLoad = CAL; } +/// \brief A directive for an undefined macro. +class UndefMacroDirective : public MacroDirective { +public: + explicit UndefMacroDirective(SourceLocation UndefLoc) + : MacroDirective(MD_Undefine, UndefLoc) { + assert(UndefLoc.isValid() && "Invalid UndefLoc!"); + } + + static bool classof(const MacroDirective *MD) { + return MD->getKind() == MD_Undefine; + } + static bool classof(const UndefMacroDirective *) { return true; } }; +/// \brief A directive for setting the module visibility of a macro. +class VisibilityMacroDirective : public MacroDirective { +public: + explicit VisibilityMacroDirective(SourceLocation Loc, bool Public) + : MacroDirective(MD_Visibility, Loc) { + IsPublic = Public; + } + + /// \brief Determine whether this macro is part of the public API of its + /// module. + bool isPublic() const { return IsPublic; } + + static bool classof(const MacroDirective *MD) { + return MD->getKind() == MD_Visibility; + } + static bool classof(const VisibilityMacroDirective *) { return true; } +}; + +inline SourceLocation MacroDirective::DefInfo::getLocation() const { + if (isInvalid()) + return SourceLocation(); + return DefDirective->getLocation(); +} + +inline MacroInfo *MacroDirective::DefInfo::getMacroInfo() { + if (isInvalid()) + return 0; + return DefDirective->getInfo(); +} + +inline MacroDirective::DefInfo +MacroDirective::DefInfo::getPreviousDefinition(bool AllowHidden) { + if (isInvalid() || DefDirective->getPrevious() == 0) + return DefInfo(); + return DefDirective->getPrevious()->getDefinition(AllowHidden); +} + } // end namespace clang #endif diff --git a/include/clang/Lex/Preprocessor.h b/include/clang/Lex/Preprocessor.h index fdff12395e..dafa497214 100644 --- a/include/clang/Lex/Preprocessor.h +++ b/include/clang/Lex/Preprocessor.h @@ -532,14 +532,14 @@ public: /// associated with this preprocessor, if any. PPMutationListener *getPPMutationListener() const { return Listener; } - /// \brief Given an identifier, return the MacroInfo it is \#defined to - /// or null if it isn't \#define'd. + /// \brief Given an identifier, return its latest MacroDirective if it is + // \#defined or null if it isn't \#define'd. MacroDirective *getMacroDirective(IdentifierInfo *II) const { if (!II->hasMacroDefinition()) return 0; MacroDirective *MD = getMacroDirectiveHistory(II); - assert(MD->getUndefLoc().isInvalid() && "Macro is undefined!"); + assert(MD->isDefined() && "Macro is undefined!"); return MD; } @@ -549,7 +549,7 @@ public: MacroInfo *getMacroInfo(IdentifierInfo *II) { if (MacroDirective *MD = getMacroDirective(II)) - return MD->getInfo(); + return MD->getMacroInfo(); return 0; } @@ -559,27 +559,20 @@ public: /// identifiers that hadMacroDefinition(). MacroDirective *getMacroDirectiveHistory(const IdentifierInfo *II) const; - /// \brief Specify a macro for this identifier. - void setMacroDirective(IdentifierInfo *II, MacroDirective *MD); - MacroDirective *setMacroDirective(IdentifierInfo *II, MacroInfo *MI, - SourceLocation Loc, bool isImported) { - MacroDirective *MD = AllocateMacroDirective(MI, Loc, isImported); - setMacroDirective(II, MD); + /// \brief Add a directive to the macro directive history for this identifier. + void appendMacroDirective(IdentifierInfo *II, MacroDirective *MD); + DefMacroDirective *appendDefMacroDirective(IdentifierInfo *II, MacroInfo *MI, + SourceLocation Loc, + bool isImported) { + DefMacroDirective *MD = AllocateDefMacroDirective(MI, Loc, isImported); + appendMacroDirective(II, MD); return MD; } - MacroDirective *setMacroDirective(IdentifierInfo *II, MacroInfo *MI) { - return setMacroDirective(II, MI, MI->getDefinitionLoc(), false); + DefMacroDirective *appendDefMacroDirective(IdentifierInfo *II, MacroInfo *MI){ + return appendDefMacroDirective(II, MI, MI->getDefinitionLoc(), false); } /// \brief Set a MacroDirective that was loaded from a PCH file. void setLoadedMacroDirective(IdentifierInfo *II, MacroDirective *MD); - /// \brief Add a MacroInfo that was loaded from an AST file. - void addLoadedMacroInfo(IdentifierInfo *II, MacroDirective *MD, - MacroDirective *Hint = 0); - /// \brief Make the given MacroInfo, that was loaded from an AST file and - /// previously hidden, visible. - void makeLoadedMacroInfoVisible(IdentifierInfo *II, MacroDirective *MD); - /// \brief Undefine a macro for this identifier. - void clearMacroInfo(IdentifierInfo *II); /// macro_iterator/macro_begin/macro_end - This allows you to walk the macro /// history table. Currently defined macros have @@ -1294,8 +1287,12 @@ private: /// \brief Allocate a new MacroInfo object. MacroInfo *AllocateMacroInfo(); - MacroDirective *AllocateMacroDirective(MacroInfo *MI, SourceLocation Loc, - bool isImported); + DefMacroDirective *AllocateDefMacroDirective(MacroInfo *MI, + SourceLocation Loc, + bool isImported); + UndefMacroDirective *AllocateUndefMacroDirective(SourceLocation UndefLoc); + VisibilityMacroDirective *AllocateVisibilityMacroDirective(SourceLocation Loc, + bool isPublic); /// \brief Release the specified MacroInfo for re-use. /// @@ -1449,8 +1446,6 @@ private: // Macro handling. void HandleDefineDirective(Token &Tok); void HandleUndefDirective(Token &Tok); - void UndefineMacro(IdentifierInfo *II, MacroDirective *MD, - SourceLocation UndefLoc); // Conditional Inclusion. void HandleIfdefDirective(Token &Tok, bool isIfndef, diff --git a/lib/Frontend/CompilerInstance.cpp b/lib/Frontend/CompilerInstance.cpp index 4c4d603716..c6c850b0d6 100644 --- a/lib/Frontend/CompilerInstance.cpp +++ b/lib/Frontend/CompilerInstance.cpp @@ -923,10 +923,11 @@ static void checkConfigMacro(Preprocessor &PP, StringRef ConfigMacro, // If this identifier does not currently have a macro definition, // check whether it had one on the command line. if (!Id->hasMacroDefinition()) { - MacroDirective *UndefMD = PP.getMacroDirectiveHistory(Id); - for (MacroDirective *MD = UndefMD; MD; MD = MD->getPrevious()) { - - FileID FID = SourceMgr.getFileID(MD->getLocation()); + MacroDirective::DefInfo LatestDef = + PP.getMacroDirectiveHistory(Id)->getDefinition(); + for (MacroDirective::DefInfo Def = LatestDef; Def; + Def = Def.getPreviousDefinition()) { + FileID FID = SourceMgr.getFileID(Def.getLocation()); if (FID.isInvalid()) continue; @@ -942,8 +943,8 @@ static void checkConfigMacro(Preprocessor &PP, StringRef ConfigMacro, // Complain. PP.Diag(ImportLoc, diag::warn_module_config_macro_undef) << true << ConfigMacro << Mod->getFullModuleName(); - if (UndefMD->getUndefLoc().isValid()) - PP.Diag(UndefMD->getUndefLoc(), diag::note_module_def_undef_here) + if (LatestDef.isUndefined()) + PP.Diag(LatestDef.getUndefLocation(), diag::note_module_def_undef_here) << true; return; } @@ -954,10 +955,12 @@ static void checkConfigMacro(Preprocessor &PP, StringRef ConfigMacro, // This identifier has a macro definition. Check whether we had a definition // on the command line. - MacroDirective *DefMD = PP.getMacroDirective(Id); - MacroDirective *PredefinedMD = 0; - for (MacroDirective *MD = DefMD; MD; MD = MD->getPrevious()) { - FileID FID = SourceMgr.getFileID(MD->getLocation()); + MacroDirective::DefInfo LatestDef = + PP.getMacroDirectiveHistory(Id)->getDefinition(); + MacroDirective::DefInfo PredefinedDef; + for (MacroDirective::DefInfo Def = LatestDef; Def; + Def = Def.getPreviousDefinition()) { + FileID FID = SourceMgr.getFileID(Def.getLocation()); if (FID.isInvalid()) continue; @@ -969,32 +972,32 @@ static void checkConfigMacro(Preprocessor &PP, StringRef ConfigMacro, if (!StringRef(Buffer->getBufferIdentifier()).equals("<built-in>")) continue; - PredefinedMD = MD; + PredefinedDef = Def; break; } // If there was no definition for this macro in the predefines buffer, // complain. - if (!PredefinedMD || - (!PredefinedMD->getLocation().isValid() && - PredefinedMD->getUndefLoc().isValid())) { + if (!PredefinedDef || + (!PredefinedDef.getLocation().isValid() && + PredefinedDef.getUndefLocation().isValid())) { PP.Diag(ImportLoc, diag::warn_module_config_macro_undef) << false << ConfigMacro << Mod->getFullModuleName(); - PP.Diag(DefMD->getLocation(), diag::note_module_def_undef_here) + PP.Diag(LatestDef.getLocation(), diag::note_module_def_undef_here) << false; return; } // If the current macro definition is the same as the predefined macro // definition, it's okay. - if (DefMD == PredefinedMD || - DefMD->getInfo()->isIdenticalTo(*PredefinedMD->getInfo(), PP)) + if (LatestDef.getMacroInfo() == PredefinedDef.getMacroInfo() || + LatestDef.getMacroInfo()->isIdenticalTo(*PredefinedDef.getMacroInfo(),PP)) return; // The macro definitions differ. PP.Diag(ImportLoc, diag::warn_module_config_macro_undef) << false << ConfigMacro << Mod->getFullModuleName(); - PP.Diag(DefMD->getLocation(), diag::note_module_def_undef_here) + PP.Diag(LatestDef.getLocation(), diag::note_module_def_undef_here) << false; } diff --git a/lib/Frontend/PrintPreprocessedOutput.cpp b/lib/Frontend/PrintPreprocessedOutput.cpp index d894939b4b..f70bd7c93e 100644 --- a/lib/Frontend/PrintPreprocessedOutput.cpp +++ b/lib/Frontend/PrintPreprocessedOutput.cpp @@ -318,7 +318,7 @@ void PrintPPOutputPPCallbacks::Ident(SourceLocation Loc, const std::string &S) { /// MacroDefined - This hook is called whenever a macro definition is seen. void PrintPPOutputPPCallbacks::MacroDefined(const Token &MacroNameTok, const MacroDirective *MD) { - const MacroInfo *MI = MD->getInfo(); + const MacroInfo *MI = MD->getMacroInfo(); // Only print out macro definitions in -dD mode. if (!DumpDefines || // Ignore __FILE__ etc. @@ -602,7 +602,7 @@ static void DoPrintMacros(Preprocessor &PP, raw_ostream *OS) { for (Preprocessor::macro_iterator I = PP.macro_begin(), E = PP.macro_end(); I != E; ++I) { if (I->first->hasMacroDefinition()) - MacrosByID.push_back(id_macro_pair(I->first, I->second->getInfo())); + MacrosByID.push_back(id_macro_pair(I->first, I->second->getMacroInfo())); } llvm::array_pod_sort(MacrosByID.begin(), MacrosByID.end(), MacroIDCompare); diff --git a/lib/Lex/MacroInfo.cpp b/lib/Lex/MacroInfo.cpp index 213e71132b..dc091f625b 100644 --- a/lib/Lex/MacroInfo.cpp +++ b/lib/Lex/MacroInfo.cpp @@ -108,14 +108,40 @@ bool MacroInfo::isIdenticalTo(const MacroInfo &Other, Preprocessor &PP) const { return true; } -const MacroDirective * +MacroDirective::DefInfo MacroDirective::getDefinition(bool AllowHidden) { + MacroDirective *MD = this; + SourceLocation UndefLoc; + Optional<bool> isPublic; + for (; MD; MD = MD->getPrevious()) { + if (!AllowHidden && MD->isHidden()) + continue; + + if (DefMacroDirective *DefMD = dyn_cast<DefMacroDirective>(MD)) + return DefInfo(DefMD, UndefLoc, + !isPublic.hasValue() || isPublic.getValue()); + + if (UndefMacroDirective *UndefMD = dyn_cast<UndefMacroDirective>(MD)) { + UndefLoc = UndefMD->getLocation(); + continue; + } + + VisibilityMacroDirective *VisMD = cast<VisibilityMacroDirective>(MD); + if (!isPublic.hasValue()) + isPublic = VisMD->isPublic(); + } + + return DefInfo(); +} + +const MacroDirective::DefInfo MacroDirective::findDirectiveAtLoc(SourceLocation L, SourceManager &SM) const { assert(L.isValid() && "SourceLocation is invalid."); - for (const MacroDirective *MD = this; MD; MD = MD->Previous) { - if (MD->getLocation().isInvalid() || // For macros defined on the command line. - SM.isBeforeInTranslationUnit(MD->getLocation(), L)) - return (MD->UndefLocation.isInvalid() || - SM.isBeforeInTranslationUnit(L, MD->UndefLocation)) ? MD : NULL; + for (DefInfo Def = getDefinition(); Def; Def = Def.getPreviousDefinition()) { + if (Def.getLocation().isInvalid() || // For macros defined on the command line. + SM.isBeforeInTranslationUnit(Def.getLocation(), L)) + return (!Def.isUndefined() || + SM.isBeforeInTranslationUnit(L, Def.getUndefLocation())) + ? Def : DefInfo(); } - return NULL; + return DefInfo(); } diff --git a/lib/Lex/PPDirectives.cpp b/lib/Lex/PPDirectives.cpp index 7020da3940..3fc19e41f8 100644 --- a/lib/Lex/PPDirectives.cpp +++ b/lib/Lex/PPDirectives.cpp @@ -70,11 +70,26 @@ MacroInfo *Preprocessor::AllocateDeserializedMacroInfo(SourceLocation L, return MI; } -MacroDirective *Preprocessor::AllocateMacroDirective(MacroInfo *MI, - SourceLocation Loc, - bool isImported) { - MacroDirective *MD = BP.Allocate<MacroDirective>(); - new (MD) MacroDirective(MI, Loc, isImported); +DefMacroDirective * +Preprocessor::AllocateDefMacroDirective(MacroInfo *MI, SourceLocation Loc, + bool isImported) { + DefMacroDirective *MD = BP.Allocate<DefMacroDirective>(); + new (MD) DefMacroDirective(MI, Loc, isImported); + return MD; +} + +UndefMacroDirective * +Preprocessor::AllocateUndefMacroDirective(SourceLocation UndefLoc) { + UndefMacroDirective *MD = BP.Allocate<UndefMacroDirective>(); + new (MD) UndefMacroDirective(UndefLoc); + return MD; +} + +VisibilityMacroDirective * +Preprocessor::AllocateVisibilityMacroDirective(SourceLocation Loc, + bool isPublic) { + VisibilityMacroDirective *MD = BP.Allocate<VisibilityMacroDirective>(); + new (MD) VisibilityMacroDirective(Loc, isPublic); return MD; } @@ -1130,15 +1145,8 @@ void Preprocessor::HandleMacroPublicDirective(Token &Tok) { } // Note that this macro has now been exported. - MD->setVisibility(/*IsPublic=*/true, MacroNameTok.getLocation()); - - // If this macro directive came from a PCH file, mark it as having changed - // since serialization. - if (MD->isFromPCH()) { - MD->setChangedAfterLoad(); - assert(II->isFromAST()); - II->setChangedSinceDeserialization(); - } + appendMacroDirective(II, AllocateVisibilityMacroDirective( + MacroNameTok.getLocation(), /*IsPublic=*/true)); } /// \brief Handle a #private directive. @@ -1164,15 +1172,8 @@ void Preprocessor::HandleMacroPrivateDirective(Token &Tok) { } // Note that this macro has now been marked private. - MD->setVisibility(/*IsPublic=*/false, MacroNameTok.getLocation()); - - // If this macro directive came from a PCH file, mark it as having changed - // since serialization. - if (MD->isFromPCH()) { - MD->setChangedAfterLoad(); - assert(II->isFromAST()); - II->setChangedSinceDeserialization(); - } + appendMacroDirective(II, AllocateVisibilityMacroDirective( + MacroNameTok.getLocation(), /*IsPublic=*/false)); } //===----------------------------------------------------------------------===// @@ -1960,7 +1961,8 @@ void Preprocessor::HandleDefineDirective(Token &DefineTok) { WarnUnusedMacroLocs.erase(OtherMI->getDefinitionLoc()); } - MacroDirective *MD = setMacroDirective(MacroNameTok.getIdentifierInfo(), MI); + DefMacroDirective *MD = + appendDefMacroDirective(MacroNameTok.getIdentifierInfo(), MI); assert(!MI->isUsed()); // If we need warning for not using the macro, add its location in the @@ -1994,7 +1996,7 @@ void Preprocessor::HandleUndefDirective(Token &UndefTok) { // Okay, we finally have a valid identifier to undef. MacroDirective *MD = getMacroDirective(MacroNameTok.getIdentifierInfo()); - const MacroInfo *MI = MD ? MD->getInfo() : 0; + const MacroInfo *MI = MD ? MD->getMacroInfo() : 0; // If the callbacks want to know, tell them about the macro #undef. // Note: no matter if the macro was defined or not. @@ -2010,20 +2012,8 @@ void Preprocessor::HandleUndefDirective(Token &UndefTok) { if (MI->isWarnIfUnused()) WarnUnusedMacroLocs.erase(MI->getDefinitionLoc()); - UndefineMacro(MacroNameTok.getIdentifierInfo(), MD, - MacroNameTok.getLocation()); -} - -void Preprocessor::UndefineMacro(IdentifierInfo *II, MacroDirective *MD, - SourceLocation UndefLoc) { - MD->setUndefLoc(UndefLoc); - if (MD->isFromPCH()) { - MD->setChangedAfterLoad(); - if (Listener) - Listener->UndefinedMacro(MD); - } - - clearMacroInfo(II); + appendMacroDirective(MacroNameTok.getIdentifierInfo(), + AllocateUndefMacroDirective(MacroNameTok.getLocation())); } @@ -2058,7 +2048,7 @@ void Preprocessor::HandleIfdefDirective(Token &Result, bool isIfndef, IdentifierInfo *MII = MacroNameTok.getIdentifierInfo(); MacroDirective *MD = getMacroDirective(MII); - MacroInfo *MI = MD ? MD->getInfo() : 0; + MacroInfo *MI = MD ? MD->getMacroInfo() : 0; if (CurPPLexer->getConditionalStackDepth() == 0) { // If the start of a top-level #ifdef and if the macro is not defined, diff --git a/lib/Lex/PPExpressions.cpp b/lib/Lex/PPExpressions.cpp index 27ad7b4a1b..d9ce8bff23 100644 --- a/lib/Lex/PPExpressions.cpp +++ b/lib/Lex/PPExpressions.cpp @@ -116,7 +116,7 @@ static bool EvaluateDefined(PPValue &Result, Token &PeekTok, DefinedTracker &DT, // If there is a macro, mark it used. if (Result.Val != 0 && ValueLive) { Macro = PP.getMacroDirective(II); - PP.markMacroAsUsed(Macro->getInfo()); + PP.markMacroAsUsed(Macro->getMacroInfo()); } // Invoke the 'defined' callback. diff --git a/lib/Lex/PPMacroExpansion.cpp b/lib/Lex/PPMacroExpansion.cpp index 868820b400..bb2634ffb6 100644 --- a/lib/Lex/PPMacroExpansion.cpp +++ b/lib/Lex/PPMacroExpansion.cpp @@ -41,15 +41,17 @@ Preprocessor::getMacroDirectiveHistory(const IdentifierInfo *II) const { return Pos->second; } -/// \brief Specify a macro for this identifier. -void Preprocessor::setMacroDirective(IdentifierInfo *II, MacroDirective *MD) { +void Preprocessor::appendMacroDirective(IdentifierInfo *II, MacroDirective *MD){ assert(MD && "MacroDirective should be non-zero!"); + assert(!MD->getPrevious() && "Already attached to a MacroDirective history."); MacroDirective *&StoredMD = Macros[II]; MD->setPrevious(StoredMD); StoredMD = MD; - II->setHasMacroDefinition(true); - if (II->isFromAST()) + II->setHasMacroDefinition(MD->isDefined()); + bool isImportedMacro = isa<DefMacroDirective>(MD) && + cast<DefMacroDirective>(MD)->isImported(); + if (II->isFromAST() && !isImportedMacro) II->setChangedSinceDeserialization(); } @@ -66,112 +68,6 @@ void Preprocessor::setLoadedMacroDirective(IdentifierInfo *II, II->setHasMacroDefinition(false); } -void Preprocessor::addLoadedMacroInfo(IdentifierInfo *II, MacroDirective *MD, - MacroDirective *Hint) { - assert(MD && "Missing macro?"); - assert(MD->isImported() && "Macro is not from an AST?"); - assert(!MD->getPrevious() && "Macro already in chain?"); - - MacroDirective *&StoredMD = Macros[II]; - - // Easy case: this is the first macro definition for this macro. - if (!StoredMD) { - StoredMD = MD; - - if (MD->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 (MD->isDefined() && StoredMD->isImported()) { - // Simple case: if this is the first actual definition, just put it at - // th beginning. - if (!StoredMD->isDefined()) { - MD->setPrevious(StoredMD); - StoredMD = MD; - - II->setHasMacroDefinition(true); - return; - } - - // Find the end of the definition chain. - MacroDirective *Prev; - MacroDirective *PrevPrev = StoredMD; - bool Ambiguous = StoredMD->isAmbiguous(); - bool MatchedOther = false; - do { - Prev = PrevPrev; - - // If the macros are not identical, we have an ambiguity. - if (!Prev->getInfo()->isIdenticalTo(*MD->getInfo(), *this)) { - if (!Ambiguous) { - Ambiguous = true; - StoredMD->setAmbiguous(true); - } - } else { - MatchedOther = true; - } - } while ((PrevPrev = Prev->getPrevious()) && - PrevPrev->isDefined()); - - // If there are ambiguous definitions, and we didn't match any other - // definition, then mark us as ambiguous. - if (Ambiguous && !MatchedOther) - MD->setAmbiguous(true); - - // Wire this macro information into the chain. - MD->setPrevious(Prev->getPrevious()); - Prev->setPrevious(MD); - return; - } - - // The macro is not a definition; put it at the end of the list. - MacroDirective *Prev = Hint? Hint : StoredMD; - while (Prev->getPrevious()) - Prev = Prev->getPrevious(); - Prev->setPrevious(MD); -} - -void Preprocessor::makeLoadedMacroInfoVisible(IdentifierInfo *II, - MacroDirective *MD) { - assert(MD->isImported() && "Macro must be from the AST"); - - MacroDirective *&StoredMD = Macros[II]; - if (StoredMD == MD) { - // Easy case: this is the first macro anyway. - II->setHasMacroDefinition(MD->isDefined()); - 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 or hidden - // would be quadratic, but it's extremely rare. - MacroDirective *Prev = StoredMD; - while (Prev->getPrevious() != MD) - Prev = Prev->getPrevious(); - Prev->setPrevious(MD->getPrevious()); - MD->setPrevious(0); - - // Add the macro back to the list. - addLoadedMacroInfo(II, MD); - - II->setHasMacroDefinition(StoredMD->isDefined()); - if (II->isFromAST()) - II->setChangedSinceDeserialization(); -} - -/// \brief Undefine a macro for this identifier. -void Preprocessor::clearMacroInfo(IdentifierInfo *II) { - assert(II->hasMacroDefinition() && "Macro is not defined!"); - assert(Macros[II]->getUndefLoc().isValid() && "Macro is still defined!"); - II->setHasMacroDefinition(false); - if (II->isFromAST()) - II->setChangedSinceDeserialization(); -} - /// RegisterBuiltinMacro - Register the specified identifier in the identifier /// table and mark it as a builtin macro to be expanded. static IdentifierInfo *RegisterBuiltinMacro(Preprocessor &PP, const char *Name){ @@ -181,7 +77,7 @@ static IdentifierInfo *RegisterBuiltinMacro(Preprocessor &PP, const char *Name){ // Mark it as being a macro that is builtin. MacroInfo *MI = PP.AllocateMacroInfo(SourceLocation()); MI->setIsBuiltinMacro(); - PP.setMacroDirective(Id, MI); + PP.appendDefMacroDirective(Id, MI); return Id; } @@ -315,7 +211,7 @@ bool Preprocessor::isNextPPTokenLParen() { /// expanded as a macro, handle it and return the next token as 'Identifier'. bool Preprocessor::HandleMacroExpandedIdentifier(Token &Identifier, MacroDirective *MD) { - MacroInfo *MI = MD->getInfo(); + MacroInfo *MI = MD->getMacroInfo(); // If this is a macro expansion in the "#if !defined(x)" line for the file, // then the macro could expand to different things in other contexts, we need diff --git a/lib/Lex/Pragma.cpp b/lib/Lex/Pragma.cpp index 2094dd1e1c..95e8a8ca8f 100644 --- a/lib/Lex/Pragma.cpp +++ b/lib/Lex/Pragma.cpp @@ -703,9 +703,10 @@ void Preprocessor::HandlePragmaPopMacro(Token &PopMacroTok) { if (iter != PragmaPushMacroInfo.end()) { // Forget the MacroInfo currently associated with IdentInfo. if (MacroDirective *CurrentMD = getMacroDirective(IdentInfo)) { - if (CurrentMD->getInfo()->isWarnIfUnused()) - WarnUnusedMacroLocs.erase(CurrentMD->getInfo()->getDefinitionLoc()); - UndefineMacro(IdentInfo, CurrentMD, MessageLoc); + MacroInfo *MI = CurrentMD->getMacroInfo(); + if (MI->isWarnIfUnused()) + WarnUnusedMacroLocs.erase(MI->getDefinitionLoc()); + appendMacroDirective(IdentInfo, AllocateUndefMacroDirective(MessageLoc)); } // Get the MacroInfo we want to reinstall. @@ -713,10 +714,8 @@ void Preprocessor::HandlePragmaPopMacro(Token &PopMacroTok) { if (MacroToReInstall) { // Reinstall the previously pushed macro. - setMacroDirective(IdentInfo, MacroToReInstall, MessageLoc, - /*isImported=*/false); - } else if (IdentInfo->hasMacroDefinition()) { - clearMacroInfo(IdentInfo); + appendDefMacroDirective(IdentInfo, MacroToReInstall, MessageLoc, + /*isImported=*/false); } // Pop PragmaPushMacroInfo stack. diff --git a/lib/Lex/PreprocessingRecord.cpp b/lib/Lex/PreprocessingRecord.cpp index b834d6cfb8..b10e7f7bee 100644 --- a/lib/Lex/PreprocessingRecord.cpp +++ b/lib/Lex/PreprocessingRecord.cpp @@ -385,31 +385,34 @@ void PreprocessingRecord::Ifdef(SourceLocation Loc, const Token &MacroNameTok, const MacroDirective *MD) { // This is not actually a macro expansion but record it as a macro reference. if (MD) - addMacroExpansion(MacroNameTok, MD->getInfo(), MacroNameTok.getLocation()); + addMacroExpansion(MacroNameTok, MD->getMacroInfo(), + MacroNameTok.getLocation()); } void PreprocessingRecord::Ifndef(SourceLocation Loc, const Token &MacroNameTok, const MacroDirective *MD) { // This is not actually a macro expansion but record it as a macro reference. if (MD) - addMacroExpansion(MacroNameTok, MD->getInfo(), MacroNameTok.getLocation()); + addMacroExpansion(MacroNameTok, MD->getMacroInfo(), + MacroNameTok.getLocation()); } void PreprocessingRecord::Defined(const Token &MacroNameTok, const MacroDirective *MD) { // This is not actually a macro expansion but record it as a macro reference. if (MD) - addMacroExpansion(MacroNameTok, MD->getInfo(), MacroNameTok.getLocation()); + addMacroExpansion(MacroNameTok, MD->getMacroInfo(), + MacroNameTok.getLocation()); } void PreprocessingRecord::MacroExpands(const Token &Id,const MacroDirective *MD, SourceRange Range) { - addMacroExpansion(Id, MD->getInfo(), Range); + addMacroExpansion(Id, MD->getMacroInfo(), Range); } void PreprocessingRecord::MacroDefined(const Token &Id, const MacroDirective *MD) { - const MacroInfo *MI = MD->getInfo(); + const MacroInfo *MI = MD->getMacroInfo(); SourceRange R(MI->getDefinitionLoc(), MI->getDefinitionEndLoc()); MacroDefinition *Def = new (*this) MacroDefinition(Id.getIdentifierInfo(), R); @@ -421,7 +424,7 @@ void PreprocessingRecord::MacroUndefined(const Token &Id, const MacroDirective *MD) { // Note: MI may be null (when #undef'ining an undefined macro). if (MD) - MacroDefinitions.erase(MD->getInfo()); + MacroDefinitions.erase(MD->getMacroInfo()); } void PreprocessingRecord::InclusionDirective( diff --git a/lib/Lex/Preprocessor.cpp b/lib/Lex/Preprocessor.cpp index af000ec1d1..bda72be555 100644 --- a/lib/Lex/Preprocessor.cpp +++ b/lib/Lex/Preprocessor.cpp @@ -306,15 +306,15 @@ StringRef Preprocessor::getLastMacroWithSpelling( StringRef BestSpelling; for (Preprocessor::macro_iterator I = macro_begin(), E = macro_end(); I != E; ++I) { - if (!I->second->getInfo()->isObjectLike()) + if (!I->second->getMacroInfo()->isObjectLike()) continue; - const MacroDirective * - MD = I->second->findDirectiveAtLoc(Loc, SourceMgr); - if (!MD) + const MacroDirective::DefInfo + Def = I->second->findDirectiveAtLoc(Loc, SourceMgr); + if (!Def) continue; - if (!MacroDefinitionEquals(MD->getInfo(), Tokens)) + if (!MacroDefinitionEquals(Def.getMacroInfo(), Tokens)) continue; - SourceLocation Location = I->second->getInfo()->getDefinitionLoc(); + SourceLocation Location = Def.getLocation(); // Choose the macro defined latest. if (BestLocation.isInvalid() || (Location.isValid() && @@ -643,7 +643,7 @@ void Preprocessor::HandleIdentifier(Token &Identifier) { // If this is a macro to be expanded, do it. if (MacroDirective *MD = getMacroDirective(&II)) { - MacroInfo *MI = MD->getInfo(); + MacroInfo *MI = MD->getMacroInfo(); if (!DisableMacroExpansion) { if (!Identifier.isExpandDisabled() && MI->isEnabled()) { if (!HandleMacroExpandedIdentifier(Identifier, MD)) diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp index 34c83edcde..2fa08fd5e1 100644 --- a/lib/Sema/SemaCodeComplete.cpp +++ b/lib/Sema/SemaCodeComplete.cpp @@ -2575,7 +2575,7 @@ CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx, if (Kind == RK_Macro) { const MacroDirective *MD = PP.getMacroDirectiveHistory(Macro); assert(MD && "Not a macro?"); - const MacroInfo *MI = MD->getInfo(); + const MacroInfo *MI = MD->getMacroInfo(); Result.AddTypedTextChunk( Result.getAllocator().CopyString(Macro->getName())); diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp index c6dbfe1498..837524dec8 100644 --- a/lib/Serialization/ASTReader.cpp +++ b/lib/Serialization/ASTReader.cpp @@ -1476,8 +1476,8 @@ void ASTReader::resolvePendingMacro(IdentifierInfo *II, MacroInfo *MI = getMacro(GMacID); SubmoduleID SubModID = MI->getOwningModuleID(); - MacroDirective *MD = PP.AllocateMacroDirective(MI, ImportLoc, - /*isImported=*/true); + MacroDirective *MD = PP.AllocateDefMacroDirective(MI, ImportLoc, + /*isImported=*/true); // Determine whether this macro definition is visible. bool Hidden = false; @@ -1494,7 +1494,6 @@ void ASTReader::resolvePendingMacro(IdentifierInfo *II, } } } - MD->setHidden(Hidden); if (!Hidden) installImportedMacro(II, MD); @@ -1527,22 +1526,30 @@ void ASTReader::installPCHMacroDirectives(IdentifierInfo *II, MacroDirective *Latest = 0, *Earliest = 0; unsigned Idx = 0, N = Record.size(); while (Idx < N) { - GlobalMacroID GMacID = getGlobalMacroID(M, Record[Idx++]); - MacroInfo *MI = getMacro(GMacID); + MacroDirective *MD = 0; SourceLocation Loc = ReadSourceLocation(M, Record, Idx); - SourceLocation UndefLoc = ReadSourceLocation(M, Record, Idx); - SourceLocation VisibilityLoc = ReadSourceLocation(M, Record, Idx); - bool isImported = Record[Idx++]; - bool isPublic = Record[Idx++]; - bool isAmbiguous = Record[Idx++]; - - MacroDirective *MD = PP.AllocateMacroDirective(MI, Loc, isImported); - if (UndefLoc.isValid()) - MD->setUndefLoc(UndefLoc); - if (VisibilityLoc.isValid()) - MD->setVisibility(isPublic, VisibilityLoc); - MD->setAmbiguous(isAmbiguous); - MD->setIsFromPCH(); + MacroDirective::Kind K = (MacroDirective::Kind)Record[Idx++]; + switch (K) { + case MacroDirective::MD_Define: { + GlobalMacroID GMacID = getGlobalMacroID(M, Record[Idx++]); + MacroInfo *MI = getMacro(GMacID); + bool isImported = Record[Idx++]; + bool isAmbiguous = Record[Idx++]; + DefMacroDirective *DefMD = + PP.AllocateDefMacroDirective(MI, Loc, isImported); + DefMD->setAmbiguous(isAmbiguous); + MD = DefMD; + break; + } + case MacroDirective::MD_Undefine: + MD = PP.AllocateUndefMacroDirective(Loc); + break; + case MacroDirective::MD_Visibility: { + bool isPublic = Record[Idx++]; + MD = PP.AllocateVisibilityMacroDirective(Loc, isPublic); + break; + } + } if (!Latest) Latest = MD; @@ -1557,13 +1564,18 @@ void ASTReader::installPCHMacroDirectives(IdentifierInfo *II, void ASTReader::installImportedMacro(IdentifierInfo *II, MacroDirective *MD) { assert(II && MD); + DefMacroDirective *DefMD = cast<DefMacroDirective>(MD); MacroDirective *Prev = PP.getMacroDirective(II); - if (Prev && !Prev->getInfo()->isIdenticalTo(*MD->getInfo(), PP)) { - Prev->setAmbiguous(true); - MD->setAmbiguous(true); + if (Prev) { + MacroDirective::DefInfo PrevDef = Prev->getDefinition(); + if (DefMD->getInfo() != PrevDef.getMacroInfo() && + !PrevDef.getMacroInfo()->isIdenticalTo(*DefMD->getInfo(), PP)) { + PrevDef.getDirective()->setAmbiguous(true); + DefMD->setAmbiguous(true); + } } - PP.setMacroDirective(II, MD); + PP.appendMacroDirective(II, MD); } InputFile ASTReader::getInputFile(ModuleFile &F, unsigned ID, bool Complain) { @@ -2723,21 +2735,12 @@ void ASTReader::makeNamesVisible(const HiddenNames &Names) { } case HiddenName::MacroVisibility: { std::pair<IdentifierInfo *, MacroDirective *> Macro = Names[I].getMacro(); - Macro.second->setHidden(!Macro.second->isPublic()); - if (Macro.second->isDefined()) { - installImportedMacro(Macro.first, Macro.second); - } + installImportedMacro(Macro.first, Macro.second); break; } case HiddenName::MacroUndef: { - std::pair<IdentifierInfo *, MacroDirective *> Macro = Names[I].getMacro(); - if (Macro.second->isDefined()) { - Macro.second->setUndefLoc(Names[I].getMacroUndefLoc()); - if (PPMutationListener *Listener = PP.getPPMutationListener()) - Listener->UndefinedMacro(Macro.second); - PP.makeLoadedMacroInfoVisible(Macro.first, Macro.second); - } + // FIXME: Remove HiddenName::MacroUndef and PPMutationListener. break; } } 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); } diff --git a/tools/libclang/CIndex.cpp b/tools/libclang/CIndex.cpp index 98891269d7..3c75e441b7 100644 --- a/tools/libclang/CIndex.cpp +++ b/tools/libclang/CIndex.cpp @@ -6305,10 +6305,12 @@ MacroInfo *cxindex::getMacroInfo(const IdentifierInfo &II, ASTUnit *Unit = cxtu::getASTUnit(TU); Preprocessor &PP = Unit->getPreprocessor(); MacroDirective *MD = PP.getMacroDirectiveHistory(&II); - while (MD) { - if (MacroDefLoc == MD->getInfo()->getDefinitionLoc()) - return MD->getInfo(); - MD = MD->getPrevious(); + if (MD) { + for (MacroDirective::DefInfo + Def = MD->getDefinition(); Def; Def = Def.getPreviousDefinition()) { + if (MacroDefLoc == Def.getMacroInfo()->getDefinitionLoc()) + return Def.getMacroInfo(); + } } return 0; @@ -6364,7 +6366,7 @@ MacroDefinition *cxindex::checkForMacroInMacroDefinition(const MacroInfo *MI, if (!InnerMD) return 0; - return PPRec->findMacroDefinition(InnerMD->getInfo()); + return PPRec->findMacroDefinition(InnerMD->getMacroInfo()); } MacroDefinition *cxindex::checkForMacroInMacroDefinition(const MacroInfo *MI, |