Coverage Report

Created: 2019-07-24 05:18

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/tools/clang/lib/CodeGen/MacroPPCallbacks.cpp
Line
Count
Source (jump to first uncovered line)
1
//===--- MacroPPCallbacks.cpp ---------------------------------------------===//
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 contains implementation for the macro preprocessors callbacks.
10
//
11
//===----------------------------------------------------------------------===//
12
13
#include "MacroPPCallbacks.h"
14
#include "CGDebugInfo.h"
15
#include "clang/CodeGen/ModuleBuilder.h"
16
#include "clang/Lex/MacroInfo.h"
17
#include "clang/Lex/Preprocessor.h"
18
19
using namespace clang;
20
21
void MacroPPCallbacks::writeMacroDefinition(const IdentifierInfo &II,
22
                                            const MacroInfo &MI,
23
                                            Preprocessor &PP, raw_ostream &Name,
24
1.38k
                                            raw_ostream &Value) {
25
1.38k
  Name << II.getName();
26
1.38k
27
1.38k
  if (MI.isFunctionLike()) {
28
15
    Name << '(';
29
15
    if (!MI.param_empty()) {
30
15
      MacroInfo::param_iterator AI = MI.param_begin(), E = MI.param_end();
31
35
      for (; AI + 1 != E; 
++AI20
) {
32
20
        Name << (*AI)->getName();
33
20
        Name << ',';
34
20
      }
35
15
36
15
      // Last argument.
37
15
      if ((*AI)->getName() == "__VA_ARGS__")
38
0
        Name << "...";
39
15
      else
40
15
        Name << (*AI)->getName();
41
15
    }
42
15
43
15
    if (MI.isGNUVarargs())
44
0
      // #define foo(x...)
45
0
      Name << "...";
46
15
47
15
    Name << ')';
48
15
  }
49
1.38k
50
1.38k
  SmallString<128> SpellingBuffer;
51
1.38k
  bool First = true;
52
1.71k
  for (const auto &T : MI.tokens()) {
53
1.71k
    if (!First && 
T.hasLeadingSpace()360
)
54
172
      Value << ' ';
55
1.71k
56
1.71k
    Value << PP.getSpelling(T, SpellingBuffer);
57
1.71k
    First = false;
58
1.71k
  }
59
1.38k
}
60
61
MacroPPCallbacks::MacroPPCallbacks(CodeGenerator *Gen, Preprocessor &PP)
62
5
    : Gen(Gen), PP(PP), Status(NoScope) {}
63
64
// This is the expected flow of enter/exit compiler and user files:
65
// - Main File Enter
66
//   - <built-in> file enter
67
//     {Compiler macro definitions} - (Line=0, no scope)
68
//     - (Optional) <command line> file enter
69
//     {Command line macro definitions} - (Line=0, no scope)
70
//     - (Optional) <command line> file exit
71
//     {Command line file includes} - (Line=0, Main file scope)
72
//       {macro definitions and file includes} - (Line!=0, Parent scope)
73
//   - <built-in> file exit
74
//   {User code macro definitions and file includes} - (Line!=0, Parent scope)
75
76
1.43k
llvm::DIMacroFile *MacroPPCallbacks::getCurrentScope() {
77
1.43k
  if (Status == MainFileScope || 
Status == CommandLineIncludeScope1.38k
)
78
60
    return Scopes.back();
79
1.37k
  return nullptr;
80
1.37k
}
81
82
1.44k
SourceLocation MacroPPCallbacks::getCorrectLocation(SourceLocation Loc) {
83
1.44k
  if (Status == MainFileScope || 
EnteredCommandLineIncludeFiles1.39k
)
84
55
    return Loc;
85
1.38k
86
1.38k
  // While parsing skipped files, location of macros is invalid.
87
1.38k
  // Invalid location represents line zero.
88
1.38k
  return SourceLocation();
89
1.38k
}
90
91
20
void MacroPPCallbacks::updateStatusToNextScope() {
92
20
  switch (Status) {
93
20
  case NoScope:
94
5
    Status = InitializedScope;
95
5
    break;
96
20
  case InitializedScope:
97
5
    Status = BuiltinScope;
98
5
    break;
99
20
  case BuiltinScope:
100
5
    Status = CommandLineIncludeScope;
101
5
    break;
102
20
  case CommandLineIncludeScope:
103
5
    Status = MainFileScope;
104
5
    break;
105
20
  case MainFileScope:
106
0
    llvm_unreachable("There is no next scope, already in the final scope");
107
20
  }
108
20
}
109
110
29
void MacroPPCallbacks::FileEntered(SourceLocation Loc) {
111
29
  SourceLocation LineLoc = getCorrectLocation(LastHashLoc);
112
29
  switch (Status) {
113
29
  case NoScope:
114
5
    updateStatusToNextScope();
115
5
    break;
116
29
  case InitializedScope:
117
5
    updateStatusToNextScope();
118
5
    return;
119
29
  case BuiltinScope:
120
9
    if (PP.getSourceManager().isWrittenInCommandLineFile(Loc))
121
4
      return;
122
5
    updateStatusToNextScope();
123
5
    LLVM_FALLTHROUGH;
124
5
  case CommandLineIncludeScope:
125
5
    EnteredCommandLineIncludeFiles++;
126
5
    break;
127
10
  case MainFileScope:
128
10
    break;
129
20
  }
130
20
131
20
  Scopes.push_back(Gen->getCGDebugInfo()->CreateTempMacroFile(getCurrentScope(),
132
20
                                                              LineLoc, Loc));
133
20
}
134
135
24
void MacroPPCallbacks::FileExited(SourceLocation Loc) {
136
24
  switch (Status) {
137
24
  default:
138
0
    llvm_unreachable("Do not expect to exit a file from current scope");
139
24
  case BuiltinScope:
140
4
    if (!PP.getSourceManager().isWrittenInBuiltinFile(Loc))
141
0
      // Skip next scope and change status to MainFileScope.
142
0
      Status = MainFileScope;
143
4
    return;
144
24
  case CommandLineIncludeScope:
145
10
    if (!EnteredCommandLineIncludeFiles) {
146
5
      updateStatusToNextScope();
147
5
      return;
148
5
    }
149
5
    EnteredCommandLineIncludeFiles--;
150
5
    break;
151
10
  case MainFileScope:
152
10
    break;
153
15
  }
154
15
155
15
  Scopes.pop_back();
156
15
}
157
158
void MacroPPCallbacks::FileChanged(SourceLocation Loc, FileChangeReason Reason,
159
                                   SrcMgr::CharacteristicKind FileType,
160
62
                                   FileID PrevFID) {
161
62
  // Only care about enter file or exit file changes.
162
62
  if (Reason == EnterFile)
163
29
    FileEntered(Loc);
164
33
  else if (Reason == ExitFile)
165
24
    FileExited(Loc);
166
62
}
167
168
void MacroPPCallbacks::InclusionDirective(
169
    SourceLocation HashLoc, const Token &IncludeTok, StringRef FileName,
170
    bool IsAngled, CharSourceRange FilenameRange, const FileEntry *File,
171
    StringRef SearchPath, StringRef RelativePath, const Module *Imported,
172
15
    SrcMgr::CharacteristicKind FileType) {
173
15
174
15
  // Record the line location of the current included file.
175
15
  LastHashLoc = HashLoc;
176
15
}
177
178
void MacroPPCallbacks::MacroDefined(const Token &MacroNameTok,
179
1.38k
                                    const MacroDirective *MD) {
180
1.38k
  IdentifierInfo *Id = MacroNameTok.getIdentifierInfo();
181
1.38k
  SourceLocation location = getCorrectLocation(MacroNameTok.getLocation());
182
1.38k
  std::string NameBuffer, ValueBuffer;
183
1.38k
  llvm::raw_string_ostream Name(NameBuffer);
184
1.38k
  llvm::raw_string_ostream Value(ValueBuffer);
185
1.38k
  writeMacroDefinition(*Id, *MD->getMacroInfo(), PP, Name, Value);
186
1.38k
  Gen->getCGDebugInfo()->CreateMacro(getCurrentScope(),
187
1.38k
                                     llvm::dwarf::DW_MACINFO_define, location,
188
1.38k
                                     Name.str(), Value.str());
189
1.38k
}
190
191
void MacroPPCallbacks::MacroUndefined(const Token &MacroNameTok,
192
                                      const MacroDefinition &MD,
193
30
                                      const MacroDirective *Undef) {
194
30
  IdentifierInfo *Id = MacroNameTok.getIdentifierInfo();
195
30
  SourceLocation location = getCorrectLocation(MacroNameTok.getLocation());
196
30
  Gen->getCGDebugInfo()->CreateMacro(getCurrentScope(),
197
30
                                     llvm::dwarf::DW_MACINFO_undef, location,
198
30
                                     Id->getName(), "");
199
30
}