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/Parse/Parser.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 static bool isBuiltinFile(SourceManager &SM, SourceLocation Loc) {
92 StringRef Filename(SM.getPresumedLoc(Loc).getFilename());
93 return Filename.equals("<built-in>");
96 static bool isCommandLineFile(SourceManager &SM, SourceLocation Loc) {
97 StringRef Filename(SM.getPresumedLoc(Loc).getFilename());
98 return Filename.equals("<command line>");
101 void MacroPPCallbacks::updateStatusToNextScope() {
104 Status = InitializedScope;
106 case InitializedScope:
107 Status = BuiltinScope;
110 Status = CommandLineIncludeScope;
112 case CommandLineIncludeScope:
113 Status = MainFileScope;
116 llvm_unreachable("There is no next scope, already in the final scope");
120 void MacroPPCallbacks::FileEntered(SourceLocation Loc) {
121 SourceLocation LineLoc = getCorrectLocation(LastHashLoc);
124 updateStatusToNextScope();
126 case InitializedScope:
127 updateStatusToNextScope();
130 if (isCommandLineFile(PP.getSourceManager(), Loc))
132 updateStatusToNextScope();
134 case CommandLineIncludeScope:
135 EnteredCommandLineIncludeFiles++;
141 Scopes.push_back(Gen->getCGDebugInfo()->CreateTempMacroFile(getCurrentScope(),
145 void MacroPPCallbacks::FileExited(SourceLocation Loc) {
148 llvm_unreachable("Do not expect to exit a file from current scope");
150 if (!isBuiltinFile(PP.getSourceManager(), Loc))
151 // Skip next scope and change status to MainFileScope.
152 Status = MainFileScope;
154 case CommandLineIncludeScope:
155 if (!EnteredCommandLineIncludeFiles) {
156 updateStatusToNextScope();
159 EnteredCommandLineIncludeFiles--;
168 void MacroPPCallbacks::FileChanged(SourceLocation Loc, FileChangeReason Reason,
169 SrcMgr::CharacteristicKind FileType,
171 // Only care about enter file or exit file changes.
172 if (Reason == EnterFile)
174 else if (Reason == ExitFile)
178 void MacroPPCallbacks::InclusionDirective(
179 SourceLocation HashLoc, const Token &IncludeTok, StringRef FileName,
180 bool IsAngled, CharSourceRange FilenameRange, const FileEntry *File,
181 StringRef SearchPath, StringRef RelativePath, const Module *Imported,
182 SrcMgr::CharacteristicKind FileType) {
184 // Record the line location of the current included file.
185 LastHashLoc = HashLoc;
188 void MacroPPCallbacks::MacroDefined(const Token &MacroNameTok,
189 const MacroDirective *MD) {
190 IdentifierInfo *Id = MacroNameTok.getIdentifierInfo();
191 SourceLocation location = getCorrectLocation(MacroNameTok.getLocation());
192 std::string NameBuffer, ValueBuffer;
193 llvm::raw_string_ostream Name(NameBuffer);
194 llvm::raw_string_ostream Value(ValueBuffer);
195 writeMacroDefinition(*Id, *MD->getMacroInfo(), PP, Name, Value);
196 Gen->getCGDebugInfo()->CreateMacro(getCurrentScope(),
197 llvm::dwarf::DW_MACINFO_define, location,
198 Name.str(), Value.str());
201 void MacroPPCallbacks::MacroUndefined(const Token &MacroNameTok,
202 const MacroDefinition &MD,
203 const MacroDirective *Undef) {
204 IdentifierInfo *Id = MacroNameTok.getIdentifierInfo();
205 SourceLocation location = getCorrectLocation(MacroNameTok.getLocation());
206 Gen->getCGDebugInfo()->CreateMacro(getCurrentScope(),
207 llvm::dwarf::DW_MACINFO_undef, location,