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