clang  16.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/Optional.h"
22 #include "llvm/ADT/StringRef.h"
23 #include "llvm/Support/Casting.h"
24 #include "llvm/Support/Compiler.h"
25 #include "llvm/Support/raw_ostream.h"
26 #include <cassert>
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  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.value());
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  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 }
clang::MacroInfo::getNumTokens
unsigned getNumTokens() const
Return the number of tokens that this macro expands to.
Definition: MacroInfo.h:235
clang::MacroInfo::param_begin
param_iterator param_begin() const
Definition: MacroInfo.h:182
clang::MacroDirective::MD_Undefine
@ MD_Undefine
Definition: MacroInfo.h:317
clang::Preprocessor::getPreprocessorAllocator
llvm::BumpPtrAllocator & getPreprocessorAllocator()
Definition: Preprocessor.h:1072
clang::Token::hasLeadingSpace
bool hasLeadingSpace() const
Return true if this token has whitespace before it.
Definition: Token.h:274
clang::MacroDirective::dump
void dump() const
Definition: MacroInfo.cpp:233
clang::SourceLocation
Encodes a location in the source.
Definition: SourceLocation.h:86
clang::MacroInfo::dump
void dump() const
Definition: MacroInfo.cpp:152
clang::Token::getIdentifierInfo
IdentifierInfo * getIdentifierInfo() const
Definition: Token.h:181
clang::MacroInfo::isIdenticalTo
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
clang::tok::getPunctuatorSpelling
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
clang::MacroInfo::tokens
ArrayRef< Token > tokens() const
Definition: MacroInfo.h:249
clang::Token::isAtStartOfLine
bool isAtStartOfLine() const
isAtStartOfLine - Return true if this token is at the start of a line.
Definition: Token.h:270
llvm::Optional< bool >
clang::ComparisonCategoryType::First
@ First
clang::MacroInfo
Encapsulates the data about a macro definition (e.g.
Definition: MacroInfo.h:39
SourceManager.h
clang::Token
Token - This structure provides full information about a lexed token.
Definition: Token.h:35
clang::VisibilityMacroDirective
A directive for setting the module visibility of a macro.
Definition: MacroInfo.h:467
clang::SourceManager
This class handles loading and caching of source files into memory.
Definition: SourceManager.h:637
Preprocessor.h
TokenKinds.h
clang::MacroDirective::getPrevious
const MacroDirective * getPrevious() const
Get previous definition of the macro with the same name.
Definition: MacroInfo.h:351
clang::Module
Describes a module or submodule.
Definition: Module.h:98
clang::MacroDirective::MD_Visibility
@ MD_Visibility
Definition: MacroInfo.h:318
clang::VisibilityMacroDirective::isPublic
bool isPublic() const
Determine whether this macro is part of the public API of its module.
Definition: MacroInfo.h:476
clang::MacroInfo::param_iterator
IdentifierInfo *const * param_iterator
Parameters - The list of parameters for a function-like macro.
Definition: MacroInfo.h:180
clang::Token::getKind
tok::TokenKind getKind() const
Definition: Token.h:93
clang::Token::is
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:98
IdentifierTable.h
clang::MacroDirective::findDirectiveAtLoc
const DefInfo findDirectiveAtLoc(SourceLocation L, const SourceManager &SM) const
Find macro definition active in the specified source location.
Definition: MacroInfo.cpp:220
clang::SourceLocation::isFileID
bool isFileID() const
Definition: SourceLocation.h:102
clang::MacroDirective::IsPublic
unsigned IsPublic
Whether the macro has public visibility (when described in a module).
Definition: MacroInfo.h:337
clang::Token::getLength
unsigned getLength() const
Definition: Token.h:129
clang::DefMacroDirective
A directive for a defined macro or a macro imported from a module.
Definition: MacroInfo.h:429
clang::UndefMacroDirective
A directive for an undefined macro.
Definition: MacroInfo.h:452
clang::Preprocessor::getSpelling
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 ...
Definition: Preprocessor.h:1913
SourceLocation.h
clang::MacroDirective::getDefinition
DefInfo getDefinition()
Traverses the macro directives history and returns the next macro definition directive along with inf...
Definition: MacroInfo.cpp:198
clang::MacroDirective::getKind
Kind getKind() const
Definition: MacroInfo.h:343
false
#define false
Definition: stdbool.h:22
clang::MacroInfo::isC99Varargs
bool isC99Varargs() const
Definition: MacroInfo.h:207
llvm::ArrayRef
Definition: LLVM.h:34
LLVM.h
clang::IdentifierInfo
One of these records is kept for each identifier that is lexed.
Definition: IdentifierTable.h:85
clang::Token::getLocation
SourceLocation getLocation() const
Return a source location identifier for the specified offset in the current file.
Definition: Token.h:126
clang::MacroInfo::getParameterNum
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
clang::MacroDirective::MD_Define
@ MD_Define
Definition: MacroInfo.h:316
clang::IdentifierInfo::getName
StringRef getName() const
Return the actual identifier string.
Definition: IdentifierTable.h:196
clang::MacroInfo::getNumParams
unsigned getNumParams() const
Definition: MacroInfo.h:184
clang
Definition: CalledOnceCheck.h:17
MacroInfo.h
clang::MacroDirective
Encapsulates changes to the "macros namespace" (the location where the macro name became active,...
Definition: MacroInfo.h:313
clang::MacroDirective::IsFromPCH
unsigned IsFromPCH
True if the macro directive was loaded from a PCH file.
Definition: MacroInfo.h:331
clang::SourceLocation::isValid
bool isValid() const
Return true if this is a valid SourceLocation object.
Definition: SourceLocation.h:110
clang::MacroDirective::DefInfo::getPreviousDefinition
DefInfo getPreviousDefinition()
Definition: MacroInfo.h:498
clang::MacroInfo::isFunctionLike
bool isFunctionLike() const
Definition: MacroInfo.h:201
clang::Preprocessor
Engages in a tight little dance with the lexer to efficiently preprocess tokens.
Definition: Preprocessor.h:129
SM
#define SM(sm)
Definition: Cuda.cpp:79
Token.h
clang::MacroDirective::DefInfo
Definition: MacroInfo.h:361
clang::MacroInfo::isGNUVarargs
bool isGNUVarargs() const
Definition: MacroInfo.h:208
clang::ModuleMacro::create
static ModuleMacro * create(Preprocessor &PP, Module *OwningModule, IdentifierInfo *II, MacroInfo *Macro, ArrayRef< ModuleMacro * > Overrides)
Definition: MacroInfo.cpp:259
clang::MacroInfo::param_end
param_iterator param_end() const
Definition: MacroInfo.h:183
clang::ModuleMacro
Represents a macro directive exported by a module.
Definition: MacroInfo.h:511