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"
14#include "clang/Basic/IdentifierTable.h"
15#include "clang/Basic/LLVM.h"
16#include "clang/Basic/SourceLocation.h"
17#include "clang/Basic/SourceManager.h"
18#include "clang/Basic/TokenKinds.h"
19#include "clang/Lex/Preprocessor.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(Loc: macroStart);
74 std::pair<FileID, unsigned>
75 endInfo = SM.getDecomposedExpansionLoc(Loc: 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.
92bool MacroInfo::isIdenticalTo(const MacroInfo &Other, Preprocessor &PP,
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() ||
123 A.hasLeadingSpace() != B.hasLeadingSpace()))
124 return false;
125
126 // If this is an identifier, it is easy.
127 if (A.getIdentifierInfo() || B.getIdentifierInfo()) {
128 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(Arg: A.getIdentifierInfo());
135 if (AArgNum == -1)
136 return false;
137 if (AArgNum != Other.getParameterNum(Arg: B.getIdentifierInfo()))
138 return false;
139 continue;
140 }
141
142 // Otherwise, check the spelling.
143 if (PP.getSpelling(Tok: A) != PP.getSpelling(Tok: 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(Kind: 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
196MacroDirective::DefInfo MacroDirective::getDefinition() {
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>(Val: MD))
202 return DefInfo(DefMD, UndefLoc, !isPublic || *isPublic);
203
204 if (UndefMacroDirective *UndefMD = dyn_cast<UndefMacroDirective>(Val: MD)) {
205 UndefLoc = UndefMD->getLocation();
206 continue;
207 }
208
209 VisibilityMacroDirective *VisMD = cast<VisibilityMacroDirective>(Val: MD);
210 if (!isPublic)
211 isPublic = VisMD->isPublic();
212 }
213
214 return DefInfo(nullptr, UndefLoc, !isPublic || *isPublic);
215}
216
217const MacroDirective::DefInfo
218MacroDirective::findDirectiveAtLoc(SourceLocation L,
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(LHS: Def.getLocation(), RHS: L))
224 return (!Def.isUndefined() ||
225 SM.isBeforeInTranslationUnit(LHS: L, RHS: 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>(Val: this))
246 Out << (IsPublic ? " public" : " private");
247
248 if (auto *DMD = dyn_cast<DefMacroDirective>(Val: this)) {
249 if (auto *Info = DMD->getInfo()) {
250 Out << "\n ";
251 Info->dump();
252 }
253 }
254 Out << "\n";
255}
256
257ModuleMacro *ModuleMacro::create(Preprocessor &PP, Module *OwningModule,
258 const IdentifierInfo *II, MacroInfo *Macro,
259 ArrayRef<ModuleMacro *> Overrides) {
260 void *Mem = PP.getPreprocessorAllocator().Allocate(
261 Size: sizeof(ModuleMacro) + sizeof(ModuleMacro *) * Overrides.size(),
262 Alignment: alignof(ModuleMacro));
263 return new (Mem) ModuleMacro(OwningModule, II, Macro, Overrides);
264}
265

Provided by KDAB

Privacy Policy
Improve your Profiling and Debugging skills
Find out more

source code of clang/lib/Lex/MacroInfo.cpp