10b57cec5SDimitry Andric //===- MacroInfo.h - Information about #defined identifiers -----*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric /// \file
100b57cec5SDimitry Andric /// Defines the clang::MacroInfo and clang::MacroDirective classes.
110b57cec5SDimitry Andric //
120b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric 
140b57cec5SDimitry Andric #ifndef LLVM_CLANG_LEX_MACROINFO_H
150b57cec5SDimitry Andric #define LLVM_CLANG_LEX_MACROINFO_H
160b57cec5SDimitry Andric 
170b57cec5SDimitry Andric #include "clang/Lex/Token.h"
180b57cec5SDimitry Andric #include "clang/Basic/LLVM.h"
190b57cec5SDimitry Andric #include "clang/Basic/SourceLocation.h"
200b57cec5SDimitry Andric #include "llvm/ADT/ArrayRef.h"
210b57cec5SDimitry Andric #include "llvm/ADT/FoldingSet.h"
220b57cec5SDimitry Andric #include "llvm/ADT/PointerIntPair.h"
230b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h"
240b57cec5SDimitry Andric #include "llvm/Support/Allocator.h"
250b57cec5SDimitry Andric #include <algorithm>
260b57cec5SDimitry Andric #include <cassert>
270b57cec5SDimitry Andric 
280b57cec5SDimitry Andric namespace clang {
290b57cec5SDimitry Andric 
300b57cec5SDimitry Andric class DefMacroDirective;
310b57cec5SDimitry Andric class IdentifierInfo;
320b57cec5SDimitry Andric class Module;
330b57cec5SDimitry Andric class Preprocessor;
340b57cec5SDimitry Andric class SourceManager;
350b57cec5SDimitry Andric 
360b57cec5SDimitry Andric /// Encapsulates the data about a macro definition (e.g. its tokens).
370b57cec5SDimitry Andric ///
380b57cec5SDimitry Andric /// There's an instance of this class for every #define.
390b57cec5SDimitry Andric class MacroInfo {
400b57cec5SDimitry Andric   //===--------------------------------------------------------------------===//
410b57cec5SDimitry Andric   // State set when the macro is defined.
420b57cec5SDimitry Andric 
430b57cec5SDimitry Andric   /// The location the macro is defined.
440b57cec5SDimitry Andric   SourceLocation Location;
450b57cec5SDimitry Andric 
460b57cec5SDimitry Andric   /// The location of the last token in the macro.
470b57cec5SDimitry Andric   SourceLocation EndLocation;
480b57cec5SDimitry Andric 
490b57cec5SDimitry Andric   /// The list of arguments for a function-like macro.
500b57cec5SDimitry Andric   ///
510b57cec5SDimitry Andric   /// ParameterList points to the first of NumParameters pointers.
520b57cec5SDimitry Andric   ///
530b57cec5SDimitry Andric   /// This can be empty, for, e.g. "#define X()".  In a C99-style variadic
540b57cec5SDimitry Andric   /// macro, this includes the \c __VA_ARGS__ identifier on the list.
550b57cec5SDimitry Andric   IdentifierInfo **ParameterList = nullptr;
560b57cec5SDimitry Andric 
5781ad6265SDimitry Andric   /// This is the list of tokens that the macro is defined to.
5881ad6265SDimitry Andric   const Token *ReplacementTokens = nullptr;
5981ad6265SDimitry Andric 
600b57cec5SDimitry Andric   /// \see ParameterList
610b57cec5SDimitry Andric   unsigned NumParameters = 0;
620b57cec5SDimitry Andric 
6381ad6265SDimitry Andric   /// \see ReplacementTokens
6481ad6265SDimitry Andric   unsigned NumReplacementTokens = 0;
650b57cec5SDimitry Andric 
660b57cec5SDimitry Andric   /// Length in characters of the macro definition.
670b57cec5SDimitry Andric   mutable unsigned DefinitionLength;
680b57cec5SDimitry Andric   mutable bool IsDefinitionLengthCached : 1;
690b57cec5SDimitry Andric 
700b57cec5SDimitry Andric   /// True if this macro is function-like, false if it is object-like.
710b57cec5SDimitry Andric   bool IsFunctionLike : 1;
720b57cec5SDimitry Andric 
730b57cec5SDimitry Andric   /// True if this macro is of the form "#define X(...)" or
740b57cec5SDimitry Andric   /// "#define X(Y,Z,...)".
750b57cec5SDimitry Andric   ///
760b57cec5SDimitry Andric   /// The __VA_ARGS__ token should be replaced with the contents of "..." in an
770b57cec5SDimitry Andric   /// invocation.
780b57cec5SDimitry Andric   bool IsC99Varargs : 1;
790b57cec5SDimitry Andric 
800b57cec5SDimitry Andric   /// True if this macro is of the form "#define X(a...)".
810b57cec5SDimitry Andric   ///
820b57cec5SDimitry Andric   /// The "a" identifier in the replacement list will be replaced with all
830b57cec5SDimitry Andric   /// arguments of the macro starting with the specified one.
840b57cec5SDimitry Andric   bool IsGNUVarargs : 1;
850b57cec5SDimitry Andric 
860b57cec5SDimitry Andric   /// True if this macro requires processing before expansion.
870b57cec5SDimitry Andric   ///
880b57cec5SDimitry Andric   /// This is the case for builtin macros such as __LINE__, so long as they have
890b57cec5SDimitry Andric   /// not been redefined, but not for regular predefined macros from the
900b57cec5SDimitry Andric   /// "<built-in>" memory buffer (see Preprocessing::getPredefinesFileID).
910b57cec5SDimitry Andric   bool IsBuiltinMacro : 1;
920b57cec5SDimitry Andric 
930b57cec5SDimitry Andric   /// Whether this macro contains the sequence ", ## __VA_ARGS__"
940b57cec5SDimitry Andric   bool HasCommaPasting : 1;
950b57cec5SDimitry Andric 
960b57cec5SDimitry Andric   //===--------------------------------------------------------------------===//
970b57cec5SDimitry Andric   // State that changes as the macro is used.
980b57cec5SDimitry Andric 
990b57cec5SDimitry Andric   /// True if we have started an expansion of this macro already.
1000b57cec5SDimitry Andric   ///
1010b57cec5SDimitry Andric   /// This disables recursive expansion, which would be quite bad for things
1020b57cec5SDimitry Andric   /// like \#define A A.
1030b57cec5SDimitry Andric   bool IsDisabled : 1;
1040b57cec5SDimitry Andric 
1050b57cec5SDimitry Andric   /// True if this macro is either defined in the main file and has
1060b57cec5SDimitry Andric   /// been used, or if it is not defined in the main file.
1070b57cec5SDimitry Andric   ///
1080b57cec5SDimitry Andric   /// This is used to emit -Wunused-macros diagnostics.
1090b57cec5SDimitry Andric   bool IsUsed : 1;
1100b57cec5SDimitry Andric 
1110b57cec5SDimitry Andric   /// True if this macro can be redefined without emitting a warning.
1120b57cec5SDimitry Andric   bool IsAllowRedefinitionsWithoutWarning : 1;
1130b57cec5SDimitry Andric 
1140b57cec5SDimitry Andric   /// Must warn if the macro is unused at the end of translation unit.
1150b57cec5SDimitry Andric   bool IsWarnIfUnused : 1;
1160b57cec5SDimitry Andric 
1170b57cec5SDimitry Andric   /// Whether this macro was used as header guard.
1180b57cec5SDimitry Andric   bool UsedForHeaderGuard : 1;
1190b57cec5SDimitry Andric 
120bdd1243dSDimitry Andric   // Only the Preprocessor gets to create these.
1210b57cec5SDimitry Andric   MacroInfo(SourceLocation DefLoc);
1220b57cec5SDimitry Andric 
1230b57cec5SDimitry Andric public:
1240b57cec5SDimitry Andric   /// Return the location that the macro was defined at.
getDefinitionLoc()1250b57cec5SDimitry Andric   SourceLocation getDefinitionLoc() const { return Location; }
1260b57cec5SDimitry Andric 
1270b57cec5SDimitry Andric   /// Set the location of the last token in the macro.
setDefinitionEndLoc(SourceLocation EndLoc)1280b57cec5SDimitry Andric   void setDefinitionEndLoc(SourceLocation EndLoc) { EndLocation = EndLoc; }
1290b57cec5SDimitry Andric 
1300b57cec5SDimitry Andric   /// Return the location of the last token in the macro.
getDefinitionEndLoc()1310b57cec5SDimitry Andric   SourceLocation getDefinitionEndLoc() const { return EndLocation; }
1320b57cec5SDimitry Andric 
1330b57cec5SDimitry Andric   /// Get length in characters of the macro definition.
getDefinitionLength(const SourceManager & SM)1340b57cec5SDimitry Andric   unsigned getDefinitionLength(const SourceManager &SM) const {
1350b57cec5SDimitry Andric     if (IsDefinitionLengthCached)
1360b57cec5SDimitry Andric       return DefinitionLength;
1370b57cec5SDimitry Andric     return getDefinitionLengthSlow(SM);
1380b57cec5SDimitry Andric   }
1390b57cec5SDimitry Andric 
1400b57cec5SDimitry Andric   /// Return true if the specified macro definition is equal to
1410b57cec5SDimitry Andric   /// this macro in spelling, arguments, and whitespace.
1420b57cec5SDimitry Andric   ///
1430b57cec5SDimitry Andric   /// \param Syntactically if true, the macro definitions can be identical even
1440b57cec5SDimitry Andric   /// if they use different identifiers for the function macro parameters.
1450b57cec5SDimitry Andric   /// Otherwise the comparison is lexical and this implements the rules in
1460b57cec5SDimitry Andric   /// C99 6.10.3.
1470b57cec5SDimitry Andric   bool isIdenticalTo(const MacroInfo &Other, Preprocessor &PP,
1480b57cec5SDimitry Andric                      bool Syntactically) const;
1490b57cec5SDimitry Andric 
1500b57cec5SDimitry Andric   /// Set or clear the isBuiltinMacro flag.
1510b57cec5SDimitry Andric   void setIsBuiltinMacro(bool Val = true) { IsBuiltinMacro = Val; }
1520b57cec5SDimitry Andric 
1530b57cec5SDimitry Andric   /// Set the value of the IsUsed flag.
setIsUsed(bool Val)1540b57cec5SDimitry Andric   void setIsUsed(bool Val) { IsUsed = Val; }
1550b57cec5SDimitry Andric 
1560b57cec5SDimitry Andric   /// Set the value of the IsAllowRedefinitionsWithoutWarning flag.
setIsAllowRedefinitionsWithoutWarning(bool Val)1570b57cec5SDimitry Andric   void setIsAllowRedefinitionsWithoutWarning(bool Val) {
1580b57cec5SDimitry Andric     IsAllowRedefinitionsWithoutWarning = Val;
1590b57cec5SDimitry Andric   }
1600b57cec5SDimitry Andric 
1610b57cec5SDimitry Andric   /// Set the value of the IsWarnIfUnused flag.
setIsWarnIfUnused(bool val)1620b57cec5SDimitry Andric   void setIsWarnIfUnused(bool val) { IsWarnIfUnused = val; }
1630b57cec5SDimitry Andric 
1640b57cec5SDimitry Andric   /// Set the specified list of identifiers as the parameter list for
1650b57cec5SDimitry Andric   /// this macro.
setParameterList(ArrayRef<IdentifierInfo * > List,llvm::BumpPtrAllocator & PPAllocator)1660b57cec5SDimitry Andric   void setParameterList(ArrayRef<IdentifierInfo *> List,
1670b57cec5SDimitry Andric                        llvm::BumpPtrAllocator &PPAllocator) {
1680b57cec5SDimitry Andric     assert(ParameterList == nullptr && NumParameters == 0 &&
1690b57cec5SDimitry Andric            "Parameter list already set!");
1700b57cec5SDimitry Andric     if (List.empty())
1710b57cec5SDimitry Andric       return;
1720b57cec5SDimitry Andric 
1730b57cec5SDimitry Andric     NumParameters = List.size();
1740b57cec5SDimitry Andric     ParameterList = PPAllocator.Allocate<IdentifierInfo *>(List.size());
1750b57cec5SDimitry Andric     std::copy(List.begin(), List.end(), ParameterList);
1760b57cec5SDimitry Andric   }
1770b57cec5SDimitry Andric 
1780b57cec5SDimitry Andric   /// Parameters - The list of parameters for a function-like macro.  This can
1790b57cec5SDimitry Andric   /// be empty, for, e.g. "#define X()".
1800b57cec5SDimitry Andric   using param_iterator = IdentifierInfo *const *;
param_empty()1810b57cec5SDimitry Andric   bool param_empty() const { return NumParameters == 0; }
param_begin()1820b57cec5SDimitry Andric   param_iterator param_begin() const { return ParameterList; }
param_end()1830b57cec5SDimitry Andric   param_iterator param_end() const { return ParameterList + NumParameters; }
getNumParams()1840b57cec5SDimitry Andric   unsigned getNumParams() const { return NumParameters; }
params()1850b57cec5SDimitry Andric   ArrayRef<const IdentifierInfo *> params() const {
1860b57cec5SDimitry Andric     return ArrayRef<const IdentifierInfo *>(ParameterList, NumParameters);
1870b57cec5SDimitry Andric   }
1880b57cec5SDimitry Andric 
1890b57cec5SDimitry Andric   /// Return the parameter number of the specified identifier,
1900b57cec5SDimitry Andric   /// or -1 if the identifier is not a formal parameter identifier.
getParameterNum(const IdentifierInfo * Arg)1910b57cec5SDimitry Andric   int getParameterNum(const IdentifierInfo *Arg) const {
1920b57cec5SDimitry Andric     for (param_iterator I = param_begin(), E = param_end(); I != E; ++I)
1930b57cec5SDimitry Andric       if (*I == Arg)
1940b57cec5SDimitry Andric         return I - param_begin();
1950b57cec5SDimitry Andric     return -1;
1960b57cec5SDimitry Andric   }
1970b57cec5SDimitry Andric 
1980b57cec5SDimitry Andric   /// Function/Object-likeness.  Keep track of whether this macro has formal
1990b57cec5SDimitry Andric   /// parameters.
setIsFunctionLike()2000b57cec5SDimitry Andric   void setIsFunctionLike() { IsFunctionLike = true; }
isFunctionLike()2010b57cec5SDimitry Andric   bool isFunctionLike() const { return IsFunctionLike; }
isObjectLike()2020b57cec5SDimitry Andric   bool isObjectLike() const { return !IsFunctionLike; }
2030b57cec5SDimitry Andric 
2040b57cec5SDimitry Andric   /// Varargs querying methods.  This can only be set for function-like macros.
setIsC99Varargs()2050b57cec5SDimitry Andric   void setIsC99Varargs() { IsC99Varargs = true; }
setIsGNUVarargs()2060b57cec5SDimitry Andric   void setIsGNUVarargs() { IsGNUVarargs = true; }
isC99Varargs()2070b57cec5SDimitry Andric   bool isC99Varargs() const { return IsC99Varargs; }
isGNUVarargs()2080b57cec5SDimitry Andric   bool isGNUVarargs() const { return IsGNUVarargs; }
isVariadic()20906c3fb27SDimitry Andric   bool isVariadic() const { return IsC99Varargs || IsGNUVarargs; }
2100b57cec5SDimitry Andric 
2110b57cec5SDimitry Andric   /// Return true if this macro requires processing before expansion.
2120b57cec5SDimitry Andric   ///
2130b57cec5SDimitry Andric   /// This is true only for builtin macro, such as \__LINE__, whose values
2140b57cec5SDimitry Andric   /// are not given by fixed textual expansions.  Regular predefined macros
2150b57cec5SDimitry Andric   /// from the "<built-in>" buffer are not reported as builtins by this
2160b57cec5SDimitry Andric   /// function.
isBuiltinMacro()2170b57cec5SDimitry Andric   bool isBuiltinMacro() const { return IsBuiltinMacro; }
2180b57cec5SDimitry Andric 
hasCommaPasting()2190b57cec5SDimitry Andric   bool hasCommaPasting() const { return HasCommaPasting; }
setHasCommaPasting()2200b57cec5SDimitry Andric   void setHasCommaPasting() { HasCommaPasting = true; }
2210b57cec5SDimitry Andric 
2220b57cec5SDimitry Andric   /// Return false if this macro is defined in the main file and has
2230b57cec5SDimitry Andric   /// not yet been used.
isUsed()2240b57cec5SDimitry Andric   bool isUsed() const { return IsUsed; }
2250b57cec5SDimitry Andric 
2260b57cec5SDimitry Andric   /// Return true if this macro can be redefined without warning.
isAllowRedefinitionsWithoutWarning()2270b57cec5SDimitry Andric   bool isAllowRedefinitionsWithoutWarning() const {
2280b57cec5SDimitry Andric     return IsAllowRedefinitionsWithoutWarning;
2290b57cec5SDimitry Andric   }
2300b57cec5SDimitry Andric 
2310b57cec5SDimitry Andric   /// Return true if we should emit a warning if the macro is unused.
isWarnIfUnused()2320b57cec5SDimitry Andric   bool isWarnIfUnused() const { return IsWarnIfUnused; }
2330b57cec5SDimitry Andric 
2340b57cec5SDimitry Andric   /// Return the number of tokens that this macro expands to.
getNumTokens()23581ad6265SDimitry Andric   unsigned getNumTokens() const { return NumReplacementTokens; }
2360b57cec5SDimitry Andric 
getReplacementToken(unsigned Tok)2370b57cec5SDimitry Andric   const Token &getReplacementToken(unsigned Tok) const {
23881ad6265SDimitry Andric     assert(Tok < NumReplacementTokens && "Invalid token #");
2390b57cec5SDimitry Andric     return ReplacementTokens[Tok];
2400b57cec5SDimitry Andric   }
2410b57cec5SDimitry Andric 
24281ad6265SDimitry Andric   using const_tokens_iterator = const Token *;
2430b57cec5SDimitry Andric 
tokens_begin()24481ad6265SDimitry Andric   const_tokens_iterator tokens_begin() const { return ReplacementTokens; }
tokens_end()24581ad6265SDimitry Andric   const_tokens_iterator tokens_end() const {
24681ad6265SDimitry Andric     return ReplacementTokens + NumReplacementTokens;
24781ad6265SDimitry Andric   }
tokens_empty()24881ad6265SDimitry Andric   bool tokens_empty() const { return NumReplacementTokens == 0; }
tokens()24981ad6265SDimitry Andric   ArrayRef<Token> tokens() const {
250bdd1243dSDimitry Andric     return llvm::ArrayRef(ReplacementTokens, NumReplacementTokens);
25181ad6265SDimitry Andric   }
2520b57cec5SDimitry Andric 
25381ad6265SDimitry Andric   llvm::MutableArrayRef<Token>
allocateTokens(unsigned NumTokens,llvm::BumpPtrAllocator & PPAllocator)25481ad6265SDimitry Andric   allocateTokens(unsigned NumTokens, llvm::BumpPtrAllocator &PPAllocator) {
25581ad6265SDimitry Andric     assert(ReplacementTokens == nullptr && NumReplacementTokens == 0 &&
25681ad6265SDimitry Andric            "Token list already allocated!");
25781ad6265SDimitry Andric     NumReplacementTokens = NumTokens;
25881ad6265SDimitry Andric     Token *NewReplacementTokens = PPAllocator.Allocate<Token>(NumTokens);
25981ad6265SDimitry Andric     ReplacementTokens = NewReplacementTokens;
260bdd1243dSDimitry Andric     return llvm::MutableArrayRef(NewReplacementTokens, NumTokens);
26181ad6265SDimitry Andric   }
26281ad6265SDimitry Andric 
setTokens(ArrayRef<Token> Tokens,llvm::BumpPtrAllocator & PPAllocator)26381ad6265SDimitry Andric   void setTokens(ArrayRef<Token> Tokens, llvm::BumpPtrAllocator &PPAllocator) {
2640b57cec5SDimitry Andric     assert(
2650b57cec5SDimitry Andric         !IsDefinitionLengthCached &&
2660b57cec5SDimitry Andric         "Changing replacement tokens after definition length got calculated");
26781ad6265SDimitry Andric     assert(ReplacementTokens == nullptr && NumReplacementTokens == 0 &&
26881ad6265SDimitry Andric            "Token list already set!");
26981ad6265SDimitry Andric     if (Tokens.empty())
27081ad6265SDimitry Andric       return;
27181ad6265SDimitry Andric 
27281ad6265SDimitry Andric     NumReplacementTokens = Tokens.size();
27381ad6265SDimitry Andric     Token *NewReplacementTokens = PPAllocator.Allocate<Token>(Tokens.size());
27481ad6265SDimitry Andric     std::copy(Tokens.begin(), Tokens.end(), NewReplacementTokens);
27581ad6265SDimitry Andric     ReplacementTokens = NewReplacementTokens;
2760b57cec5SDimitry Andric   }
2770b57cec5SDimitry Andric 
2780b57cec5SDimitry Andric   /// Return true if this macro is enabled.
2790b57cec5SDimitry Andric   ///
2800b57cec5SDimitry Andric   /// In other words, that we are not currently in an expansion of this macro.
isEnabled()2810b57cec5SDimitry Andric   bool isEnabled() const { return !IsDisabled; }
2820b57cec5SDimitry Andric 
EnableMacro()2830b57cec5SDimitry Andric   void EnableMacro() {
2840b57cec5SDimitry Andric     assert(IsDisabled && "Cannot enable an already-enabled macro!");
2850b57cec5SDimitry Andric     IsDisabled = false;
2860b57cec5SDimitry Andric   }
2870b57cec5SDimitry Andric 
DisableMacro()2880b57cec5SDimitry Andric   void DisableMacro() {
2890b57cec5SDimitry Andric     assert(!IsDisabled && "Cannot disable an already-disabled macro!");
2900b57cec5SDimitry Andric     IsDisabled = true;
2910b57cec5SDimitry Andric   }
2920b57cec5SDimitry Andric 
2930b57cec5SDimitry Andric   /// Determine whether this macro was used for a header guard.
isUsedForHeaderGuard()2940b57cec5SDimitry Andric   bool isUsedForHeaderGuard() const { return UsedForHeaderGuard; }
2950b57cec5SDimitry Andric 
setUsedForHeaderGuard(bool Val)2960b57cec5SDimitry Andric   void setUsedForHeaderGuard(bool Val) { UsedForHeaderGuard = Val; }
2970b57cec5SDimitry Andric 
2980b57cec5SDimitry Andric   void dump() const;
2990b57cec5SDimitry Andric 
3000b57cec5SDimitry Andric private:
3010b57cec5SDimitry Andric   friend class Preprocessor;
3020b57cec5SDimitry Andric 
3030b57cec5SDimitry Andric   unsigned getDefinitionLengthSlow(const SourceManager &SM) const;
3040b57cec5SDimitry Andric };
3050b57cec5SDimitry Andric 
3060b57cec5SDimitry Andric /// Encapsulates changes to the "macros namespace" (the location where
3070b57cec5SDimitry Andric /// the macro name became active, the location where it was undefined, etc.).
3080b57cec5SDimitry Andric ///
3090b57cec5SDimitry Andric /// MacroDirectives, associated with an identifier, are used to model the macro
3100b57cec5SDimitry Andric /// history. Usually a macro definition (MacroInfo) is where a macro name
3110b57cec5SDimitry Andric /// becomes active (MacroDirective) but #pragma push_macro / pop_macro can
3120b57cec5SDimitry Andric /// create additional DefMacroDirectives for the same MacroInfo.
3130b57cec5SDimitry Andric class MacroDirective {
3140b57cec5SDimitry Andric public:
3150b57cec5SDimitry Andric   enum Kind {
3160b57cec5SDimitry Andric     MD_Define,
3170b57cec5SDimitry Andric     MD_Undefine,
3180b57cec5SDimitry Andric     MD_Visibility
3190b57cec5SDimitry Andric   };
3200b57cec5SDimitry Andric 
3210b57cec5SDimitry Andric protected:
3220b57cec5SDimitry Andric   /// Previous macro directive for the same identifier, or nullptr.
3230b57cec5SDimitry Andric   MacroDirective *Previous = nullptr;
3240b57cec5SDimitry Andric 
3250b57cec5SDimitry Andric   SourceLocation Loc;
3260b57cec5SDimitry Andric 
3270b57cec5SDimitry Andric   /// MacroDirective kind.
3285f757f3fSDimitry Andric   LLVM_PREFERRED_TYPE(Kind)
3290b57cec5SDimitry Andric   unsigned MDKind : 2;
3300b57cec5SDimitry Andric 
3310b57cec5SDimitry Andric   /// True if the macro directive was loaded from a PCH file.
3325f757f3fSDimitry Andric   LLVM_PREFERRED_TYPE(bool)
3330b57cec5SDimitry Andric   unsigned IsFromPCH : 1;
3340b57cec5SDimitry Andric 
3350b57cec5SDimitry Andric   // Used by VisibilityMacroDirective ----------------------------------------//
3360b57cec5SDimitry Andric 
3370b57cec5SDimitry Andric   /// Whether the macro has public visibility (when described in a
3380b57cec5SDimitry Andric   /// module).
3395f757f3fSDimitry Andric   LLVM_PREFERRED_TYPE(bool)
3400b57cec5SDimitry Andric   unsigned IsPublic : 1;
3410b57cec5SDimitry Andric 
MacroDirective(Kind K,SourceLocation Loc)3420b57cec5SDimitry Andric   MacroDirective(Kind K, SourceLocation Loc)
3430b57cec5SDimitry Andric       : Loc(Loc), MDKind(K), IsFromPCH(false), IsPublic(true) {}
3440b57cec5SDimitry Andric 
3450b57cec5SDimitry Andric public:
getKind()3460b57cec5SDimitry Andric   Kind getKind() const { return Kind(MDKind); }
3470b57cec5SDimitry Andric 
getLocation()3480b57cec5SDimitry Andric   SourceLocation getLocation() const { return Loc; }
3490b57cec5SDimitry Andric 
3500b57cec5SDimitry Andric   /// Set previous definition of the macro with the same name.
setPrevious(MacroDirective * Prev)3510b57cec5SDimitry Andric   void setPrevious(MacroDirective *Prev) { Previous = Prev; }
3520b57cec5SDimitry Andric 
3530b57cec5SDimitry Andric   /// Get previous definition of the macro with the same name.
getPrevious()3540b57cec5SDimitry Andric   const MacroDirective *getPrevious() const { return Previous; }
3550b57cec5SDimitry Andric 
3560b57cec5SDimitry Andric   /// Get previous definition of the macro with the same name.
getPrevious()3570b57cec5SDimitry Andric   MacroDirective *getPrevious() { return Previous; }
3580b57cec5SDimitry Andric 
3590b57cec5SDimitry Andric   /// Return true if the macro directive was loaded from a PCH file.
isFromPCH()3600b57cec5SDimitry Andric   bool isFromPCH() const { return IsFromPCH; }
3610b57cec5SDimitry Andric 
setIsFromPCH()3620b57cec5SDimitry Andric   void setIsFromPCH() { IsFromPCH = true; }
3630b57cec5SDimitry Andric 
3640b57cec5SDimitry Andric   class DefInfo {
3650b57cec5SDimitry Andric     DefMacroDirective *DefDirective = nullptr;
3660b57cec5SDimitry Andric     SourceLocation UndefLoc;
3670b57cec5SDimitry Andric     bool IsPublic = true;
3680b57cec5SDimitry Andric 
3690b57cec5SDimitry Andric   public:
3700b57cec5SDimitry Andric     DefInfo() = default;
DefInfo(DefMacroDirective * DefDirective,SourceLocation UndefLoc,bool isPublic)3710b57cec5SDimitry Andric     DefInfo(DefMacroDirective *DefDirective, SourceLocation UndefLoc,
3720b57cec5SDimitry Andric             bool isPublic)
3730b57cec5SDimitry Andric         : DefDirective(DefDirective), UndefLoc(UndefLoc), IsPublic(isPublic) {}
3740b57cec5SDimitry Andric 
getDirective()3750b57cec5SDimitry Andric     const DefMacroDirective *getDirective() const { return DefDirective; }
getDirective()3760b57cec5SDimitry Andric     DefMacroDirective *getDirective() { return DefDirective; }
3770b57cec5SDimitry Andric 
3780b57cec5SDimitry Andric     inline SourceLocation getLocation() const;
3790b57cec5SDimitry Andric     inline MacroInfo *getMacroInfo();
3800b57cec5SDimitry Andric 
getMacroInfo()3810b57cec5SDimitry Andric     const MacroInfo *getMacroInfo() const {
3820b57cec5SDimitry Andric       return const_cast<DefInfo *>(this)->getMacroInfo();
3830b57cec5SDimitry Andric     }
3840b57cec5SDimitry Andric 
getUndefLocation()3850b57cec5SDimitry Andric     SourceLocation getUndefLocation() const { return UndefLoc; }
isUndefined()3860b57cec5SDimitry Andric     bool isUndefined() const { return UndefLoc.isValid(); }
3870b57cec5SDimitry Andric 
isPublic()3880b57cec5SDimitry Andric     bool isPublic() const { return IsPublic; }
3890b57cec5SDimitry Andric 
isValid()3900b57cec5SDimitry Andric     bool isValid() const { return DefDirective != nullptr; }
isInvalid()3910b57cec5SDimitry Andric     bool isInvalid() const { return !isValid(); }
3920b57cec5SDimitry Andric 
3930b57cec5SDimitry Andric     explicit operator bool() const { return isValid(); }
3940b57cec5SDimitry Andric 
3950b57cec5SDimitry Andric     inline DefInfo getPreviousDefinition();
3960b57cec5SDimitry Andric 
getPreviousDefinition()3970b57cec5SDimitry Andric     const DefInfo getPreviousDefinition() const {
3980b57cec5SDimitry Andric       return const_cast<DefInfo *>(this)->getPreviousDefinition();
3990b57cec5SDimitry Andric     }
4000b57cec5SDimitry Andric   };
4010b57cec5SDimitry Andric 
4020b57cec5SDimitry Andric   /// Traverses the macro directives history and returns the next
4030b57cec5SDimitry Andric   /// macro definition directive along with info about its undefined location
4040b57cec5SDimitry Andric   /// (if there is one) and if it is public or private.
4050b57cec5SDimitry Andric   DefInfo getDefinition();
getDefinition()4060b57cec5SDimitry Andric   const DefInfo getDefinition() const {
4070b57cec5SDimitry Andric     return const_cast<MacroDirective *>(this)->getDefinition();
4080b57cec5SDimitry Andric   }
4090b57cec5SDimitry Andric 
isDefined()4100b57cec5SDimitry Andric   bool isDefined() const {
4110b57cec5SDimitry Andric     if (const DefInfo Def = getDefinition())
4120b57cec5SDimitry Andric       return !Def.isUndefined();
4130b57cec5SDimitry Andric     return false;
4140b57cec5SDimitry Andric   }
4150b57cec5SDimitry Andric 
getMacroInfo()4160b57cec5SDimitry Andric   const MacroInfo *getMacroInfo() const {
4170b57cec5SDimitry Andric     return getDefinition().getMacroInfo();
4180b57cec5SDimitry Andric   }
getMacroInfo()4190b57cec5SDimitry Andric   MacroInfo *getMacroInfo() { return getDefinition().getMacroInfo(); }
4200b57cec5SDimitry Andric 
4210b57cec5SDimitry Andric   /// Find macro definition active in the specified source location. If
4220b57cec5SDimitry Andric   /// this macro was not defined there, return NULL.
4230b57cec5SDimitry Andric   const DefInfo findDirectiveAtLoc(SourceLocation L,
4240b57cec5SDimitry Andric                                    const SourceManager &SM) const;
4250b57cec5SDimitry Andric 
4260b57cec5SDimitry Andric   void dump() const;
4270b57cec5SDimitry Andric 
classof(const MacroDirective *)4280b57cec5SDimitry Andric   static bool classof(const MacroDirective *) { return true; }
4290b57cec5SDimitry Andric };
4300b57cec5SDimitry Andric 
4310b57cec5SDimitry Andric /// A directive for a defined macro or a macro imported from a module.
4320b57cec5SDimitry Andric class DefMacroDirective : public MacroDirective {
4330b57cec5SDimitry Andric   MacroInfo *Info;
4340b57cec5SDimitry Andric 
4350b57cec5SDimitry Andric public:
DefMacroDirective(MacroInfo * MI,SourceLocation Loc)4360b57cec5SDimitry Andric   DefMacroDirective(MacroInfo *MI, SourceLocation Loc)
4370b57cec5SDimitry Andric       : MacroDirective(MD_Define, Loc), Info(MI) {
4380b57cec5SDimitry Andric     assert(MI && "MacroInfo is null");
4390b57cec5SDimitry Andric   }
DefMacroDirective(MacroInfo * MI)4400b57cec5SDimitry Andric   explicit DefMacroDirective(MacroInfo *MI)
4410b57cec5SDimitry Andric       : DefMacroDirective(MI, MI->getDefinitionLoc()) {}
4420b57cec5SDimitry Andric 
4430b57cec5SDimitry Andric   /// The data for the macro definition.
getInfo()4440b57cec5SDimitry Andric   const MacroInfo *getInfo() const { return Info; }
getInfo()4450b57cec5SDimitry Andric   MacroInfo *getInfo() { return Info; }
4460b57cec5SDimitry Andric 
classof(const MacroDirective * MD)4470b57cec5SDimitry Andric   static bool classof(const MacroDirective *MD) {
4480b57cec5SDimitry Andric     return MD->getKind() == MD_Define;
4490b57cec5SDimitry Andric   }
4500b57cec5SDimitry Andric 
classof(const DefMacroDirective *)4510b57cec5SDimitry Andric   static bool classof(const DefMacroDirective *) { return true; }
4520b57cec5SDimitry Andric };
4530b57cec5SDimitry Andric 
4540b57cec5SDimitry Andric /// A directive for an undefined macro.
4550b57cec5SDimitry Andric class UndefMacroDirective : public MacroDirective {
4560b57cec5SDimitry Andric public:
UndefMacroDirective(SourceLocation UndefLoc)4570b57cec5SDimitry Andric   explicit UndefMacroDirective(SourceLocation UndefLoc)
4580b57cec5SDimitry Andric       : MacroDirective(MD_Undefine, UndefLoc) {
4590b57cec5SDimitry Andric     assert(UndefLoc.isValid() && "Invalid UndefLoc!");
4600b57cec5SDimitry Andric   }
4610b57cec5SDimitry Andric 
classof(const MacroDirective * MD)4620b57cec5SDimitry Andric   static bool classof(const MacroDirective *MD) {
4630b57cec5SDimitry Andric     return MD->getKind() == MD_Undefine;
4640b57cec5SDimitry Andric   }
4650b57cec5SDimitry Andric 
classof(const UndefMacroDirective *)4660b57cec5SDimitry Andric   static bool classof(const UndefMacroDirective *) { return true; }
4670b57cec5SDimitry Andric };
4680b57cec5SDimitry Andric 
4690b57cec5SDimitry Andric /// A directive for setting the module visibility of a macro.
4700b57cec5SDimitry Andric class VisibilityMacroDirective : public MacroDirective {
4710b57cec5SDimitry Andric public:
VisibilityMacroDirective(SourceLocation Loc,bool Public)4720b57cec5SDimitry Andric   explicit VisibilityMacroDirective(SourceLocation Loc, bool Public)
4730b57cec5SDimitry Andric       : MacroDirective(MD_Visibility, Loc) {
4740b57cec5SDimitry Andric     IsPublic = Public;
4750b57cec5SDimitry Andric   }
4760b57cec5SDimitry Andric 
4770b57cec5SDimitry Andric   /// Determine whether this macro is part of the public API of its
4780b57cec5SDimitry Andric   /// module.
isPublic()4790b57cec5SDimitry Andric   bool isPublic() const { return IsPublic; }
4800b57cec5SDimitry Andric 
classof(const MacroDirective * MD)4810b57cec5SDimitry Andric   static bool classof(const MacroDirective *MD) {
4820b57cec5SDimitry Andric     return MD->getKind() == MD_Visibility;
4830b57cec5SDimitry Andric   }
4840b57cec5SDimitry Andric 
classof(const VisibilityMacroDirective *)4850b57cec5SDimitry Andric   static bool classof(const VisibilityMacroDirective *) { return true; }
4860b57cec5SDimitry Andric };
4870b57cec5SDimitry Andric 
getLocation()4880b57cec5SDimitry Andric inline SourceLocation MacroDirective::DefInfo::getLocation() const {
4890b57cec5SDimitry Andric   if (isInvalid())
4900b57cec5SDimitry Andric     return {};
4910b57cec5SDimitry Andric   return DefDirective->getLocation();
4920b57cec5SDimitry Andric }
4930b57cec5SDimitry Andric 
getMacroInfo()4940b57cec5SDimitry Andric inline MacroInfo *MacroDirective::DefInfo::getMacroInfo() {
4950b57cec5SDimitry Andric   if (isInvalid())
4960b57cec5SDimitry Andric     return nullptr;
4970b57cec5SDimitry Andric   return DefDirective->getInfo();
4980b57cec5SDimitry Andric }
4990b57cec5SDimitry Andric 
5000b57cec5SDimitry Andric inline MacroDirective::DefInfo
getPreviousDefinition()5010b57cec5SDimitry Andric MacroDirective::DefInfo::getPreviousDefinition() {
5020b57cec5SDimitry Andric   if (isInvalid() || DefDirective->getPrevious() == nullptr)
5030b57cec5SDimitry Andric     return {};
5040b57cec5SDimitry Andric   return DefDirective->getPrevious()->getDefinition();
5050b57cec5SDimitry Andric }
5060b57cec5SDimitry Andric 
5070b57cec5SDimitry Andric /// Represents a macro directive exported by a module.
5080b57cec5SDimitry Andric ///
5090b57cec5SDimitry Andric /// There's an instance of this class for every macro #define or #undef that is
5100b57cec5SDimitry Andric /// the final directive for a macro name within a module. These entities also
5110b57cec5SDimitry Andric /// represent the macro override graph.
5120b57cec5SDimitry Andric ///
5130b57cec5SDimitry Andric /// These are stored in a FoldingSet in the preprocessor.
5140b57cec5SDimitry Andric class ModuleMacro : public llvm::FoldingSetNode {
5150b57cec5SDimitry Andric   friend class Preprocessor;
5160b57cec5SDimitry Andric 
5170b57cec5SDimitry Andric   /// The name defined by the macro.
5180b57cec5SDimitry Andric   IdentifierInfo *II;
5190b57cec5SDimitry Andric 
5200b57cec5SDimitry Andric   /// The body of the #define, or nullptr if this is a #undef.
5210b57cec5SDimitry Andric   MacroInfo *Macro;
5220b57cec5SDimitry Andric 
5230b57cec5SDimitry Andric   /// The module that exports this macro.
5240b57cec5SDimitry Andric   Module *OwningModule;
5250b57cec5SDimitry Andric 
5260b57cec5SDimitry Andric   /// The number of module macros that override this one.
5270b57cec5SDimitry Andric   unsigned NumOverriddenBy = 0;
5280b57cec5SDimitry Andric 
5290b57cec5SDimitry Andric   /// The number of modules whose macros are directly overridden by this one.
5300b57cec5SDimitry Andric   unsigned NumOverrides;
5310b57cec5SDimitry Andric 
ModuleMacro(Module * OwningModule,IdentifierInfo * II,MacroInfo * Macro,ArrayRef<ModuleMacro * > Overrides)5320b57cec5SDimitry Andric   ModuleMacro(Module *OwningModule, IdentifierInfo *II, MacroInfo *Macro,
5330b57cec5SDimitry Andric               ArrayRef<ModuleMacro *> Overrides)
5340b57cec5SDimitry Andric       : II(II), Macro(Macro), OwningModule(OwningModule),
5350b57cec5SDimitry Andric         NumOverrides(Overrides.size()) {
5360b57cec5SDimitry Andric     std::copy(Overrides.begin(), Overrides.end(),
5370b57cec5SDimitry Andric               reinterpret_cast<ModuleMacro **>(this + 1));
5380b57cec5SDimitry Andric   }
5390b57cec5SDimitry Andric 
5400b57cec5SDimitry Andric public:
5410b57cec5SDimitry Andric   static ModuleMacro *create(Preprocessor &PP, Module *OwningModule,
5420b57cec5SDimitry Andric                              IdentifierInfo *II, MacroInfo *Macro,
5430b57cec5SDimitry Andric                              ArrayRef<ModuleMacro *> Overrides);
5440b57cec5SDimitry Andric 
Profile(llvm::FoldingSetNodeID & ID)5450b57cec5SDimitry Andric   void Profile(llvm::FoldingSetNodeID &ID) const {
5460b57cec5SDimitry Andric     return Profile(ID, OwningModule, II);
5470b57cec5SDimitry Andric   }
5480b57cec5SDimitry Andric 
Profile(llvm::FoldingSetNodeID & ID,Module * OwningModule,const IdentifierInfo * II)5490b57cec5SDimitry Andric   static void Profile(llvm::FoldingSetNodeID &ID, Module *OwningModule,
550fe6060f1SDimitry Andric                       const IdentifierInfo *II) {
5510b57cec5SDimitry Andric     ID.AddPointer(OwningModule);
5520b57cec5SDimitry Andric     ID.AddPointer(II);
5530b57cec5SDimitry Andric   }
5540b57cec5SDimitry Andric 
5550b57cec5SDimitry Andric   /// Get the name of the macro.
getName()5560b57cec5SDimitry Andric   IdentifierInfo *getName() const { return II; }
5570b57cec5SDimitry Andric 
5580b57cec5SDimitry Andric   /// Get the ID of the module that exports this macro.
getOwningModule()5590b57cec5SDimitry Andric   Module *getOwningModule() const { return OwningModule; }
5600b57cec5SDimitry Andric 
5610b57cec5SDimitry Andric   /// Get definition for this exported #define, or nullptr if this
5620b57cec5SDimitry Andric   /// represents a #undef.
getMacroInfo()5630b57cec5SDimitry Andric   MacroInfo *getMacroInfo() const { return Macro; }
5640b57cec5SDimitry Andric 
5650b57cec5SDimitry Andric   /// Iterators over the overridden module IDs.
5660b57cec5SDimitry Andric   /// \{
5670b57cec5SDimitry Andric   using overrides_iterator = ModuleMacro *const *;
5680b57cec5SDimitry Andric 
overrides_begin()5690b57cec5SDimitry Andric   overrides_iterator overrides_begin() const {
5700b57cec5SDimitry Andric     return reinterpret_cast<overrides_iterator>(this + 1);
5710b57cec5SDimitry Andric   }
5720b57cec5SDimitry Andric 
overrides_end()5730b57cec5SDimitry Andric   overrides_iterator overrides_end() const {
5740b57cec5SDimitry Andric     return overrides_begin() + NumOverrides;
5750b57cec5SDimitry Andric   }
5760b57cec5SDimitry Andric 
overrides()5770b57cec5SDimitry Andric   ArrayRef<ModuleMacro *> overrides() const {
578bdd1243dSDimitry Andric     return llvm::ArrayRef(overrides_begin(), overrides_end());
5790b57cec5SDimitry Andric   }
5800b57cec5SDimitry Andric   /// \}
5810b57cec5SDimitry Andric 
5820b57cec5SDimitry Andric   /// Get the number of macros that override this one.
getNumOverridingMacros()5830b57cec5SDimitry Andric   unsigned getNumOverridingMacros() const { return NumOverriddenBy; }
5840b57cec5SDimitry Andric };
5850b57cec5SDimitry Andric 
5860b57cec5SDimitry Andric /// A description of the current definition of a macro.
5870b57cec5SDimitry Andric ///
5880b57cec5SDimitry Andric /// The definition of a macro comprises a set of (at least one) defining
5890b57cec5SDimitry Andric /// entities, which are either local MacroDirectives or imported ModuleMacros.
5900b57cec5SDimitry Andric class MacroDefinition {
5910b57cec5SDimitry Andric   llvm::PointerIntPair<DefMacroDirective *, 1, bool> LatestLocalAndAmbiguous;
5920b57cec5SDimitry Andric   ArrayRef<ModuleMacro *> ModuleMacros;
5930b57cec5SDimitry Andric 
5940b57cec5SDimitry Andric public:
5950b57cec5SDimitry Andric   MacroDefinition() = default;
MacroDefinition(DefMacroDirective * MD,ArrayRef<ModuleMacro * > MMs,bool IsAmbiguous)5960b57cec5SDimitry Andric   MacroDefinition(DefMacroDirective *MD, ArrayRef<ModuleMacro *> MMs,
5970b57cec5SDimitry Andric                   bool IsAmbiguous)
5980b57cec5SDimitry Andric       : LatestLocalAndAmbiguous(MD, IsAmbiguous), ModuleMacros(MMs) {}
5990b57cec5SDimitry Andric 
6000b57cec5SDimitry Andric   /// Determine whether there is a definition of this macro.
6010b57cec5SDimitry Andric   explicit operator bool() const {
6020b57cec5SDimitry Andric     return getLocalDirective() || !ModuleMacros.empty();
6030b57cec5SDimitry Andric   }
6040b57cec5SDimitry Andric 
6050b57cec5SDimitry Andric   /// Get the MacroInfo that should be used for this definition.
getMacroInfo()6060b57cec5SDimitry Andric   MacroInfo *getMacroInfo() const {
6070b57cec5SDimitry Andric     if (!ModuleMacros.empty())
6080b57cec5SDimitry Andric       return ModuleMacros.back()->getMacroInfo();
6090b57cec5SDimitry Andric     if (auto *MD = getLocalDirective())
6100b57cec5SDimitry Andric       return MD->getMacroInfo();
6110b57cec5SDimitry Andric     return nullptr;
6120b57cec5SDimitry Andric   }
6130b57cec5SDimitry Andric 
6140b57cec5SDimitry Andric   /// \c true if the definition is ambiguous, \c false otherwise.
isAmbiguous()6150b57cec5SDimitry Andric   bool isAmbiguous() const { return LatestLocalAndAmbiguous.getInt(); }
6160b57cec5SDimitry Andric 
6170b57cec5SDimitry Andric   /// Get the latest non-imported, non-\#undef'd macro definition
6180b57cec5SDimitry Andric   /// for this macro.
getLocalDirective()6190b57cec5SDimitry Andric   DefMacroDirective *getLocalDirective() const {
6200b57cec5SDimitry Andric     return LatestLocalAndAmbiguous.getPointer();
6210b57cec5SDimitry Andric   }
6220b57cec5SDimitry Andric 
6230b57cec5SDimitry Andric   /// Get the active module macros for this macro.
getModuleMacros()6240b57cec5SDimitry Andric   ArrayRef<ModuleMacro *> getModuleMacros() const { return ModuleMacros; }
6250b57cec5SDimitry Andric 
forAllDefinitions(Fn F)6260b57cec5SDimitry Andric   template <typename Fn> void forAllDefinitions(Fn F) const {
6270b57cec5SDimitry Andric     if (auto *MD = getLocalDirective())
6280b57cec5SDimitry Andric       F(MD->getMacroInfo());
6290b57cec5SDimitry Andric     for (auto *MM : getModuleMacros())
6300b57cec5SDimitry Andric       F(MM->getMacroInfo());
6310b57cec5SDimitry Andric   }
6320b57cec5SDimitry Andric };
6330b57cec5SDimitry Andric 
6340b57cec5SDimitry Andric } // namespace clang
6350b57cec5SDimitry Andric 
6360b57cec5SDimitry Andric #endif // LLVM_CLANG_LEX_MACROINFO_H
637