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/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
29using namespace clang;
30
31namespace {
32
33// MacroInfo is expected to take 40 bytes on platforms with an 8 byte pointer
34// and 4 byte SourceLocation.
35template <int> class MacroInfoSizeChecker {
36public:
37 [[maybe_unused]] constexpr static bool AsExpected = true;
38};
39template <> class MacroInfoSizeChecker<8> {
40public:
41 [[maybe_unused]] constexpr static bool AsExpected =
42 sizeof(MacroInfo) == (32 + sizeof(SourceLocation) * 2);
43};
44
45static_assert(MacroInfoSizeChecker<sizeof(void *)>::AsExpected,
46 "Unexpected size of MacroInfo");
47
48} // end namespace
49
50MacroInfo::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
57unsigned 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() ||
126 return false;
127
128 // If this is an identifier, it is easy.
129 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
152LLVM_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
233LLVM_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
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:220
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: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
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: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:137
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