xref: /minix3/external/bsd/llvm/dist/clang/lib/Lex/MacroInfo.cpp (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
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