1 //===--- MacroPPCallbacks.cpp ---------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 // This file contains implementation for the macro preprocessors callbacks.
11 //===----------------------------------------------------------------------===//
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"
19 using namespace clang
;
21 void MacroPPCallbacks::writeMacroDefinition(const IdentifierInfo
&II
,
23 Preprocessor
&PP
, raw_ostream
&Name
,
27 if (MI
.isFunctionLike()) {
29 if (!MI
.param_empty()) {
30 MacroInfo::param_iterator AI
= MI
.param_begin(), E
= MI
.param_end();
31 for (; AI
+ 1 != E
; ++AI
) {
32 Name
<< (*AI
)->getName();
37 if ((*AI
)->getName() == "__VA_ARGS__")
40 Name
<< (*AI
)->getName();
43 if (MI
.isGNUVarargs())
50 SmallString
<128> SpellingBuffer
;
52 for (const auto &T
: MI
.tokens()) {
53 if (!First
&& T
.hasLeadingSpace())
56 Value
<< PP
.getSpelling(T
, SpellingBuffer
);
61 MacroPPCallbacks::MacroPPCallbacks(CodeGenerator
*Gen
, Preprocessor
&PP
)
62 : Gen(Gen
), PP(PP
), Status(NoScope
) {}
64 // This is the expected flow of enter/exit compiler and user files:
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)
76 llvm::DIMacroFile
*MacroPPCallbacks::getCurrentScope() {
77 if (Status
== MainFileScope
|| Status
== CommandLineIncludeScope
)
82 SourceLocation
MacroPPCallbacks::getCorrectLocation(SourceLocation Loc
) {
83 if (Status
== MainFileScope
|| EnteredCommandLineIncludeFiles
)
86 // While parsing skipped files, location of macros is invalid.
87 // Invalid location represents line zero.
88 return SourceLocation();
91 void MacroPPCallbacks::updateStatusToNextScope() {
94 Status
= InitializedScope
;
96 case InitializedScope
:
97 Status
= BuiltinScope
;
100 Status
= CommandLineIncludeScope
;
102 case CommandLineIncludeScope
:
103 Status
= MainFileScope
;
106 llvm_unreachable("There is no next scope, already in the final scope");
110 void MacroPPCallbacks::FileEntered(SourceLocation Loc
) {
111 SourceLocation LineLoc
= getCorrectLocation(LastHashLoc
);
114 updateStatusToNextScope();
116 case InitializedScope
:
117 updateStatusToNextScope();
120 if (PP
.getSourceManager().isWrittenInCommandLineFile(Loc
))
122 updateStatusToNextScope();
124 case CommandLineIncludeScope
:
125 EnteredCommandLineIncludeFiles
++;
131 Scopes
.push_back(Gen
->getCGDebugInfo()->CreateTempMacroFile(getCurrentScope(),
135 void MacroPPCallbacks::FileExited(SourceLocation Loc
) {
138 llvm_unreachable("Do not expect to exit a file from current scope");
140 if (!PP
.getSourceManager().isWrittenInBuiltinFile(Loc
))
141 // Skip next scope and change status to MainFileScope.
142 Status
= MainFileScope
;
144 case CommandLineIncludeScope
:
145 if (!EnteredCommandLineIncludeFiles
) {
146 updateStatusToNextScope();
149 EnteredCommandLineIncludeFiles
--;
158 void MacroPPCallbacks::FileChanged(SourceLocation Loc
, FileChangeReason Reason
,
159 SrcMgr::CharacteristicKind FileType
,
161 // Only care about enter file or exit file changes.
162 if (Reason
== EnterFile
)
164 else if (Reason
== ExitFile
)
168 void MacroPPCallbacks::InclusionDirective(
169 SourceLocation HashLoc
, const Token
&IncludeTok
, StringRef FileName
,
170 bool IsAngled
, CharSourceRange FilenameRange
, OptionalFileEntryRef File
,
171 StringRef SearchPath
, StringRef RelativePath
, const Module
*Imported
,
172 SrcMgr::CharacteristicKind FileType
) {
174 // Record the line location of the current included file.
175 LastHashLoc
= HashLoc
;
178 void MacroPPCallbacks::MacroDefined(const Token
&MacroNameTok
,
179 const MacroDirective
*MD
) {
180 IdentifierInfo
*Id
= MacroNameTok
.getIdentifierInfo();
181 SourceLocation location
= getCorrectLocation(MacroNameTok
.getLocation());
182 std::string NameBuffer
, ValueBuffer
;
183 llvm::raw_string_ostream
Name(NameBuffer
);
184 llvm::raw_string_ostream
Value(ValueBuffer
);
185 writeMacroDefinition(*Id
, *MD
->getMacroInfo(), PP
, Name
, Value
);
186 Gen
->getCGDebugInfo()->CreateMacro(getCurrentScope(),
187 llvm::dwarf::DW_MACINFO_define
, location
,
188 Name
.str(), Value
.str());
191 void MacroPPCallbacks::MacroUndefined(const Token
&MacroNameTok
,
192 const MacroDefinition
&MD
,
193 const MacroDirective
*Undef
) {
194 IdentifierInfo
*Id
= MacroNameTok
.getIdentifierInfo();
195 SourceLocation location
= getCorrectLocation(MacroNameTok
.getLocation());
196 Gen
->getCGDebugInfo()->CreateMacro(getCurrentScope(),
197 llvm::dwarf::DW_MACINFO_undef
, location
,