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