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"
16using namespace clang;
17
18MacroInfo::MacroInfo(SourceLocation DefLoc)
19  : Location(DefLoc),
20    ArgumentList(0),
21    NumArguments(0),
22    IsDefinitionLengthCached(false),
23    IsFunctionLike(false),
24    IsC99Varargs(false),
25    IsGNUVarargs(false),
26    IsBuiltinMacro(false),
27    HasCommaPasting(false),
28    IsDisabled(false),
29    IsUsed(false),
30    IsAllowRedefinitionsWithoutWarning(false),
31    IsWarnIfUnused(false),
32    FromASTFile(false) {
33}
34
35unsigned 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>
52      startInfo = SM.getDecomposedExpansionLoc(macroStart);
53  std::pair<FileID, unsigned>
54      endInfo = SM.getDecomposedExpansionLoc(macroEnd);
55  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
64/// \brief Return true if the specified macro definition is equal to
65/// this macro in spelling, arguments, and whitespace.
66///
67/// \param Syntactically if true, the macro definitions can be identical even
68/// if they use different identifiers for the function macro parameters.
69/// Otherwise the comparison is lexical and this implements the rules in
70/// C99 6.10.3.
71bool MacroInfo::isIdenticalTo(const MacroInfo &Other, Preprocessor &PP,
72                              bool Syntactically) const {
73  bool Lexically = !Syntactically;
74
75  // Check # tokens in replacement, number of args, and various flags all match.
76  if (ReplacementTokens.size() != Other.ReplacementTokens.size() ||
77      getNumArgs() != Other.getNumArgs() ||
78      isFunctionLike() != Other.isFunctionLike() ||
79      isC99Varargs() != Other.isC99Varargs() ||
80      isGNUVarargs() != Other.isGNUVarargs())
81    return false;
82
83  if (Lexically) {
84    // Check arguments.
85    for (arg_iterator I = arg_begin(), OI = Other.arg_begin(), E = arg_end();
86         I != E; ++I, ++OI)
87      if (*I != *OI) return false;
88  }
89
90  // Check all the tokens.
91  for (unsigned i = 0, e = ReplacementTokens.size(); i != e; ++i) {
92    const Token &A = ReplacementTokens[i];
93    const Token &B = Other.ReplacementTokens[i];
94    if (A.getKind() != B.getKind())
95      return false;
96
97    // If this isn't the first first token, check that the whitespace and
98    // start-of-line characteristics match.
99    if (i != 0 &&
100        (A.isAtStartOfLine() != B.isAtStartOfLine() ||
101         A.hasLeadingSpace() != B.hasLeadingSpace()))
102      return false;
103
104    // If this is an identifier, it is easy.
105    if (A.getIdentifierInfo() || B.getIdentifierInfo()) {
106      if (A.getIdentifierInfo() == B.getIdentifierInfo())
107        continue;
108      if (Lexically)
109        return false;
110      // With syntactic equivalence the parameter names can be different as long
111      // as they are used in the same place.
112      int AArgNum = getArgumentNum(A.getIdentifierInfo());
113      if (AArgNum == -1)
114        return false;
115      if (AArgNum != Other.getArgumentNum(B.getIdentifierInfo()))
116        return false;
117      continue;
118    }
119
120    // Otherwise, check the spelling.
121    if (PP.getSpelling(A) != PP.getSpelling(B))
122      return false;
123  }
124
125  return true;
126}
127
128MacroDirective::DefInfo MacroDirective::getDefinition(bool AllowHidden) {
129  MacroDirective *MD = this;
130  SourceLocation UndefLoc;
131  Optional<bool> isPublic;
132  for (; MD; MD = MD->getPrevious()) {
133    if (!AllowHidden && MD->isHidden())
134      continue;
135
136    if (DefMacroDirective *DefMD = dyn_cast<DefMacroDirective>(MD))
137      return DefInfo(DefMD, UndefLoc,
138                     !isPublic.hasValue() || isPublic.getValue());
139
140    if (UndefMacroDirective *UndefMD = dyn_cast<UndefMacroDirective>(MD)) {
141      UndefLoc = UndefMD->getLocation();
142      continue;
143    }
144
145    VisibilityMacroDirective *VisMD = cast<VisibilityMacroDirective>(MD);
146    if (!isPublic.hasValue())
147      isPublic = VisMD->isPublic();
148  }
149
150  return DefInfo();
151}
152
153const MacroDirective::DefInfo
154MacroDirective::findDirectiveAtLoc(SourceLocation L, SourceManager &SM) const {
155  assert(L.isValid() && "SourceLocation is invalid.");
156  for (DefInfo Def = getDefinition(); Def; Def = Def.getPreviousDefinition()) {
157    if (Def.getLocation().isInvalid() ||  // For macros defined on the command line.
158        SM.isBeforeInTranslationUnit(Def.getLocation(), L))
159      return (!Def.isUndefined() ||
160              SM.isBeforeInTranslationUnit(L, Def.getUndefLocation()))
161                  ? Def : DefInfo();
162  }
163  return DefInfo();
164}
165