diff options
Diffstat (limited to 'include/clang/Lex/MacroInfo.h')
-rw-r--r-- | include/clang/Lex/MacroInfo.h | 236 |
1 files changed, 138 insertions, 98 deletions
diff --git a/include/clang/Lex/MacroInfo.h b/include/clang/Lex/MacroInfo.h index ca5d497..81d075c 100644 --- a/include/clang/Lex/MacroInfo.h +++ b/include/clang/Lex/MacroInfo.h @@ -17,11 +17,15 @@ #include "clang/Lex/Token.h" #include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/FoldingSet.h" +#include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/SmallVector.h" #include "llvm/Support/Allocator.h" #include <cassert> namespace clang { +class Module; +class ModuleMacro; class Preprocessor; /// \brief Encapsulates the data about a macro definition (e.g. its tokens). @@ -109,7 +113,7 @@ class MacroInfo { // Only the Preprocessor gets to create and destroy these. MacroInfo(SourceLocation DefLoc); - ~MacroInfo() {} + ~MacroInfo() = default; public: /// \brief Return the location that the macro was defined at. @@ -241,6 +245,7 @@ public: tokens_iterator tokens_begin() const { return ReplacementTokens.begin(); } tokens_iterator tokens_end() const { return ReplacementTokens.end(); } bool tokens_empty() const { return ReplacementTokens.empty(); } + ArrayRef<Token> tokens() const { return ReplacementTokens; } /// \brief Add the specified token to the replacement text for the macro. void AddTokenToBody(const Token &Tok) { @@ -302,15 +307,8 @@ class DefMacroDirective; /// /// MacroDirectives, associated with an identifier, are used to model the macro /// history. Usually a macro definition (MacroInfo) is where a macro name -/// becomes active (MacroDirective) but modules can have their own macro -/// history, separate from the local (current translation unit) macro history. -/// -/// For example, if "@import A;" imports macro FOO, there will be a new local -/// MacroDirective created to indicate that "FOO" became active at the import -/// location. Module "A" itself will contain another MacroDirective in its macro -/// history (at the point of the definition of FOO) and both MacroDirectives -/// will point to the same MacroInfo object. -/// +/// becomes active (MacroDirective) but #pragma push_macro / pop_macro can +/// create additional DefMacroDirectives for the same MacroInfo. class MacroDirective { public: enum Kind { @@ -331,47 +329,15 @@ protected: /// \brief True if the macro directive was loaded from a PCH file. bool IsFromPCH : 1; - // Used by DefMacroDirective -----------------------------------------------// - - /// \brief Whether the definition of this macro is ambiguous, due to - /// multiple definitions coming in from multiple modules. - bool IsAmbiguous : 1; - // Used by VisibilityMacroDirective ----------------------------------------// /// \brief Whether the macro has public visibility (when described in a /// module). bool IsPublic : 1; - // Used by DefMacroDirective and UndefMacroDirective -----------------------// - - /// \brief True if this macro was imported from a module. - bool IsImported : 1; - - /// \brief For an imported directive, the number of modules whose macros are - /// overridden by this directive. Only used if IsImported. - unsigned NumOverrides : 26; - - unsigned *getModuleDataStart(); - const unsigned *getModuleDataStart() const { - return const_cast<MacroDirective*>(this)->getModuleDataStart(); - } - - MacroDirective(Kind K, SourceLocation Loc, - unsigned ImportedFromModuleID = 0, - ArrayRef<unsigned> Overrides = None) + MacroDirective(Kind K, SourceLocation Loc) : Previous(nullptr), Loc(Loc), MDKind(K), IsFromPCH(false), - IsAmbiguous(false), IsPublic(true), IsImported(ImportedFromModuleID), - NumOverrides(Overrides.size()) { - assert(NumOverrides == Overrides.size() && "too many overrides"); - assert((IsImported || !NumOverrides) && "overrides for non-module macro"); - - if (IsImported) { - unsigned *Extra = getModuleDataStart(); - *Extra++ = ImportedFromModuleID; - std::copy(Overrides.begin(), Overrides.end(), Extra); - } - } + IsPublic(true) {} public: Kind getKind() const { return Kind(MDKind); } @@ -394,34 +360,13 @@ public: void setIsFromPCH() { IsFromPCH = true; } - /// \brief True if this macro was imported from a module. - /// Note that this is never the case for a VisibilityMacroDirective. - bool isImported() const { return IsImported; } - - /// \brief If this directive was imported from a module, get the submodule - /// whose directive this is. Note that this may be different from the module - /// that owns the MacroInfo for a DefMacroDirective due to #pragma pop_macro - /// and similar effects. - unsigned getOwningModuleID() const { - if (isImported()) - return *getModuleDataStart(); - return 0; - } - - /// \brief Get the module IDs of modules whose macros are overridden by this - /// directive. Only valid if this is an imported directive. - ArrayRef<unsigned> getOverriddenModules() const { - assert(IsImported && "can only get overridden modules for imported macro"); - return llvm::makeArrayRef(getModuleDataStart() + 1, NumOverrides); - } - class DefInfo { DefMacroDirective *DefDirective; SourceLocation UndefLoc; bool IsPublic; public: - DefInfo() : DefDirective(nullptr) { } + DefInfo() : DefDirective(nullptr), IsPublic(true) { } DefInfo(DefMacroDirective *DefDirective, SourceLocation UndefLoc, bool isPublic) @@ -444,7 +389,7 @@ public: bool isValid() const { return DefDirective != nullptr; } bool isInvalid() const { return !isValid(); } - LLVM_EXPLICIT operator bool() const { return isValid(); } + explicit operator bool() const { return isValid(); } inline DefInfo getPreviousDefinition(); const DefInfo getPreviousDefinition() const { @@ -487,30 +432,17 @@ class DefMacroDirective : public MacroDirective { MacroInfo *Info; public: - explicit DefMacroDirective(MacroInfo *MI) - : MacroDirective(MD_Define, MI->getDefinitionLoc()), Info(MI) { - assert(MI && "MacroInfo is null"); - } - - DefMacroDirective(MacroInfo *MI, SourceLocation Loc, - unsigned ImportedFromModuleID = 0, - ArrayRef<unsigned> Overrides = None) - : MacroDirective(MD_Define, Loc, ImportedFromModuleID, Overrides), - Info(MI) { + DefMacroDirective(MacroInfo *MI, SourceLocation Loc) + : MacroDirective(MD_Define, Loc), Info(MI) { assert(MI && "MacroInfo is null"); } + explicit DefMacroDirective(MacroInfo *MI) + : DefMacroDirective(MI, MI->getDefinitionLoc()) {} /// \brief The data for the macro definition. const MacroInfo *getInfo() const { return Info; } MacroInfo *getInfo() { return Info; } - /// \brief Determine whether this macro definition is ambiguous with - /// other macro definitions. - bool isAmbiguous() const { return IsAmbiguous; } - - /// \brief Set whether this macro definition is ambiguous. - void setAmbiguous(bool Val) { IsAmbiguous = Val; } - static bool classof(const MacroDirective *MD) { return MD->getKind() == MD_Define; } @@ -520,11 +452,9 @@ public: /// \brief A directive for an undefined macro. class UndefMacroDirective : public MacroDirective { public: - explicit UndefMacroDirective(SourceLocation UndefLoc, - unsigned ImportedFromModuleID = 0, - ArrayRef<unsigned> Overrides = None) - : MacroDirective(MD_Undefine, UndefLoc, ImportedFromModuleID, Overrides) { - assert((UndefLoc.isValid() || ImportedFromModuleID) && "Invalid UndefLoc!"); + explicit UndefMacroDirective(SourceLocation UndefLoc) + : MacroDirective(MD_Undefine, UndefLoc) { + assert(UndefLoc.isValid() && "Invalid UndefLoc!"); } static bool classof(const MacroDirective *MD) { @@ -537,7 +467,7 @@ public: class VisibilityMacroDirective : public MacroDirective { public: explicit VisibilityMacroDirective(SourceLocation Loc, bool Public) - : MacroDirective(MD_Visibility, Loc) { + : MacroDirective(MD_Visibility, Loc) { IsPublic = Public; } @@ -551,13 +481,6 @@ public: static bool classof(const VisibilityMacroDirective *) { return true; } }; -inline unsigned *MacroDirective::getModuleDataStart() { - if (auto *Def = dyn_cast<DefMacroDirective>(this)) - return reinterpret_cast<unsigned*>(Def + 1); - else - return reinterpret_cast<unsigned*>(cast<UndefMacroDirective>(this) + 1); -} - inline SourceLocation MacroDirective::DefInfo::getLocation() const { if (isInvalid()) return SourceLocation(); @@ -577,6 +500,123 @@ MacroDirective::DefInfo::getPreviousDefinition() { return DefDirective->getPrevious()->getDefinition(); } -} // end namespace clang +/// \brief Represents a macro directive exported by a module. +/// +/// There's an instance of this class for every macro #define or #undef that is +/// the final directive for a macro name within a module. These entities also +/// represent the macro override graph. +/// +/// These are stored in a FoldingSet in the preprocessor. +class ModuleMacro : public llvm::FoldingSetNode { + /// The name defined by the macro. + IdentifierInfo *II; + /// The body of the #define, or nullptr if this is a #undef. + MacroInfo *Macro; + /// The module that exports this macro. + Module *OwningModule; + /// The number of module macros that override this one. + unsigned NumOverriddenBy; + /// The number of modules whose macros are directly overridden by this one. + unsigned NumOverrides; + //ModuleMacro *OverriddenMacros[NumOverrides]; + + friend class Preprocessor; + + ModuleMacro(Module *OwningModule, IdentifierInfo *II, MacroInfo *Macro, + ArrayRef<ModuleMacro *> Overrides) + : II(II), Macro(Macro), OwningModule(OwningModule), + NumOverriddenBy(0), NumOverrides(Overrides.size()) { + std::copy(Overrides.begin(), Overrides.end(), + reinterpret_cast<ModuleMacro **>(this + 1)); + } + +public: + static ModuleMacro *create(Preprocessor &PP, Module *OwningModule, + IdentifierInfo *II, MacroInfo *Macro, + ArrayRef<ModuleMacro *> Overrides); + + void Profile(llvm::FoldingSetNodeID &ID) const { + return Profile(ID, OwningModule, II); + } + static void Profile(llvm::FoldingSetNodeID &ID, Module *OwningModule, + IdentifierInfo *II) { + ID.AddPointer(OwningModule); + ID.AddPointer(II); + } + + /// Get the ID of the module that exports this macro. + Module *getOwningModule() const { return OwningModule; } + + /// Get definition for this exported #define, or nullptr if this + /// represents a #undef. + MacroInfo *getMacroInfo() const { return Macro; } + + /// Iterators over the overridden module IDs. + /// \{ + typedef ModuleMacro *const *overrides_iterator; + overrides_iterator overrides_begin() const { + return reinterpret_cast<overrides_iterator>(this + 1); + } + overrides_iterator overrides_end() const { + return overrides_begin() + NumOverrides; + } + ArrayRef<ModuleMacro *> overrides() const { + return llvm::makeArrayRef(overrides_begin(), overrides_end()); + } + /// \} + + /// Get the number of macros that override this one. + unsigned getNumOverridingMacros() const { return NumOverriddenBy; } +}; + +/// \brief A description of the current definition of a macro. +/// +/// The definition of a macro comprises a set of (at least one) defining +/// entities, which are either local MacroDirectives or imported ModuleMacros. +class MacroDefinition { + llvm::PointerIntPair<DefMacroDirective *, 1, bool> LatestLocalAndAmbiguous; + ArrayRef<ModuleMacro *> ModuleMacros; + +public: + MacroDefinition() : LatestLocalAndAmbiguous(), ModuleMacros() {} + MacroDefinition(DefMacroDirective *MD, ArrayRef<ModuleMacro *> MMs, + bool IsAmbiguous) + : LatestLocalAndAmbiguous(MD, IsAmbiguous), ModuleMacros(MMs) {} + + /// \brief Determine whether there is a definition of this macro. + explicit operator bool() const { + return getLocalDirective() || !ModuleMacros.empty(); + } + + /// \brief Get the MacroInfo that should be used for this definition. + MacroInfo *getMacroInfo() const { + if (!ModuleMacros.empty()) + return ModuleMacros.back()->getMacroInfo(); + if (auto *MD = getLocalDirective()) + return MD->getMacroInfo(); + return nullptr; + } + + /// \brief \c true if the definition is ambiguous, \c false otherwise. + bool isAmbiguous() const { return LatestLocalAndAmbiguous.getInt(); } + + /// \brief Get the latest non-imported, non-\#undef'd macro definition + /// for this macro. + DefMacroDirective *getLocalDirective() const { + return LatestLocalAndAmbiguous.getPointer(); + } + + /// \brief Get the active module macros for this macro. + ArrayRef<ModuleMacro *> getModuleMacros() const { return ModuleMacros; } + + template <typename Fn> void forAllDefinitions(Fn F) const { + if (auto *MD = getLocalDirective()) + F(MD->getMacroInfo()); + for (auto *MM : getModuleMacros()) + F(MM->getMacroInfo()); + } +}; + +} // end namespace clang #endif |