clang 20.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"
20#include "clang/Lex/Token.h"
21#include "llvm/Support/Compiler.h"
22#include "llvm/Support/raw_ostream.h"
23#include <cassert>
24#include <optional>
25#include <utility>
26
27using namespace clang;
28
29namespace {
30
31// MacroInfo is expected to take 40 bytes on platforms with an 8 byte pointer
32// and 4 byte SourceLocation.
33template <int> class MacroInfoSizeChecker {
34public:
35 [[maybe_unused]] constexpr static bool AsExpected = true;
36};
37template <> class MacroInfoSizeChecker<8> {
38public:
39 [[maybe_unused]] constexpr static bool AsExpected =
40 sizeof(MacroInfo) == (32 + sizeof(SourceLocation) * 2);
41};
42
43static_assert(MacroInfoSizeChecker<sizeof(void *)>::AsExpected,
44 "Unexpected size of MacroInfo");
45
46} // end namespace
47
48MacroInfo::MacroInfo(SourceLocation DefLoc)
49 : Location(DefLoc), IsDefinitionLengthCached(false), IsFunctionLike(false),
50 IsC99Varargs(false), IsGNUVarargs(false), IsBuiltinMacro(false),
51 HasCommaPasting(false), IsDisabled(false), IsUsed(false),
52 IsAllowRedefinitionsWithoutWarning(false), IsWarnIfUnused(false),
53 UsedForHeaderGuard(false) {}
54
55unsigned MacroInfo::getDefinitionLengthSlow(const SourceManager &SM) const {
56 assert(!IsDefinitionLengthCached);
57 IsDefinitionLengthCached = true;
58
59 ArrayRef<Token> ReplacementTokens = tokens();
60 if (ReplacementTokens.empty())
61 return (DefinitionLength = 0);
62
63 const Token &firstToken = ReplacementTokens.front();
64 const Token &lastToken = ReplacementTokens.back();
65 SourceLocation macroStart = firstToken.getLocation();
66 SourceLocation macroEnd = lastToken.getLocation();
67 assert(macroStart.isValid() && macroEnd.isValid());
68 assert((macroStart.isFileID() || firstToken.is(tok::comment)) &&
69 "Macro defined in macro?");
70 assert((macroEnd.isFileID() || lastToken.is(tok::comment)) &&
71 "Macro defined in macro?");
72 std::pair<FileID, unsigned>
73 startInfo = SM.getDecomposedExpansionLoc(macroStart);
74 std::pair<FileID, unsigned>
75 endInfo = SM.getDecomposedExpansionLoc(macroEnd);
76 assert(startInfo.first == endInfo.first &&
77 "Macro definition spanning multiple FileIDs ?");
78 assert(startInfo.second <= endInfo.second);
79 DefinitionLength = endInfo.second - startInfo.second;
80 DefinitionLength += lastToken.getLength();
81
82 return DefinitionLength;
83}
84
85/// Return true if the specified macro definition is equal to
86/// this macro in spelling, arguments, and whitespace.
87///
88/// \param Syntactically if true, the macro definitions can be identical even
89/// if they use different identifiers for the function macro parameters.
90/// Otherwise the comparison is lexical and this implements the rules in
91/// C99 6.10.3.
93 bool Syntactically) const {
94 bool Lexically = !Syntactically;
95
96 // Check # tokens in replacement, number of args, and various flags all match.
97 if (getNumTokens() != Other.getNumTokens() ||
98 getNumParams() != Other.getNumParams() ||
99 isFunctionLike() != Other.isFunctionLike() ||
100 isC99Varargs() != Other.isC99Varargs() ||
101 isGNUVarargs() != Other.isGNUVarargs())
102 return false;
103
104 if (Lexically) {
105 // Check arguments.
106 for (param_iterator I = param_begin(), OI = Other.param_begin(),
107 E = param_end();
108 I != E; ++I, ++OI)
109 if (*I != *OI) return false;
110 }
111
112 // Check all the tokens.
113 for (unsigned i = 0; i != NumReplacementTokens; ++i) {
114 const Token &A = ReplacementTokens[i];
115 const Token &B = Other.ReplacementTokens[i];
116 if (A.getKind() != B.getKind())
117 return false;
118
119 // If this isn't the first token, check that the whitespace and
120 // start-of-line characteristics match.
121 if (i != 0 &&
122 (A.isAtStartOfLine() != B.isAtStartOfLine() ||
124 return false;
125
126 // If this is an identifier, it is easy.
127 if (A.getIdentifierInfo() || B.getIdentifierInfo()) {
129 continue;
130 if (Lexically)
131 return false;
132 // With syntactic equivalence the parameter names can be different as long
133 // as they are used in the same place.
134 int AArgNum = getParameterNum(A.getIdentifierInfo());
135 if (AArgNum == -1)
136 return false;
137 if (AArgNum != Other.getParameterNum(B.getIdentifierInfo()))
138 return false;
139 continue;
140 }
141
142 // Otherwise, check the spelling.
143 if (PP.getSpelling(A) != PP.getSpelling(B))
144 return false;
145 }
146
147 return true;
148}
149
150LLVM_DUMP_METHOD void MacroInfo::dump() const {
151 llvm::raw_ostream &Out = llvm::errs();
152
153 // FIXME: Dump locations.
154 Out << "MacroInfo " << this;
155 if (IsBuiltinMacro) Out << " builtin";
156 if (IsDisabled) Out << " disabled";
157 if (IsUsed) Out << " used";
158 if (IsAllowRedefinitionsWithoutWarning)
159 Out << " allow_redefinitions_without_warning";
160 if (IsWarnIfUnused) Out << " warn_if_unused";
161 if (UsedForHeaderGuard) Out << " header_guard";
162
163 Out << "\n #define <macro>";
164 if (IsFunctionLike) {
165 Out << "(";
166 for (unsigned I = 0; I != NumParameters; ++I) {
167 if (I) Out << ", ";
168 Out << ParameterList[I]->getName();
169 }
170 if (IsC99Varargs || IsGNUVarargs) {
171 if (NumParameters && IsC99Varargs) Out << ", ";
172 Out << "...";
173 }
174 Out << ")";
175 }
176
177 bool First = true;
178 for (const Token &Tok : tokens()) {
179 // Leading space is semantically meaningful in a macro definition,
180 // so preserve it in the dump output.
181 if (First || Tok.hasLeadingSpace())
182 Out << " ";
183 First = false;
184
185 if (const char *Punc = tok::getPunctuatorSpelling(Tok.getKind()))
186 Out << Punc;
187 else if (Tok.isLiteral() && Tok.getLiteralData())
188 Out << StringRef(Tok.getLiteralData(), Tok.getLength());
189 else if (auto *II = Tok.getIdentifierInfo())
190 Out << II->getName();
191 else
192 Out << Tok.getName();
193 }
194}
195
197 MacroDirective *MD = this;
198 SourceLocation UndefLoc;
199 std::optional<bool> isPublic;
200 for (; MD; MD = MD->getPrevious()) {
201 if (DefMacroDirective *DefMD = dyn_cast<DefMacroDirective>(MD))
202 return DefInfo(DefMD, UndefLoc, !isPublic || *isPublic);
203
204 if (UndefMacroDirective *UndefMD = dyn_cast<UndefMacroDirective>(MD)) {
205 UndefLoc = UndefMD->getLocation();
206 continue;
207 }
208
209 VisibilityMacroDirective *VisMD = cast<VisibilityMacroDirective>(MD);
210 if (!isPublic)
211 isPublic = VisMD->isPublic();
212 }
213
214 return DefInfo(nullptr, UndefLoc, !isPublic || *isPublic);
215}
216
219 const SourceManager &SM) const {
220 assert(L.isValid() && "SourceLocation is invalid.");
221 for (DefInfo Def = getDefinition(); Def; Def = Def.getPreviousDefinition()) {
222 if (Def.getLocation().isInvalid() || // For macros defined on the command line.
223 SM.isBeforeInTranslationUnit(Def.getLocation(), L))
224 return (!Def.isUndefined() ||
225 SM.isBeforeInTranslationUnit(L, Def.getUndefLocation()))
226 ? Def : DefInfo();
227 }
228 return DefInfo();
229}
230
231LLVM_DUMP_METHOD void MacroDirective::dump() const {
232 llvm::raw_ostream &Out = llvm::errs();
233
234 switch (getKind()) {
235 case MD_Define: Out << "DefMacroDirective"; break;
236 case MD_Undefine: Out << "UndefMacroDirective"; break;
237 case MD_Visibility: Out << "VisibilityMacroDirective"; break;
238 }
239 Out << " " << this;
240 // FIXME: Dump SourceLocation.
241 if (auto *Prev = getPrevious())
242 Out << " prev " << Prev;
243 if (IsFromPCH) Out << " from_pch";
244
245 if (isa<VisibilityMacroDirective>(this))
246 Out << (IsPublic ? " public" : " private");
247
248 if (auto *DMD = dyn_cast<DefMacroDirective>(this)) {
249 if (auto *Info = DMD->getInfo()) {
250 Out << "\n ";
251 Info->dump();
252 }
253 }
254 Out << "\n";
255}
256
258 const IdentifierInfo *II, MacroInfo *Macro,
259 ArrayRef<ModuleMacro *> Overrides) {
260 void *Mem = PP.getPreprocessorAllocator().Allocate(
261 sizeof(ModuleMacro) + sizeof(ModuleMacro *) * Overrides.size(),
262 alignof(ModuleMacro));
263 return new (Mem) ModuleMacro(OwningModule, II, Macro, Overrides);
264}
#define SM(sm)
Definition: Cuda.cpp:84
Expr * E
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 MacroDirective * getPrevious() const
Get previous definition of the macro with the same name.
Definition: MacroInfo.h:354
const DefInfo findDirectiveAtLoc(SourceLocation L, const SourceManager &SM) const
Find macro definition active in the specified source location.
Definition: MacroInfo.cpp:218
unsigned IsPublic
Whether the macro has public visibility (when described in a module).
Definition: MacroInfo.h:340
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:196
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:92
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:150
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
ArrayRef< Token > tokens() const
Definition: MacroInfo.h:249
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
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:257
Describes a module or submodule.
Definition: Module.h:115
Engages in a tight little dance with the lexer to efficiently preprocess tokens.
Definition: Preprocessor.h:138
llvm::BumpPtrAllocator & getPreprocessorAllocator()
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 ...
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
IdentifierInfo * getIdentifierInfo() const
Definition: Token.h:187
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
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