1 //===--- MacroPPCallbacks.cpp ---------------------------------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file contains implementation for the macro preprocessors callbacks.
12 //===----------------------------------------------------------------------===//
14 #include "MacroPPCallbacks.h"
15 #include "CGDebugInfo.h"
16 #include "clang/CodeGen/ModuleBuilder.h"
17 #include "clang/Lex/MacroInfo.h"
18 #include "clang/Lex/Preprocessor.h"
20 using namespace clang;
22 void MacroPPCallbacks::writeMacroDefinition(const IdentifierInfo &II,
24 Preprocessor &PP, raw_ostream &Name,
28 if (MI.isFunctionLike()) {
30 if (!MI.param_empty()) {
31 MacroInfo::param_iterator AI = MI.param_begin(), E = MI.param_end();
32 for (; AI + 1 != E; ++AI) {
33 Name << (*AI)->getName();
38 if ((*AI)->getName() == "__VA_ARGS__")
41 Name << (*AI)->getName();
44 if (MI.isGNUVarargs())
51 SmallString<128> SpellingBuffer;
53 for (const auto &T : MI.tokens()) {
54 if (!First && T.hasLeadingSpace())
57 Value << PP.getSpelling(T, SpellingBuffer);
62 MacroPPCallbacks::MacroPPCallbacks(CodeGenerator *Gen, Preprocessor &PP)
63 : Gen(Gen), PP(PP), Status(NoScope) {}
65 // This is the expected flow of enter/exit compiler and user files:
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)
77 llvm::DIMacroFile *MacroPPCallbacks::getCurrentScope() {
78 if (Status == MainFileScope || Status == CommandLineIncludeScope)
83 SourceLocation MacroPPCallbacks::getCorrectLocation(SourceLocation Loc) {
84 if (Status == MainFileScope || EnteredCommandLineIncludeFiles)
87 // While parsing skipped files, location of macros is invalid.
88 // Invalid location represents line zero.
89 return SourceLocation();
92 void MacroPPCallbacks::updateStatusToNextScope() {
95 Status = InitializedScope;
97 case InitializedScope:
98 Status = BuiltinScope;
101 Status = CommandLineIncludeScope;
103 case CommandLineIncludeScope:
104 Status = MainFileScope;
107 llvm_unreachable("There is no next scope, already in the final scope");
111 void MacroPPCallbacks::FileEntered(SourceLocation Loc) {
112 SourceLocation LineLoc = getCorrectLocation(LastHashLoc);
115 updateStatusToNextScope();
117 case InitializedScope:
118 updateStatusToNextScope();
121 if (PP.getSourceManager().isWrittenInCommandLineFile(Loc))
123 updateStatusToNextScope();
125 case CommandLineIncludeScope:
126 EnteredCommandLineIncludeFiles++;
132 Scopes.push_back(Gen->getCGDebugInfo()->CreateTempMacroFile(getCurrentScope(),
136 void MacroPPCallbacks::FileExited(SourceLocation Loc) {
139 llvm_unreachable("Do not expect to exit a file from current scope");
141 if (!PP.getSourceManager().isWrittenInBuiltinFile(Loc))
142 // Skip next scope and change status to MainFileScope.
143 Status = MainFileScope;
145 case CommandLineIncludeScope:
146 if (!EnteredCommandLineIncludeFiles) {
147 updateStatusToNextScope();
150 EnteredCommandLineIncludeFiles--;
159 void MacroPPCallbacks::FileChanged(SourceLocation Loc, FileChangeReason Reason,
160 SrcMgr::CharacteristicKind FileType,
162 // Only care about enter file or exit file changes.
163 if (Reason == EnterFile)
165 else if (Reason == ExitFile)
169 void MacroPPCallbacks::InclusionDirective(
170 SourceLocation HashLoc, const Token &IncludeTok, StringRef FileName,
171 bool IsAngled, CharSourceRange FilenameRange, const FileEntry *File,
172 StringRef SearchPath, StringRef RelativePath, const Module *Imported,
173 SrcMgr::CharacteristicKind FileType) {
175 // Record the line location of the current included file.
176 LastHashLoc = HashLoc;
179 void 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());
192 void MacroPPCallbacks::MacroUndefined(const Token &MacroNameTok,
193 const MacroDefinition &MD,
194 const MacroDirective *Undef) {
195 IdentifierInfo *Id = MacroNameTok.getIdentifierInfo();
196 SourceLocation location = getCorrectLocation(MacroNameTok.getLocation());
197 Gen->getCGDebugInfo()->CreateMacro(getCurrentScope(),
198 llvm::dwarf::DW_MACINFO_undef, location,