]> CyberLeo.Net >> Repos - FreeBSD/stable/9.git/blob - contrib/llvm/tools/clang/lib/Lex/MacroInfo.cpp
MFC r244628:
[FreeBSD/stable/9.git] / contrib / llvm / tools / clang / lib / Lex / MacroInfo.cpp
1 //===--- MacroInfo.cpp - Information about #defined identifiers -----------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file implements the MacroInfo interface.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "clang/Lex/MacroInfo.h"
15 #include "clang/Lex/Preprocessor.h"
16 using namespace clang;
17
18 MacroInfo::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),
28     IsFromAST(false),
29     ChangedAfterLoad(false),
30     IsDisabled(false),
31     IsUsed(false),
32     IsAllowRedefinitionsWithoutWarning(false),
33     IsWarnIfUnused(false),
34     IsPublic(true),
35     IsHidden(false),
36     IsAmbiguous(false) {
37 }
38
39 MacroInfo::MacroInfo(const MacroInfo &MI, llvm::BumpPtrAllocator &PPAllocator)
40   : Location(MI.Location),
41     EndLocation(MI.EndLocation),
42     UndefLocation(MI.UndefLocation),
43     PreviousDefinition(0),
44     ArgumentList(0),
45     NumArguments(0),
46     ReplacementTokens(MI.ReplacementTokens),
47     DefinitionLength(MI.DefinitionLength),
48     IsDefinitionLengthCached(MI.IsDefinitionLengthCached),
49     IsFunctionLike(MI.IsFunctionLike),
50     IsC99Varargs(MI.IsC99Varargs),
51     IsGNUVarargs(MI.IsGNUVarargs),
52     IsBuiltinMacro(MI.IsBuiltinMacro),
53     IsFromAST(MI.IsFromAST),
54     ChangedAfterLoad(MI.ChangedAfterLoad),
55     IsDisabled(MI.IsDisabled),
56     IsUsed(MI.IsUsed),
57     IsAllowRedefinitionsWithoutWarning(MI.IsAllowRedefinitionsWithoutWarning),
58     IsWarnIfUnused(MI.IsWarnIfUnused),
59     IsPublic(MI.IsPublic),
60     IsHidden(MI.IsHidden),
61     IsAmbiguous(MI.IsAmbiguous) {
62   setArgumentList(MI.ArgumentList, MI.NumArguments, PPAllocator);
63 }
64
65 const MacroInfo *MacroInfo::findDefinitionAtLoc(SourceLocation L,
66                                                 SourceManager &SM) const {
67   assert(L.isValid() && "SourceLocation is invalid.");
68   for (const MacroInfo *MI = this; MI; MI = MI->PreviousDefinition) {
69     if (MI->Location.isInvalid() ||  // For macros defined on the command line.
70         SM.isBeforeInTranslationUnit(MI->Location, L))
71       return (MI->UndefLocation.isInvalid() ||
72               SM.isBeforeInTranslationUnit(L, MI->UndefLocation)) ? MI : NULL;
73   }
74   return NULL;
75 }
76
77 unsigned MacroInfo::getDefinitionLengthSlow(SourceManager &SM) const {
78   assert(!IsDefinitionLengthCached);
79   IsDefinitionLengthCached = true;
80
81   if (ReplacementTokens.empty())
82     return (DefinitionLength = 0);
83
84   const Token &firstToken = ReplacementTokens.front();
85   const Token &lastToken = ReplacementTokens.back();
86   SourceLocation macroStart = firstToken.getLocation();
87   SourceLocation macroEnd = lastToken.getLocation();
88   assert(macroStart.isValid() && macroEnd.isValid());
89   assert((macroStart.isFileID() || firstToken.is(tok::comment)) &&
90          "Macro defined in macro?");
91   assert((macroEnd.isFileID() || lastToken.is(tok::comment)) &&
92          "Macro defined in macro?");
93   std::pair<FileID, unsigned>
94       startInfo = SM.getDecomposedExpansionLoc(macroStart);
95   std::pair<FileID, unsigned>
96       endInfo = SM.getDecomposedExpansionLoc(macroEnd);
97   assert(startInfo.first == endInfo.first &&
98          "Macro definition spanning multiple FileIDs ?");
99   assert(startInfo.second <= endInfo.second);
100   DefinitionLength = endInfo.second - startInfo.second;
101   DefinitionLength += lastToken.getLength();
102
103   return DefinitionLength;
104 }
105
106 /// isIdenticalTo - Return true if the specified macro definition is equal to
107 /// this macro in spelling, arguments, and whitespace.  This is used to emit
108 /// duplicate definition warnings.  This implements the rules in C99 6.10.3.
109 ///
110 bool MacroInfo::isIdenticalTo(const MacroInfo &Other, Preprocessor &PP) const {
111   // Check # tokens in replacement, number of args, and various flags all match.
112   if (ReplacementTokens.size() != Other.ReplacementTokens.size() ||
113       getNumArgs() != Other.getNumArgs() ||
114       isFunctionLike() != Other.isFunctionLike() ||
115       isC99Varargs() != Other.isC99Varargs() ||
116       isGNUVarargs() != Other.isGNUVarargs())
117     return false;
118
119   // Check arguments.
120   for (arg_iterator I = arg_begin(), OI = Other.arg_begin(), E = arg_end();
121        I != E; ++I, ++OI)
122     if (*I != *OI) return false;
123
124   // Check all the tokens.
125   for (unsigned i = 0, e = ReplacementTokens.size(); i != e; ++i) {
126     const Token &A = ReplacementTokens[i];
127     const Token &B = Other.ReplacementTokens[i];
128     if (A.getKind() != B.getKind())
129       return false;
130
131     // If this isn't the first first token, check that the whitespace and
132     // start-of-line characteristics match.
133     if (i != 0 &&
134         (A.isAtStartOfLine() != B.isAtStartOfLine() ||
135          A.hasLeadingSpace() != B.hasLeadingSpace()))
136       return false;
137
138     // If this is an identifier, it is easy.
139     if (A.getIdentifierInfo() || B.getIdentifierInfo()) {
140       if (A.getIdentifierInfo() != B.getIdentifierInfo())
141         return false;
142       continue;
143     }
144
145     // Otherwise, check the spelling.
146     if (PP.getSpelling(A) != PP.getSpelling(B))
147       return false;
148   }
149
150   return true;
151 }