blob: dc091f625b52987351c6450c83a75423744e44c9 [file] [log] [blame]
Reid Spencer5f016e22007-07-11 17:01:13 +00001//===--- MacroInfo.cpp - Information about #defined identifiers -----------===//
2//
3// The LLVM Compiler Infrastructure
4//
Chris Lattner0bc735f2007-12-29 19:59:25 +00005// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
Reid Spencer5f016e22007-07-11 17:01:13 +00007//
8//===----------------------------------------------------------------------===//
9//
10// This file implements the MacroInfo interface.
11//
12//===----------------------------------------------------------------------===//
13
14#include "clang/Lex/MacroInfo.h"
15#include "clang/Lex/Preprocessor.h"
16using namespace clang;
17
Alexander Kornienko8a64bb52012-08-29 00:20:03 +000018MacroInfo::MacroInfo(SourceLocation DefLoc)
19 : Location(DefLoc),
Alexander Kornienko8a64bb52012-08-29 00:20:03 +000020 ArgumentList(0),
21 NumArguments(0),
22 IsDefinitionLengthCached(false),
23 IsFunctionLike(false),
24 IsC99Varargs(false),
25 IsGNUVarargs(false),
26 IsBuiltinMacro(false),
Eli Friedman4fa4b482012-11-14 02:18:46 +000027 HasCommaPasting(false),
Alexander Kornienko8a64bb52012-08-29 00:20:03 +000028 IsDisabled(false),
29 IsUsed(false),
30 IsAllowRedefinitionsWithoutWarning(false),
Argyrios Kyrtzidisbaa74bd2013-03-22 21:12:51 +000031 IsWarnIfUnused(false),
32 FromASTFile(false) {
Alexander Kornienko66da0ab2012-09-28 22:24:03 +000033}
34
Argyrios Kyrtzidisb73377e2011-07-07 03:40:34 +000035unsigned MacroInfo::getDefinitionLengthSlow(SourceManager &SM) const {
36 assert(!IsDefinitionLengthCached);
37 IsDefinitionLengthCached = true;
38
39 if (ReplacementTokens.empty())
40 return (DefinitionLength = 0);
41
42 const Token &firstToken = ReplacementTokens.front();
43 const Token &lastToken = ReplacementTokens.back();
44 SourceLocation macroStart = firstToken.getLocation();
45 SourceLocation macroEnd = lastToken.getLocation();
46 assert(macroStart.isValid() && macroEnd.isValid());
47 assert((macroStart.isFileID() || firstToken.is(tok::comment)) &&
48 "Macro defined in macro?");
49 assert((macroEnd.isFileID() || lastToken.is(tok::comment)) &&
50 "Macro defined in macro?");
51 std::pair<FileID, unsigned>
Chandler Carruthe7b2b6e2011-07-25 20:52:32 +000052 startInfo = SM.getDecomposedExpansionLoc(macroStart);
Argyrios Kyrtzidisb73377e2011-07-07 03:40:34 +000053 std::pair<FileID, unsigned>
Chandler Carruthe7b2b6e2011-07-25 20:52:32 +000054 endInfo = SM.getDecomposedExpansionLoc(macroEnd);
Argyrios Kyrtzidisb73377e2011-07-07 03:40:34 +000055 assert(startInfo.first == endInfo.first &&
56 "Macro definition spanning multiple FileIDs ?");
57 assert(startInfo.second <= endInfo.second);
58 DefinitionLength = endInfo.second - startInfo.second;
59 DefinitionLength += lastToken.getLength();
60
61 return DefinitionLength;
62}
63
James Dennett81ba9d12013-03-20 21:30:03 +000064// isIdenticalTo - Return true if the specified macro definition is equal to
65// this macro in spelling, arguments, and whitespace. This is used to emit
66// duplicate definition warnings. This implements the rules in C99 6.10.3.
67//
Reid Spencer5f016e22007-07-11 17:01:13 +000068bool MacroInfo::isIdenticalTo(const MacroInfo &Other, Preprocessor &PP) const {
69 // Check # tokens in replacement, number of args, and various flags all match.
70 if (ReplacementTokens.size() != Other.ReplacementTokens.size() ||
Chris Lattner25c96482007-07-14 22:46:43 +000071 getNumArgs() != Other.getNumArgs() ||
Reid Spencer5f016e22007-07-11 17:01:13 +000072 isFunctionLike() != Other.isFunctionLike() ||
73 isC99Varargs() != Other.isC99Varargs() ||
74 isGNUVarargs() != Other.isGNUVarargs())
75 return false;
76
77 // Check arguments.
78 for (arg_iterator I = arg_begin(), OI = Other.arg_begin(), E = arg_end();
79 I != E; ++I, ++OI)
80 if (*I != *OI) return false;
Mike Stump1eb44332009-09-09 15:08:12 +000081
Reid Spencer5f016e22007-07-11 17:01:13 +000082 // Check all the tokens.
83 for (unsigned i = 0, e = ReplacementTokens.size(); i != e; ++i) {
Chris Lattnerd2177732007-07-20 16:59:19 +000084 const Token &A = ReplacementTokens[i];
85 const Token &B = Other.ReplacementTokens[i];
Chris Lattner688a2482009-03-09 20:33:32 +000086 if (A.getKind() != B.getKind())
87 return false;
Mike Stump1eb44332009-09-09 15:08:12 +000088
Chris Lattner688a2482009-03-09 20:33:32 +000089 // If this isn't the first first token, check that the whitespace and
90 // start-of-line characteristics match.
91 if (i != 0 &&
92 (A.isAtStartOfLine() != B.isAtStartOfLine() ||
93 A.hasLeadingSpace() != B.hasLeadingSpace()))
Reid Spencer5f016e22007-07-11 17:01:13 +000094 return false;
Mike Stump1eb44332009-09-09 15:08:12 +000095
Reid Spencer5f016e22007-07-11 17:01:13 +000096 // If this is an identifier, it is easy.
97 if (A.getIdentifierInfo() || B.getIdentifierInfo()) {
98 if (A.getIdentifierInfo() != B.getIdentifierInfo())
99 return false;
100 continue;
101 }
Mike Stump1eb44332009-09-09 15:08:12 +0000102
Reid Spencer5f016e22007-07-11 17:01:13 +0000103 // Otherwise, check the spelling.
104 if (PP.getSpelling(A) != PP.getSpelling(B))
105 return false;
106 }
Mike Stump1eb44332009-09-09 15:08:12 +0000107
Reid Spencer5f016e22007-07-11 17:01:13 +0000108 return true;
109}
Argyrios Kyrtzidis9818a1d2013-02-20 00:54:57 +0000110
Argyrios Kyrtzidisc56fff72013-03-26 17:17:01 +0000111MacroDirective::DefInfo MacroDirective::getDefinition(bool AllowHidden) {
112 MacroDirective *MD = this;
113 SourceLocation UndefLoc;
114 Optional<bool> isPublic;
115 for (; MD; MD = MD->getPrevious()) {
116 if (!AllowHidden && MD->isHidden())
117 continue;
118
119 if (DefMacroDirective *DefMD = dyn_cast<DefMacroDirective>(MD))
120 return DefInfo(DefMD, UndefLoc,
121 !isPublic.hasValue() || isPublic.getValue());
122
123 if (UndefMacroDirective *UndefMD = dyn_cast<UndefMacroDirective>(MD)) {
124 UndefLoc = UndefMD->getLocation();
125 continue;
126 }
127
128 VisibilityMacroDirective *VisMD = cast<VisibilityMacroDirective>(MD);
129 if (!isPublic.hasValue())
130 isPublic = VisMD->isPublic();
131 }
132
133 return DefInfo();
134}
135
136const MacroDirective::DefInfo
Argyrios Kyrtzidis9818a1d2013-02-20 00:54:57 +0000137MacroDirective::findDirectiveAtLoc(SourceLocation L, SourceManager &SM) const {
138 assert(L.isValid() && "SourceLocation is invalid.");
Argyrios Kyrtzidisc56fff72013-03-26 17:17:01 +0000139 for (DefInfo Def = getDefinition(); Def; Def = Def.getPreviousDefinition()) {
140 if (Def.getLocation().isInvalid() || // For macros defined on the command line.
141 SM.isBeforeInTranslationUnit(Def.getLocation(), L))
142 return (!Def.isUndefined() ||
143 SM.isBeforeInTranslationUnit(L, Def.getUndefLocation()))
144 ? Def : DefInfo();
Argyrios Kyrtzidis9818a1d2013-02-20 00:54:57 +0000145 }
Argyrios Kyrtzidisc56fff72013-03-26 17:17:01 +0000146 return DefInfo();
Argyrios Kyrtzidis9818a1d2013-02-20 00:54:57 +0000147}