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