clang  19.0.0git
MacroInfo.cpp
Go to the documentation of this file.
1 //===- MacroInfo.cpp - Information about #defined identifiers -------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file implements the MacroInfo interface.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "clang/Lex/MacroInfo.h"
15 #include "clang/Basic/LLVM.h"
18 #include "clang/Basic/TokenKinds.h"
19 #include "clang/Lex/Preprocessor.h"
20 #include "clang/Lex/Token.h"
21 #include "llvm/ADT/StringRef.h"
22 #include "llvm/Support/Casting.h"
23 #include "llvm/Support/Compiler.h"
24 #include "llvm/Support/raw_ostream.h"
25 #include <cassert>
26 #include <optional>
27 #include <utility>
28 
29 using namespace clang;
30 
31 namespace {
32 
33 // MacroInfo is expected to take 40 bytes on platforms with an 8 byte pointer
34 // and 4 byte SourceLocation.
35 template <int> class MacroInfoSizeChecker {
36 public:
37  [[maybe_unused]] constexpr static bool AsExpected = true;
38 };
39 template <> class MacroInfoSizeChecker<8> {
40 public:
41  [[maybe_unused]] constexpr static bool AsExpected =
42  sizeof(MacroInfo) == (32 + sizeof(SourceLocation) * 2);
43 };
44 
45 static_assert(MacroInfoSizeChecker<sizeof(void *)>::AsExpected,
46  "Unexpected size of MacroInfo");
47 
48 } // end namespace
49 
50 MacroInfo::MacroInfo(SourceLocation DefLoc)
51  : Location(DefLoc), IsDefinitionLengthCached(false), IsFunctionLike(false),
52  IsC99Varargs(false), IsGNUVarargs(false), IsBuiltinMacro(false),
53  HasCommaPasting(false), IsDisabled(false), IsUsed(false),
54  IsAllowRedefinitionsWithoutWarning(false), IsWarnIfUnused(false),
55  UsedForHeaderGuard(false) {}
56 
57 unsigned MacroInfo::getDefinitionLengthSlow(const SourceManager &SM) const {
58  assert(!IsDefinitionLengthCached);
59  IsDefinitionLengthCached = true;
60 
61  ArrayRef<Token> ReplacementTokens = tokens();
62  if (ReplacementTokens.empty())
63  return (DefinitionLength = 0);
64 
65  const Token &firstToken = ReplacementTokens.front();
66  const Token &lastToken = ReplacementTokens.back();
67  SourceLocation macroStart = firstToken.getLocation();
68  SourceLocation macroEnd = lastToken.getLocation();
69  assert(macroStart.isValid() && macroEnd.isValid());
70  assert((macroStart.isFileID() || firstToken.is(tok::comment)) &&
71  "Macro defined in macro?");
72  assert((macroEnd.isFileID() || lastToken.is(tok::comment)) &&
73  "Macro defined in macro?");
74  std::pair<FileID, unsigned>
75  startInfo = SM.getDecomposedExpansionLoc(macroStart);
76  std::pair<FileID, unsigned>
77  endInfo = SM.getDecomposedExpansionLoc(macroEnd);
78  assert(startInfo.first == endInfo.first &&
79  "Macro definition spanning multiple FileIDs ?");
80  assert(startInfo.second <= endInfo.second);
81  DefinitionLength = endInfo.second - startInfo.second;
82  DefinitionLength += lastToken.getLength();
83 
84  return DefinitionLength;
85 }
86 
87 /// Return true if the specified macro definition is equal to
88 /// this macro in spelling, arguments, and whitespace.
89 ///
90 /// \param Syntactically if true, the macro definitions can be identical even
91 /// if they use different identifiers for the function macro parameters.
92 /// Otherwise the comparison is lexical and this implements the rules in
93 /// C99 6.10.3.
95  bool Syntactically) const {
96  bool Lexically = !Syntactically;
97 
98  // Check # tokens in replacement, number of args, and various flags all match.
99  if (getNumTokens() != Other.getNumTokens() ||
100  getNumParams() != Other.getNumParams() ||
101  isFunctionLike() != Other.isFunctionLike() ||
102  isC99Varargs() != Other.isC99Varargs() ||
103  isGNUVarargs() != Other.isGNUVarargs())
104  return false;
105 
106  if (Lexically) {
107  // Check arguments.
108  for (param_iterator I = param_begin(), OI = Other.param_begin(),
109  E = param_end();
110  I != E; ++I, ++OI)
111  if (*I != *OI) return false;
112  }
113 
114  // Check all the tokens.
115  for (unsigned i = 0; i != NumReplacementTokens; ++i) {
116  const Token &A = ReplacementTokens[i];
117  const Token &B = Other.ReplacementTokens[i];
118  if (A.getKind() != B.getKind())
119  return false;
120 
121  // If this isn't the first token, check that the whitespace and
122  // start-of-line characteristics match.
123  if (i != 0 &&
124  (A.isAtStartOfLine() != B.isAtStartOfLine() ||
125  A.hasLeadingSpace() != B.hasLeadingSpace()))
126  return false;
127 
128  // If this is an identifier, it is easy.
129  if (A.getIdentifierInfo() || B.getIdentifierInfo()) {
130  if (A.getIdentifierInfo() == B.getIdentifierInfo())
131  continue;
132  if (Lexically)
133  return false;
134  // With syntactic equivalence the parameter names can be different as long
135  // as they are used in the same place.
136  int AArgNum = getParameterNum(A.getIdentifierInfo());
137  if (AArgNum == -1)
138  return false;
139  if (AArgNum != Other.getParameterNum(B.getIdentifierInfo()))
140  return false;
141  continue;
142  }
143 
144  // Otherwise, check the spelling.
145  if (PP.getSpelling(A) != PP.getSpelling(B))
146  return false;
147  }
148 
149  return true;
150 }
151 
152 LLVM_DUMP_METHOD void MacroInfo::dump() const {
153  llvm::raw_ostream &Out = llvm::errs();
154 
155  // FIXME: Dump locations.
156  Out << "MacroInfo " << this;
157  if (IsBuiltinMacro) Out << " builtin";
158  if (IsDisabled) Out << " disabled";
159  if (IsUsed) Out << " used";
160  if (IsAllowRedefinitionsWithoutWarning)
161  Out << " allow_redefinitions_without_warning";
162  if (IsWarnIfUnused) Out << " warn_if_unused";
163  if (UsedForHeaderGuard) Out << " header_guard";
164 
165  Out << "\n #define <macro>";
166  if (IsFunctionLike) {
167  Out << "(";
168  for (unsigned I = 0; I != NumParameters; ++I) {
169  if (I) Out << ", ";
170  Out << ParameterList[I]->getName();
171  }
172  if (IsC99Varargs || IsGNUVarargs) {
173  if (NumParameters && IsC99Varargs) Out << ", ";
174  Out << "...";
175  }
176  Out << ")";
177  }
178 
179  bool First = true;
180  for (const Token &Tok : tokens()) {
181  // Leading space is semantically meaningful in a macro definition,
182  // so preserve it in the dump output.
183  if (First || Tok.hasLeadingSpace())
184  Out << " ";
185  First = false;
186 
187  if (const char *Punc = tok::getPunctuatorSpelling(Tok.getKind()))
188  Out << Punc;
189  else if (Tok.isLiteral() && Tok.getLiteralData())
190  Out << StringRef(Tok.getLiteralData(), Tok.getLength());
191  else if (auto *II = Tok.getIdentifierInfo())
192  Out << II->getName();
193  else
194  Out << Tok.getName();
195  }
196 }
197 
199  MacroDirective *MD = this;
200  SourceLocation UndefLoc;
201  std::optional<bool> isPublic;
202  for (; MD; MD = MD->getPrevious()) {
203  if (DefMacroDirective *DefMD = dyn_cast<DefMacroDirective>(MD))
204  return DefInfo(DefMD, UndefLoc, !isPublic || *isPublic);
205 
206  if (UndefMacroDirective *UndefMD = dyn_cast<UndefMacroDirective>(MD)) {
207  UndefLoc = UndefMD->getLocation();
208  continue;
209  }
210 
211  VisibilityMacroDirective *VisMD = cast<VisibilityMacroDirective>(MD);
212  if (!isPublic)
213  isPublic = VisMD->isPublic();
214  }
215 
216  return DefInfo(nullptr, UndefLoc, !isPublic || *isPublic);
217 }
218 
221  const SourceManager &SM) const {
222  assert(L.isValid() && "SourceLocation is invalid.");
223  for (DefInfo Def = getDefinition(); Def; Def = Def.getPreviousDefinition()) {
224  if (Def.getLocation().isInvalid() || // For macros defined on the command line.
225  SM.isBeforeInTranslationUnit(Def.getLocation(), L))
226  return (!Def.isUndefined() ||
227  SM.isBeforeInTranslationUnit(L, Def.getUndefLocation()))
228  ? Def : DefInfo();
229  }
230  return DefInfo();
231 }
232 
233 LLVM_DUMP_METHOD void MacroDirective::dump() const {
234  llvm::raw_ostream &Out = llvm::errs();
235 
236  switch (getKind()) {
237  case MD_Define: Out << "DefMacroDirective"; break;
238  case MD_Undefine: Out << "UndefMacroDirective"; break;
239  case MD_Visibility: Out << "VisibilityMacroDirective"; break;
240  }
241  Out << " " << this;
242  // FIXME: Dump SourceLocation.
243  if (auto *Prev = getPrevious())
244  Out << " prev " << Prev;
245  if (IsFromPCH) Out << " from_pch";
246 
247  if (isa<VisibilityMacroDirective>(this))
248  Out << (IsPublic ? " public" : " private");
249 
250  if (auto *DMD = dyn_cast<DefMacroDirective>(this)) {
251  if (auto *Info = DMD->getInfo()) {
252  Out << "\n ";
253  Info->dump();
254  }
255  }
256  Out << "\n";
257 }
258 
260  const IdentifierInfo *II, MacroInfo *Macro,
261  ArrayRef<ModuleMacro *> Overrides) {
262  void *Mem = PP.getPreprocessorAllocator().Allocate(
263  sizeof(ModuleMacro) + sizeof(ModuleMacro *) * Overrides.size(),
264  alignof(ModuleMacro));
265  return new (Mem) ModuleMacro(OwningModule, II, Macro, Overrides);
266 }
#define SM(sm)
Definition: Cuda.cpp:83
Defines the clang::IdentifierInfo, clang::IdentifierTable, and clang::Selector interfaces.
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.
Defines the clang::MacroInfo and clang::MacroDirective classes.
Defines the clang::Preprocessor interface.
Defines the clang::SourceLocation class and associated facilities.
Defines the SourceManager interface.
Defines the clang::TokenKind enum and support functions.
A directive for a defined macro or a macro imported from a module.
Definition: MacroInfo.h:432
One of these records is kept for each identifier that is lexed.
StringRef getName() const
Return the actual identifier string.
Encapsulates changes to the "macros namespace" (the location where the macro name became active,...
Definition: MacroInfo.h:313
const DefInfo findDirectiveAtLoc(SourceLocation L, const SourceManager &SM) const
Find macro definition active in the specified source location.
Definition: MacroInfo.cpp:220
unsigned IsPublic
Whether the macro has public visibility (when described in a module).
Definition: MacroInfo.h:340
const MacroDirective * getPrevious() const
Get previous definition of the macro with the same name.
Definition: MacroInfo.h:354
Kind getKind() const
Definition: MacroInfo.h:346
unsigned IsFromPCH
True if the macro directive was loaded from a PCH file.
Definition: MacroInfo.h:333
DefInfo getDefinition()
Traverses the macro directives history and returns the next macro definition directive along with inf...
Definition: MacroInfo.cpp:198
Encapsulates the data about a macro definition (e.g.
Definition: MacroInfo.h:39
bool isIdenticalTo(const MacroInfo &Other, Preprocessor &PP, bool Syntactically) const
Return true if the specified macro definition is equal to this macro in spelling, arguments,...
Definition: MacroInfo.cpp:94
bool isC99Varargs() const
Definition: MacroInfo.h:207
bool isFunctionLike() const
Definition: MacroInfo.h:201
param_iterator param_begin() const
Definition: MacroInfo.h:182
unsigned getNumTokens() const
Return the number of tokens that this macro expands to.
Definition: MacroInfo.h:235
void dump() const
Definition: MacroInfo.cpp:152
unsigned getNumParams() const
Definition: MacroInfo.h:184
IdentifierInfo *const * param_iterator
Parameters - The list of parameters for a function-like macro.
Definition: MacroInfo.h:180
param_iterator param_end() const
Definition: MacroInfo.h:183
int getParameterNum(const IdentifierInfo *Arg) const
Return the parameter number of the specified identifier, or -1 if the identifier is not a formal para...
Definition: MacroInfo.h:191
bool isGNUVarargs() const
Definition: MacroInfo.h:208
ArrayRef< Token > tokens() const
Definition: MacroInfo.h:249
Represents a macro directive exported by a module.
Definition: MacroInfo.h:514
static ModuleMacro * create(Preprocessor &PP, Module *OwningModule, const IdentifierInfo *II, MacroInfo *Macro, ArrayRef< ModuleMacro * > Overrides)
Definition: MacroInfo.cpp:259
Describes a module or submodule.
Definition: Module.h:105
Engages in a tight little dance with the lexer to efficiently preprocess tokens.
Definition: Preprocessor.h:128
StringRef getSpelling(SourceLocation loc, SmallVectorImpl< char > &buffer, bool *invalid=nullptr) const
Return the 'spelling' of the token at the given location; does not go up to the spelling location or ...
llvm::BumpPtrAllocator & getPreprocessorAllocator()
Encodes a location in the source.
bool isValid() const
Return true if this is a valid SourceLocation object.
This class handles loading and caching of source files into memory.
Token - This structure provides full information about a lexed token.
Definition: Token.h:36
SourceLocation getLocation() const
Return a source location identifier for the specified offset in the current file.
Definition: Token.h:132
unsigned getLength() const
Definition: Token.h:135
bool is(tok::TokenKind K) const
is/isNot - Predicates to check if this token is a specific kind, as in "if (Tok.is(tok::l_brace)) {....
Definition: Token.h:99
tok::TokenKind getKind() const
Definition: Token.h:94
bool isAtStartOfLine() const
isAtStartOfLine - Return true if this token is at the start of a line.
Definition: Token.h:276
IdentifierInfo * getIdentifierInfo() const
Definition: Token.h:187
bool hasLeadingSpace() const
Return true if this token has whitespace before it.
Definition: Token.h:280
A directive for an undefined macro.
Definition: MacroInfo.h:455
A directive for setting the module visibility of a macro.
Definition: MacroInfo.h:470
bool isPublic() const
Determine whether this macro is part of the public API of its module.
Definition: MacroInfo.h:479
const char * getPunctuatorSpelling(TokenKind Kind) LLVM_READNONE
Determines the spelling of simple punctuation tokens like '!' or '', and returns NULL for literal and...
Definition: TokenKinds.cpp:31
The JSON file list parser is used to communicate input to InstallAPI.
@ Other
Other implicit parameter.
#define false
Definition: stdbool.h:26