blob: d1875c79d0d156ce8ac91f2363811a79d4eab8c7 [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),
20 PreviousDefinition(0),
21 ArgumentList(0),
22 NumArguments(0),
23 IsDefinitionLengthCached(false),
24 IsFunctionLike(false),
25 IsC99Varargs(false),
26 IsGNUVarargs(false),
27 IsBuiltinMacro(false),
Eli Friedman4fa4b482012-11-14 02:18:46 +000028 HasCommaPasting(false),
Alexander Kornienko8a64bb52012-08-29 00:20:03 +000029 IsFromAST(false),
30 ChangedAfterLoad(false),
31 IsDisabled(false),
32 IsUsed(false),
33 IsAllowRedefinitionsWithoutWarning(false),
34 IsWarnIfUnused(false),
Douglas Gregor6c6c54a2012-10-11 00:46:49 +000035 IsPublic(true),
Douglas Gregore8219a62012-10-11 21:07:39 +000036 IsHidden(false),
37 IsAmbiguous(false) {
Reid Spencer5f016e22007-07-11 17:01:13 +000038}
39
Alexander Kornienko8a64bb52012-08-29 00:20:03 +000040MacroInfo::MacroInfo(const MacroInfo &MI, llvm::BumpPtrAllocator &PPAllocator)
41 : Location(MI.Location),
42 EndLocation(MI.EndLocation),
43 UndefLocation(MI.UndefLocation),
44 PreviousDefinition(0),
45 ArgumentList(0),
46 NumArguments(0),
47 ReplacementTokens(MI.ReplacementTokens),
48 DefinitionLength(MI.DefinitionLength),
49 IsDefinitionLengthCached(MI.IsDefinitionLengthCached),
50 IsFunctionLike(MI.IsFunctionLike),
51 IsC99Varargs(MI.IsC99Varargs),
52 IsGNUVarargs(MI.IsGNUVarargs),
53 IsBuiltinMacro(MI.IsBuiltinMacro),
Eli Friedman4fa4b482012-11-14 02:18:46 +000054 HasCommaPasting(MI.HasCommaPasting),
Alexander Kornienko8a64bb52012-08-29 00:20:03 +000055 IsFromAST(MI.IsFromAST),
56 ChangedAfterLoad(MI.ChangedAfterLoad),
57 IsDisabled(MI.IsDisabled),
58 IsUsed(MI.IsUsed),
59 IsAllowRedefinitionsWithoutWarning(MI.IsAllowRedefinitionsWithoutWarning),
60 IsWarnIfUnused(MI.IsWarnIfUnused),
Douglas Gregor6c6c54a2012-10-11 00:46:49 +000061 IsPublic(MI.IsPublic),
Douglas Gregore8219a62012-10-11 21:07:39 +000062 IsHidden(MI.IsHidden),
63 IsAmbiguous(MI.IsAmbiguous) {
Chris Lattnerf47724b2010-08-17 15:55:45 +000064 setArgumentList(MI.ArgumentList, MI.NumArguments, PPAllocator);
65}
66
Alexander Kornienko66da0ab2012-09-28 22:24:03 +000067const MacroInfo *MacroInfo::findDefinitionAtLoc(SourceLocation L,
68 SourceManager &SM) const {
69 assert(L.isValid() && "SourceLocation is invalid.");
70 for (const MacroInfo *MI = this; MI; MI = MI->PreviousDefinition) {
71 if (MI->Location.isInvalid() || // For macros defined on the command line.
72 SM.isBeforeInTranslationUnit(MI->Location, L))
73 return (MI->UndefLocation.isInvalid() ||
74 SM.isBeforeInTranslationUnit(L, MI->UndefLocation)) ? MI : NULL;
75 }
76 return NULL;
77}
78
Argyrios Kyrtzidisb73377e2011-07-07 03:40:34 +000079unsigned MacroInfo::getDefinitionLengthSlow(SourceManager &SM) const {
80 assert(!IsDefinitionLengthCached);
81 IsDefinitionLengthCached = true;
82
83 if (ReplacementTokens.empty())
84 return (DefinitionLength = 0);
85
86 const Token &firstToken = ReplacementTokens.front();
87 const Token &lastToken = ReplacementTokens.back();
88 SourceLocation macroStart = firstToken.getLocation();
89 SourceLocation macroEnd = lastToken.getLocation();
90 assert(macroStart.isValid() && macroEnd.isValid());
91 assert((macroStart.isFileID() || firstToken.is(tok::comment)) &&
92 "Macro defined in macro?");
93 assert((macroEnd.isFileID() || lastToken.is(tok::comment)) &&
94 "Macro defined in macro?");
95 std::pair<FileID, unsigned>
Chandler Carruthe7b2b6e2011-07-25 20:52:32 +000096 startInfo = SM.getDecomposedExpansionLoc(macroStart);
Argyrios Kyrtzidisb73377e2011-07-07 03:40:34 +000097 std::pair<FileID, unsigned>
Chandler Carruthe7b2b6e2011-07-25 20:52:32 +000098 endInfo = SM.getDecomposedExpansionLoc(macroEnd);
Argyrios Kyrtzidisb73377e2011-07-07 03:40:34 +000099 assert(startInfo.first == endInfo.first &&
100 "Macro definition spanning multiple FileIDs ?");
101 assert(startInfo.second <= endInfo.second);
102 DefinitionLength = endInfo.second - startInfo.second;
103 DefinitionLength += lastToken.getLength();
104
105 return DefinitionLength;
106}
107
Reid Spencer5f016e22007-07-11 17:01:13 +0000108/// isIdenticalTo - Return true if the specified macro definition is equal to
109/// this macro in spelling, arguments, and whitespace. This is used to emit
110/// duplicate definition warnings. This implements the rules in C99 6.10.3.
111///
Reid Spencer5f016e22007-07-11 17:01:13 +0000112bool MacroInfo::isIdenticalTo(const MacroInfo &Other, Preprocessor &PP) const {
113 // Check # tokens in replacement, number of args, and various flags all match.
114 if (ReplacementTokens.size() != Other.ReplacementTokens.size() ||
Chris Lattner25c96482007-07-14 22:46:43 +0000115 getNumArgs() != Other.getNumArgs() ||
Reid Spencer5f016e22007-07-11 17:01:13 +0000116 isFunctionLike() != Other.isFunctionLike() ||
117 isC99Varargs() != Other.isC99Varargs() ||
118 isGNUVarargs() != Other.isGNUVarargs())
119 return false;
120
121 // Check arguments.
122 for (arg_iterator I = arg_begin(), OI = Other.arg_begin(), E = arg_end();
123 I != E; ++I, ++OI)
124 if (*I != *OI) return false;
Mike Stump1eb44332009-09-09 15:08:12 +0000125
Reid Spencer5f016e22007-07-11 17:01:13 +0000126 // Check all the tokens.
127 for (unsigned i = 0, e = ReplacementTokens.size(); i != e; ++i) {
Chris Lattnerd2177732007-07-20 16:59:19 +0000128 const Token &A = ReplacementTokens[i];
129 const Token &B = Other.ReplacementTokens[i];
Chris Lattner688a2482009-03-09 20:33:32 +0000130 if (A.getKind() != B.getKind())
131 return false;
Mike Stump1eb44332009-09-09 15:08:12 +0000132
Chris Lattner688a2482009-03-09 20:33:32 +0000133 // If this isn't the first first token, check that the whitespace and
134 // start-of-line characteristics match.
135 if (i != 0 &&
136 (A.isAtStartOfLine() != B.isAtStartOfLine() ||
137 A.hasLeadingSpace() != B.hasLeadingSpace()))
Reid Spencer5f016e22007-07-11 17:01:13 +0000138 return false;
Mike Stump1eb44332009-09-09 15:08:12 +0000139
Reid Spencer5f016e22007-07-11 17:01:13 +0000140 // If this is an identifier, it is easy.
141 if (A.getIdentifierInfo() || B.getIdentifierInfo()) {
142 if (A.getIdentifierInfo() != B.getIdentifierInfo())
143 return false;
144 continue;
145 }
Mike Stump1eb44332009-09-09 15:08:12 +0000146
Reid Spencer5f016e22007-07-11 17:01:13 +0000147 // Otherwise, check the spelling.
148 if (PP.getSpelling(A) != PP.getSpelling(B))
149 return false;
150 }
Mike Stump1eb44332009-09-09 15:08:12 +0000151
Reid Spencer5f016e22007-07-11 17:01:13 +0000152 return true;
153}