1f4a2713aSLionel Sambuc //===--- MacroInfo.cpp - Information about #defined identifiers -----------===//
2f4a2713aSLionel Sambuc //
3f4a2713aSLionel Sambuc // The LLVM Compiler Infrastructure
4f4a2713aSLionel Sambuc //
5f4a2713aSLionel Sambuc // This file is distributed under the University of Illinois Open Source
6f4a2713aSLionel Sambuc // License. See LICENSE.TXT for details.
7f4a2713aSLionel Sambuc //
8f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
9f4a2713aSLionel Sambuc //
10f4a2713aSLionel Sambuc // This file implements the MacroInfo interface.
11f4a2713aSLionel Sambuc //
12f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
13f4a2713aSLionel Sambuc
14f4a2713aSLionel Sambuc #include "clang/Lex/MacroInfo.h"
15f4a2713aSLionel Sambuc #include "clang/Lex/Preprocessor.h"
16f4a2713aSLionel Sambuc using namespace clang;
17f4a2713aSLionel Sambuc
MacroInfo(SourceLocation DefLoc)18f4a2713aSLionel Sambuc MacroInfo::MacroInfo(SourceLocation DefLoc)
19f4a2713aSLionel Sambuc : Location(DefLoc),
20*0a6a1f1dSLionel Sambuc ArgumentList(nullptr),
21f4a2713aSLionel Sambuc NumArguments(0),
22f4a2713aSLionel Sambuc IsDefinitionLengthCached(false),
23f4a2713aSLionel Sambuc IsFunctionLike(false),
24f4a2713aSLionel Sambuc IsC99Varargs(false),
25f4a2713aSLionel Sambuc IsGNUVarargs(false),
26f4a2713aSLionel Sambuc IsBuiltinMacro(false),
27f4a2713aSLionel Sambuc HasCommaPasting(false),
28f4a2713aSLionel Sambuc IsDisabled(false),
29f4a2713aSLionel Sambuc IsUsed(false),
30f4a2713aSLionel Sambuc IsAllowRedefinitionsWithoutWarning(false),
31f4a2713aSLionel Sambuc IsWarnIfUnused(false),
32*0a6a1f1dSLionel Sambuc FromASTFile(false),
33*0a6a1f1dSLionel Sambuc UsedForHeaderGuard(false) {
34f4a2713aSLionel Sambuc }
35f4a2713aSLionel Sambuc
getDefinitionLengthSlow(SourceManager & SM) const36f4a2713aSLionel Sambuc unsigned MacroInfo::getDefinitionLengthSlow(SourceManager &SM) const {
37f4a2713aSLionel Sambuc assert(!IsDefinitionLengthCached);
38f4a2713aSLionel Sambuc IsDefinitionLengthCached = true;
39f4a2713aSLionel Sambuc
40f4a2713aSLionel Sambuc if (ReplacementTokens.empty())
41f4a2713aSLionel Sambuc return (DefinitionLength = 0);
42f4a2713aSLionel Sambuc
43f4a2713aSLionel Sambuc const Token &firstToken = ReplacementTokens.front();
44f4a2713aSLionel Sambuc const Token &lastToken = ReplacementTokens.back();
45f4a2713aSLionel Sambuc SourceLocation macroStart = firstToken.getLocation();
46f4a2713aSLionel Sambuc SourceLocation macroEnd = lastToken.getLocation();
47f4a2713aSLionel Sambuc assert(macroStart.isValid() && macroEnd.isValid());
48f4a2713aSLionel Sambuc assert((macroStart.isFileID() || firstToken.is(tok::comment)) &&
49f4a2713aSLionel Sambuc "Macro defined in macro?");
50f4a2713aSLionel Sambuc assert((macroEnd.isFileID() || lastToken.is(tok::comment)) &&
51f4a2713aSLionel Sambuc "Macro defined in macro?");
52f4a2713aSLionel Sambuc std::pair<FileID, unsigned>
53f4a2713aSLionel Sambuc startInfo = SM.getDecomposedExpansionLoc(macroStart);
54f4a2713aSLionel Sambuc std::pair<FileID, unsigned>
55f4a2713aSLionel Sambuc endInfo = SM.getDecomposedExpansionLoc(macroEnd);
56f4a2713aSLionel Sambuc assert(startInfo.first == endInfo.first &&
57f4a2713aSLionel Sambuc "Macro definition spanning multiple FileIDs ?");
58f4a2713aSLionel Sambuc assert(startInfo.second <= endInfo.second);
59f4a2713aSLionel Sambuc DefinitionLength = endInfo.second - startInfo.second;
60f4a2713aSLionel Sambuc DefinitionLength += lastToken.getLength();
61f4a2713aSLionel Sambuc
62f4a2713aSLionel Sambuc return DefinitionLength;
63f4a2713aSLionel Sambuc }
64f4a2713aSLionel Sambuc
65f4a2713aSLionel Sambuc /// \brief Return true if the specified macro definition is equal to
66f4a2713aSLionel Sambuc /// this macro in spelling, arguments, and whitespace.
67f4a2713aSLionel Sambuc ///
68f4a2713aSLionel Sambuc /// \param Syntactically if true, the macro definitions can be identical even
69f4a2713aSLionel Sambuc /// if they use different identifiers for the function macro parameters.
70f4a2713aSLionel Sambuc /// Otherwise the comparison is lexical and this implements the rules in
71f4a2713aSLionel Sambuc /// C99 6.10.3.
isIdenticalTo(const MacroInfo & Other,Preprocessor & PP,bool Syntactically) const72f4a2713aSLionel Sambuc bool MacroInfo::isIdenticalTo(const MacroInfo &Other, Preprocessor &PP,
73f4a2713aSLionel Sambuc bool Syntactically) const {
74f4a2713aSLionel Sambuc bool Lexically = !Syntactically;
75f4a2713aSLionel Sambuc
76f4a2713aSLionel Sambuc // Check # tokens in replacement, number of args, and various flags all match.
77f4a2713aSLionel Sambuc if (ReplacementTokens.size() != Other.ReplacementTokens.size() ||
78f4a2713aSLionel Sambuc getNumArgs() != Other.getNumArgs() ||
79f4a2713aSLionel Sambuc isFunctionLike() != Other.isFunctionLike() ||
80f4a2713aSLionel Sambuc isC99Varargs() != Other.isC99Varargs() ||
81f4a2713aSLionel Sambuc isGNUVarargs() != Other.isGNUVarargs())
82f4a2713aSLionel Sambuc return false;
83f4a2713aSLionel Sambuc
84f4a2713aSLionel Sambuc if (Lexically) {
85f4a2713aSLionel Sambuc // Check arguments.
86f4a2713aSLionel Sambuc for (arg_iterator I = arg_begin(), OI = Other.arg_begin(), E = arg_end();
87f4a2713aSLionel Sambuc I != E; ++I, ++OI)
88f4a2713aSLionel Sambuc if (*I != *OI) return false;
89f4a2713aSLionel Sambuc }
90f4a2713aSLionel Sambuc
91f4a2713aSLionel Sambuc // Check all the tokens.
92f4a2713aSLionel Sambuc for (unsigned i = 0, e = ReplacementTokens.size(); i != e; ++i) {
93f4a2713aSLionel Sambuc const Token &A = ReplacementTokens[i];
94f4a2713aSLionel Sambuc const Token &B = Other.ReplacementTokens[i];
95f4a2713aSLionel Sambuc if (A.getKind() != B.getKind())
96f4a2713aSLionel Sambuc return false;
97f4a2713aSLionel Sambuc
98f4a2713aSLionel Sambuc // If this isn't the first first token, check that the whitespace and
99f4a2713aSLionel Sambuc // start-of-line characteristics match.
100f4a2713aSLionel Sambuc if (i != 0 &&
101f4a2713aSLionel Sambuc (A.isAtStartOfLine() != B.isAtStartOfLine() ||
102f4a2713aSLionel Sambuc A.hasLeadingSpace() != B.hasLeadingSpace()))
103f4a2713aSLionel Sambuc return false;
104f4a2713aSLionel Sambuc
105f4a2713aSLionel Sambuc // If this is an identifier, it is easy.
106f4a2713aSLionel Sambuc if (A.getIdentifierInfo() || B.getIdentifierInfo()) {
107f4a2713aSLionel Sambuc if (A.getIdentifierInfo() == B.getIdentifierInfo())
108f4a2713aSLionel Sambuc continue;
109f4a2713aSLionel Sambuc if (Lexically)
110f4a2713aSLionel Sambuc return false;
111f4a2713aSLionel Sambuc // With syntactic equivalence the parameter names can be different as long
112f4a2713aSLionel Sambuc // as they are used in the same place.
113f4a2713aSLionel Sambuc int AArgNum = getArgumentNum(A.getIdentifierInfo());
114f4a2713aSLionel Sambuc if (AArgNum == -1)
115f4a2713aSLionel Sambuc return false;
116f4a2713aSLionel Sambuc if (AArgNum != Other.getArgumentNum(B.getIdentifierInfo()))
117f4a2713aSLionel Sambuc return false;
118f4a2713aSLionel Sambuc continue;
119f4a2713aSLionel Sambuc }
120f4a2713aSLionel Sambuc
121f4a2713aSLionel Sambuc // Otherwise, check the spelling.
122f4a2713aSLionel Sambuc if (PP.getSpelling(A) != PP.getSpelling(B))
123f4a2713aSLionel Sambuc return false;
124f4a2713aSLionel Sambuc }
125f4a2713aSLionel Sambuc
126f4a2713aSLionel Sambuc return true;
127f4a2713aSLionel Sambuc }
128f4a2713aSLionel Sambuc
dump() const129*0a6a1f1dSLionel Sambuc void MacroInfo::dump() const {
130*0a6a1f1dSLionel Sambuc llvm::raw_ostream &Out = llvm::errs();
131*0a6a1f1dSLionel Sambuc
132*0a6a1f1dSLionel Sambuc // FIXME: Dump locations.
133*0a6a1f1dSLionel Sambuc Out << "MacroInfo " << this;
134*0a6a1f1dSLionel Sambuc if (IsBuiltinMacro) Out << " builtin";
135*0a6a1f1dSLionel Sambuc if (IsDisabled) Out << " disabled";
136*0a6a1f1dSLionel Sambuc if (IsUsed) Out << " used";
137*0a6a1f1dSLionel Sambuc if (IsAllowRedefinitionsWithoutWarning)
138*0a6a1f1dSLionel Sambuc Out << " allow_redefinitions_without_warning";
139*0a6a1f1dSLionel Sambuc if (IsWarnIfUnused) Out << " warn_if_unused";
140*0a6a1f1dSLionel Sambuc if (FromASTFile) Out << " imported";
141*0a6a1f1dSLionel Sambuc if (UsedForHeaderGuard) Out << " header_guard";
142*0a6a1f1dSLionel Sambuc
143*0a6a1f1dSLionel Sambuc Out << "\n #define <macro>";
144*0a6a1f1dSLionel Sambuc if (IsFunctionLike) {
145*0a6a1f1dSLionel Sambuc Out << "(";
146*0a6a1f1dSLionel Sambuc for (unsigned I = 0; I != NumArguments; ++I) {
147*0a6a1f1dSLionel Sambuc if (I) Out << ", ";
148*0a6a1f1dSLionel Sambuc Out << ArgumentList[I]->getName();
149*0a6a1f1dSLionel Sambuc }
150*0a6a1f1dSLionel Sambuc if (IsC99Varargs || IsGNUVarargs) {
151*0a6a1f1dSLionel Sambuc if (NumArguments && IsC99Varargs) Out << ", ";
152*0a6a1f1dSLionel Sambuc Out << "...";
153*0a6a1f1dSLionel Sambuc }
154*0a6a1f1dSLionel Sambuc Out << ")";
155*0a6a1f1dSLionel Sambuc }
156*0a6a1f1dSLionel Sambuc
157*0a6a1f1dSLionel Sambuc for (const Token &Tok : ReplacementTokens) {
158*0a6a1f1dSLionel Sambuc Out << " ";
159*0a6a1f1dSLionel Sambuc if (const char *Punc = tok::getPunctuatorSpelling(Tok.getKind()))
160*0a6a1f1dSLionel Sambuc Out << Punc;
161*0a6a1f1dSLionel Sambuc else if (const char *Kwd = tok::getKeywordSpelling(Tok.getKind()))
162*0a6a1f1dSLionel Sambuc Out << Kwd;
163*0a6a1f1dSLionel Sambuc else if (Tok.is(tok::identifier))
164*0a6a1f1dSLionel Sambuc Out << Tok.getIdentifierInfo()->getName();
165*0a6a1f1dSLionel Sambuc else if (Tok.isLiteral() && Tok.getLiteralData())
166*0a6a1f1dSLionel Sambuc Out << StringRef(Tok.getLiteralData(), Tok.getLength());
167*0a6a1f1dSLionel Sambuc else
168*0a6a1f1dSLionel Sambuc Out << Tok.getName();
169*0a6a1f1dSLionel Sambuc }
170*0a6a1f1dSLionel Sambuc }
171*0a6a1f1dSLionel Sambuc
getDefinition()172*0a6a1f1dSLionel Sambuc MacroDirective::DefInfo MacroDirective::getDefinition() {
173f4a2713aSLionel Sambuc MacroDirective *MD = this;
174f4a2713aSLionel Sambuc SourceLocation UndefLoc;
175f4a2713aSLionel Sambuc Optional<bool> isPublic;
176f4a2713aSLionel Sambuc for (; MD; MD = MD->getPrevious()) {
177f4a2713aSLionel Sambuc if (DefMacroDirective *DefMD = dyn_cast<DefMacroDirective>(MD))
178f4a2713aSLionel Sambuc return DefInfo(DefMD, UndefLoc,
179f4a2713aSLionel Sambuc !isPublic.hasValue() || isPublic.getValue());
180f4a2713aSLionel Sambuc
181f4a2713aSLionel Sambuc if (UndefMacroDirective *UndefMD = dyn_cast<UndefMacroDirective>(MD)) {
182f4a2713aSLionel Sambuc UndefLoc = UndefMD->getLocation();
183f4a2713aSLionel Sambuc continue;
184f4a2713aSLionel Sambuc }
185f4a2713aSLionel Sambuc
186f4a2713aSLionel Sambuc VisibilityMacroDirective *VisMD = cast<VisibilityMacroDirective>(MD);
187f4a2713aSLionel Sambuc if (!isPublic.hasValue())
188f4a2713aSLionel Sambuc isPublic = VisMD->isPublic();
189f4a2713aSLionel Sambuc }
190f4a2713aSLionel Sambuc
191*0a6a1f1dSLionel Sambuc return DefInfo(nullptr, UndefLoc,
192*0a6a1f1dSLionel Sambuc !isPublic.hasValue() || isPublic.getValue());
193f4a2713aSLionel Sambuc }
194f4a2713aSLionel Sambuc
195f4a2713aSLionel Sambuc const MacroDirective::DefInfo
findDirectiveAtLoc(SourceLocation L,SourceManager & SM) const196f4a2713aSLionel Sambuc MacroDirective::findDirectiveAtLoc(SourceLocation L, SourceManager &SM) const {
197f4a2713aSLionel Sambuc assert(L.isValid() && "SourceLocation is invalid.");
198f4a2713aSLionel Sambuc for (DefInfo Def = getDefinition(); Def; Def = Def.getPreviousDefinition()) {
199f4a2713aSLionel Sambuc if (Def.getLocation().isInvalid() || // For macros defined on the command line.
200f4a2713aSLionel Sambuc SM.isBeforeInTranslationUnit(Def.getLocation(), L))
201f4a2713aSLionel Sambuc return (!Def.isUndefined() ||
202f4a2713aSLionel Sambuc SM.isBeforeInTranslationUnit(L, Def.getUndefLocation()))
203f4a2713aSLionel Sambuc ? Def : DefInfo();
204f4a2713aSLionel Sambuc }
205f4a2713aSLionel Sambuc return DefInfo();
206f4a2713aSLionel Sambuc }
207*0a6a1f1dSLionel Sambuc
dump() const208*0a6a1f1dSLionel Sambuc void MacroDirective::dump() const {
209*0a6a1f1dSLionel Sambuc llvm::raw_ostream &Out = llvm::errs();
210*0a6a1f1dSLionel Sambuc
211*0a6a1f1dSLionel Sambuc switch (getKind()) {
212*0a6a1f1dSLionel Sambuc case MD_Define: Out << "DefMacroDirective"; break;
213*0a6a1f1dSLionel Sambuc case MD_Undefine: Out << "UndefMacroDirective"; break;
214*0a6a1f1dSLionel Sambuc case MD_Visibility: Out << "VisibilityMacroDirective"; break;
215*0a6a1f1dSLionel Sambuc }
216*0a6a1f1dSLionel Sambuc Out << " " << this;
217*0a6a1f1dSLionel Sambuc // FIXME: Dump SourceLocation.
218*0a6a1f1dSLionel Sambuc if (auto *Prev = getPrevious())
219*0a6a1f1dSLionel Sambuc Out << " prev " << Prev;
220*0a6a1f1dSLionel Sambuc if (IsFromPCH) Out << " from_pch";
221*0a6a1f1dSLionel Sambuc if (IsImported) Out << " imported";
222*0a6a1f1dSLionel Sambuc if (IsAmbiguous) Out << " ambiguous";
223*0a6a1f1dSLionel Sambuc
224*0a6a1f1dSLionel Sambuc if (IsPublic)
225*0a6a1f1dSLionel Sambuc Out << " public";
226*0a6a1f1dSLionel Sambuc else if (isa<VisibilityMacroDirective>(this))
227*0a6a1f1dSLionel Sambuc Out << " private";
228*0a6a1f1dSLionel Sambuc
229*0a6a1f1dSLionel Sambuc if (auto *DMD = dyn_cast<DefMacroDirective>(this)) {
230*0a6a1f1dSLionel Sambuc if (auto *Info = DMD->getInfo()) {
231*0a6a1f1dSLionel Sambuc Out << "\n ";
232*0a6a1f1dSLionel Sambuc Info->dump();
233*0a6a1f1dSLionel Sambuc }
234*0a6a1f1dSLionel Sambuc }
235*0a6a1f1dSLionel Sambuc Out << "\n";
236*0a6a1f1dSLionel Sambuc }
237