1 //===- MacroInfo.cpp - Information about #defined identifiers -------------===//
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
7 //===----------------------------------------------------------------------===//
9 // This file implements the MacroInfo interface.
11 //===----------------------------------------------------------------------===//
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/ADT/StringRef.h"
22 #include "llvm/Support/Casting.h"
23 #include "llvm/Support/Compiler.h"
24 #include "llvm/Support/raw_ostream.h"
29 using namespace clang
;
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
{
37 [[maybe_unused
]] constexpr static bool AsExpected
= true;
39 template <> class MacroInfoSizeChecker
<8> {
41 [[maybe_unused
]] constexpr static bool AsExpected
=
42 sizeof(MacroInfo
) == (32 + sizeof(SourceLocation
) * 2);
45 static_assert(MacroInfoSizeChecker
<sizeof(void *)>::AsExpected
,
46 "Unexpected size of MacroInfo");
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) {}
57 unsigned MacroInfo::getDefinitionLengthSlow(const SourceManager
&SM
) const {
58 assert(!IsDefinitionLengthCached
);
59 IsDefinitionLengthCached
= true;
61 ArrayRef
<Token
> ReplacementTokens
= tokens();
62 if (ReplacementTokens
.empty())
63 return (DefinitionLength
= 0);
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();
84 return DefinitionLength
;
87 /// Return true if the specified macro definition is equal to
88 /// this macro in spelling, arguments, and whitespace.
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
94 bool MacroInfo::isIdenticalTo(const MacroInfo
&Other
, Preprocessor
&PP
,
95 bool Syntactically
) const {
96 bool Lexically
= !Syntactically
;
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())
108 for (param_iterator I
= param_begin(), OI
= Other
.param_begin(),
111 if (*I
!= *OI
) return false;
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())
121 // If this isn't the first token, check that the whitespace and
122 // start-of-line characteristics match.
124 (A
.isAtStartOfLine() != B
.isAtStartOfLine() ||
125 A
.hasLeadingSpace() != B
.hasLeadingSpace()))
128 // If this is an identifier, it is easy.
129 if (A
.getIdentifierInfo() || B
.getIdentifierInfo()) {
130 if (A
.getIdentifierInfo() == B
.getIdentifierInfo())
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());
139 if (AArgNum
!= Other
.getParameterNum(B
.getIdentifierInfo()))
144 // Otherwise, check the spelling.
145 if (PP
.getSpelling(A
) != PP
.getSpelling(B
))
152 LLVM_DUMP_METHOD
void MacroInfo::dump() const {
153 llvm::raw_ostream
&Out
= llvm::errs();
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";
165 Out
<< "\n #define <macro>";
166 if (IsFunctionLike
) {
168 for (unsigned I
= 0; I
!= NumParameters
; ++I
) {
170 Out
<< ParameterList
[I
]->getName();
172 if (IsC99Varargs
|| IsGNUVarargs
) {
173 if (NumParameters
&& IsC99Varargs
) Out
<< ", ";
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())
187 if (const char *Punc
= tok::getPunctuatorSpelling(Tok
.getKind()))
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();
194 Out
<< Tok
.getName();
198 MacroDirective::DefInfo
MacroDirective::getDefinition() {
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
);
206 if (UndefMacroDirective
*UndefMD
= dyn_cast
<UndefMacroDirective
>(MD
)) {
207 UndefLoc
= UndefMD
->getLocation();
211 VisibilityMacroDirective
*VisMD
= cast
<VisibilityMacroDirective
>(MD
);
213 isPublic
= VisMD
->isPublic();
216 return DefInfo(nullptr, UndefLoc
, !isPublic
|| *isPublic
);
219 const MacroDirective::DefInfo
220 MacroDirective::findDirectiveAtLoc(SourceLocation L
,
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()))
233 LLVM_DUMP_METHOD
void MacroDirective::dump() const {
234 llvm::raw_ostream
&Out
= llvm::errs();
237 case MD_Define
: Out
<< "DefMacroDirective"; break;
238 case MD_Undefine
: Out
<< "UndefMacroDirective"; break;
239 case MD_Visibility
: Out
<< "VisibilityMacroDirective"; break;
242 // FIXME: Dump SourceLocation.
243 if (auto *Prev
= getPrevious())
244 Out
<< " prev " << Prev
;
245 if (IsFromPCH
) Out
<< " from_pch";
247 if (isa
<VisibilityMacroDirective
>(this))
248 Out
<< (IsPublic
? " public" : " private");
250 if (auto *DMD
= dyn_cast
<DefMacroDirective
>(this)) {
251 if (auto *Info
= DMD
->getInfo()) {
259 ModuleMacro
*ModuleMacro::create(Preprocessor
&PP
, Module
*OwningModule
,
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
);