Coverage Report

Created: 2020-09-19 12:23

/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/lib/Lex/MacroInfo.cpp
Line
Count
Source (jump to first uncovered line)
1
//===- MacroInfo.cpp - Information about #defined identifiers -------------===//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
//
9
// This file implements the MacroInfo interface.
10
//
11
//===----------------------------------------------------------------------===//
12
13
#include "clang/Lex/MacroInfo.h"
14
#include "clang/Basic/IdentifierTable.h"
15
#include "clang/Basic/LLVM.h"
16
#include "clang/Basic/SourceLocation.h"
17
#include "clang/Basic/SourceManager.h"
18
#include "clang/Basic/TokenKinds.h"
19
#include "clang/Lex/Preprocessor.h"
20
#include "clang/Lex/Token.h"
21
#include "llvm/ADT/Optional.h"
22
#include "llvm/ADT/StringRef.h"
23
#include "llvm/Support/Casting.h"
24
#include "llvm/Support/Compiler.h"
25
#include "llvm/Support/raw_ostream.h"
26
#include <cassert>
27
#include <utility>
28
29
using namespace clang;
30
31
MacroInfo::MacroInfo(SourceLocation DefLoc)
32
    : Location(DefLoc), IsDefinitionLengthCached(false), IsFunctionLike(false),
33
      IsC99Varargs(false), IsGNUVarargs(false), IsBuiltinMacro(false),
34
      HasCommaPasting(false), IsDisabled(false), IsUsed(false),
35
      IsAllowRedefinitionsWithoutWarning(false), IsWarnIfUnused(false),
36
52.9M
      UsedForHeaderGuard(false) {}
37
38
779k
unsigned MacroInfo::getDefinitionLengthSlow(const SourceManager &SM) const {
39
779k
  assert(!IsDefinitionLengthCached);
40
779k
  IsDefinitionLengthCached = true;
41
779k
42
779k
  if (ReplacementTokens.empty())
43
0
    return (DefinitionLength = 0);
44
779k
45
779k
  const Token &firstToken = ReplacementTokens.front();
46
779k
  const Token &lastToken = ReplacementTokens.back();
47
779k
  SourceLocation macroStart = firstToken.getLocation();
48
779k
  SourceLocation macroEnd = lastToken.getLocation();
49
779k
  assert(macroStart.isValid() && macroEnd.isValid());
50
779k
  assert((macroStart.isFileID() || firstToken.is(tok::comment)) &&
51
779k
         "Macro defined in macro?");
52
779k
  assert((macroEnd.isFileID() || lastToken.is(tok::comment)) &&
53
779k
         "Macro defined in macro?");
54
779k
  std::pair<FileID, unsigned>
55
779k
      startInfo = SM.getDecomposedExpansionLoc(macroStart);
56
779k
  std::pair<FileID, unsigned>
57
779k
      endInfo = SM.getDecomposedExpansionLoc(macroEnd);
58
779k
  assert(startInfo.first == endInfo.first &&
59
779k
         "Macro definition spanning multiple FileIDs ?");
60
779k
  assert(startInfo.second <= endInfo.second);
61
779k
  DefinitionLength = endInfo.second - startInfo.second;
62
779k
  DefinitionLength += lastToken.getLength();
63
779k
64
779k
  return DefinitionLength;
65
779k
}
66
67
/// Return true if the specified macro definition is equal to
68
/// this macro in spelling, arguments, and whitespace.
69
///
70
/// \param Syntactically if true, the macro definitions can be identical even
71
/// if they use different identifiers for the function macro parameters.
72
/// Otherwise the comparison is lexical and this implements the rules in
73
/// C99 6.10.3.
74
bool MacroInfo::isIdenticalTo(const MacroInfo &Other, Preprocessor &PP,
75
300k
                              bool Syntactically) const {
76
300k
  bool Lexically = !Syntactically;
77
300k
78
  // Check # tokens in replacement, number of args, and various flags all match.
79
300k
  if (ReplacementTokens.size() != Other.ReplacementTokens.size() ||
80
300k
      getNumParams() != Other.getNumParams() ||
81
300k
      isFunctionLike() != Other.isFunctionLike() ||
82
300k
      isC99Varargs() != Other.isC99Varargs() ||
83
300k
      isGNUVarargs() != Other.isGNUVarargs())
84
131
    return false;
85
300k
86
300k
  if (Lexically) {
87
    // Check arguments.
88
300k
    for (param_iterator I = param_begin(), OI = Other.param_begin(),
89
300k
                        E = param_end();
90
300k
         I != E; 
++I, ++OI19
)
91
20
      if (*I != *OI) 
return false1
;
92
300k
  }
93
300k
94
  // Check all the tokens.
95
601k
  
for (unsigned i = 0, e = ReplacementTokens.size(); 300k
i != e;
++i300k
) {
96
300k
    const Token &A = ReplacementTokens[i];
97
300k
    const Token &B = Other.ReplacementTokens[i];
98
300k
    if (A.getKind() != B.getKind())
99
86
      return false;
100
300k
101
    // If this isn't the first first token, check that the whitespace and
102
    // start-of-line characteristics match.
103
300k
    if (i != 0 &&
104
361
        (A.isAtStartOfLine() != B.isAtStartOfLine() ||
105
361
         A.hasLeadingSpace() != B.hasLeadingSpace()))
106
2
      return false;
107
300k
108
    // If this is an identifier, it is easy.
109
300k
    if (A.getIdentifierInfo() || 
B.getIdentifierInfo()300k
) {
110
344
      if (A.getIdentifierInfo() == B.getIdentifierInfo())
111
287
        continue;
112
57
      if (Lexically)
113
36
        return false;
114
      // With syntactic equivalence the parameter names can be different as long
115
      // as they are used in the same place.
116
21
      int AArgNum = getParameterNum(A.getIdentifierInfo());
117
21
      if (AArgNum == -1)
118
0
        return false;
119
21
      if (AArgNum != Other.getParameterNum(B.getIdentifierInfo()))
120
1
        return false;
121
20
      continue;
122
20
    }
123
300k
124
    // Otherwise, check the spelling.
125
300k
    if (PP.getSpelling(A) != PP.getSpelling(B))
126
32
      return false;
127
300k
  }
128
300k
129
300k
  return true;
130
300k
}
131
132
19
LLVM_DUMP_METHOD void MacroInfo::dump() const {
133
19
  llvm::raw_ostream &Out = llvm::errs();
134
19
135
  // FIXME: Dump locations.
136
19
  Out << "MacroInfo " << this;
137
19
  if (IsBuiltinMacro) 
Out << " builtin"0
;
138
19
  if (IsDisabled) 
Out << " disabled"0
;
139
19
  if (IsUsed) 
Out << " used"2
;
140
19
  if (IsAllowRedefinitionsWithoutWarning)
141
0
    Out << " allow_redefinitions_without_warning";
142
19
  if (IsWarnIfUnused) 
Out << " warn_if_unused"0
;
143
19
  if (UsedForHeaderGuard) 
Out << " header_guard"1
;
144
19
145
19
  Out << "\n    #define <macro>";
146
19
  if (IsFunctionLike) {
147
0
    Out << "(";
148
0
    for (unsigned I = 0; I != NumParameters; ++I) {
149
0
      if (I) Out << ", ";
150
0
      Out << ParameterList[I]->getName();
151
0
    }
152
0
    if (IsC99Varargs || IsGNUVarargs) {
153
0
      if (NumParameters && IsC99Varargs) Out << ", ";
154
0
      Out << "...";
155
0
    }
156
0
    Out << ")";
157
0
  }
158
19
159
19
  bool First = true;
160
18
  for (const Token &Tok : ReplacementTokens) {
161
    // Leading space is semantically meaningful in a macro definition,
162
    // so preserve it in the dump output.
163
18
    if (First || 
Tok.hasLeadingSpace()0
)
164
18
      Out << " ";
165
18
    First = false;
166
18
167
18
    if (const char *Punc = tok::getPunctuatorSpelling(Tok.getKind()))
168
0
      Out << Punc;
169
18
    else if (Tok.isLiteral() && Tok.getLiteralData())
170
0
      Out << StringRef(Tok.getLiteralData(), Tok.getLength());
171
18
    else if (auto *II = Tok.getIdentifierInfo())
172
0
      Out << II->getName();
173
18
    else
174
18
      Out << Tok.getName();
175
18
  }
176
19
}
177
178
368M
MacroDirective::DefInfo MacroDirective::getDefinition() {
179
368M
  MacroDirective *MD = this;
180
368M
  SourceLocation UndefLoc;
181
368M
  Optional<bool> isPublic;
182
368M
  for (; MD; 
MD = MD->getPrevious()113k
) {
183
368M
    if (DefMacroDirective *DefMD = dyn_cast<DefMacroDirective>(MD))
184
368M
      return DefInfo(DefMD, UndefLoc,
185
368M
                     !isPublic.hasValue() || 
isPublic.getValue()325
);
186
113k
187
113k
    
if (UndefMacroDirective *113k
UndefMD113k
= dyn_cast<UndefMacroDirective>(MD)) {
188
113k
      UndefLoc = UndefMD->getLocation();
189
113k
      continue;
190
113k
    }
191
18.4E
192
18.4E
    VisibilityMacroDirective *VisMD = cast<VisibilityMacroDirective>(MD);
193
18.4E
    if (!isPublic.hasValue())
194
325
      isPublic = VisMD->isPublic();
195
18.4E
  }
196
368M
197
461
  return DefInfo(nullptr, UndefLoc,
198
461
                 !isPublic.hasValue() || 
isPublic.getValue()0
);
199
368M
}
200
201
const MacroDirective::DefInfo
202
MacroDirective::findDirectiveAtLoc(SourceLocation L,
203
114k
                                   const SourceManager &SM) const {
204
114k
  assert(L.isValid() && "SourceLocation is invalid.");
205
114k
  for (DefInfo Def = getDefinition(); Def; 
Def = Def.getPreviousDefinition()198
) {
206
114k
    if (Def.getLocation().isInvalid() ||  // For macros defined on the command line.
207
107k
        SM.isBeforeInTranslationUnit(Def.getLocation(), L))
208
114k
      return (!Def.isUndefined() ||
209
264
              SM.isBeforeInTranslationUnit(L, Def.getUndefLocation()))
210
114k
                  ? Def : 
DefInfo()205
;
211
114k
  }
212
86
  return DefInfo();
213
114k
}
214
215
0
LLVM_DUMP_METHOD void MacroDirective::dump() const {
216
0
  llvm::raw_ostream &Out = llvm::errs();
217
0
218
0
  switch (getKind()) {
219
0
  case MD_Define: Out << "DefMacroDirective"; break;
220
0
  case MD_Undefine: Out << "UndefMacroDirective"; break;
221
0
  case MD_Visibility: Out << "VisibilityMacroDirective"; break;
222
0
  }
223
0
  Out << " " << this;
224
  // FIXME: Dump SourceLocation.
225
0
  if (auto *Prev = getPrevious())
226
0
    Out << " prev " << Prev;
227
0
  if (IsFromPCH) Out << " from_pch";
228
0
229
0
  if (isa<VisibilityMacroDirective>(this))
230
0
    Out << (IsPublic ? " public" : " private");
231
0
232
0
  if (auto *DMD = dyn_cast<DefMacroDirective>(this)) {
233
0
    if (auto *Info = DMD->getInfo()) {
234
0
      Out << "\n  ";
235
0
      Info->dump();
236
0
    }
237
0
  }
238
0
  Out << "\n";
239
0
}
240
241
ModuleMacro *ModuleMacro::create(Preprocessor &PP, Module *OwningModule,
242
                                 IdentifierInfo *II, MacroInfo *Macro,
243
2.02M
                                 ArrayRef<ModuleMacro *> Overrides) {
244
2.02M
  void *Mem = PP.getPreprocessorAllocator().Allocate(
245
2.02M
      sizeof(ModuleMacro) + sizeof(ModuleMacro *) * Overrides.size(),
246
2.02M
      alignof(ModuleMacro));
247
2.02M
  return new (Mem) ModuleMacro(OwningModule, II, Macro, Overrides);
248
2.02M
}