1 //===--- 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" 17 #include "clang/Parse/Parser.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 raw_ostream &Value) { 25 Name << II.getName(); 26 27 if (MI.isFunctionLike()) { 28 Name << '('; 29 if (!MI.arg_empty()) { 30 MacroInfo::arg_iterator AI = MI.arg_begin(), E = MI.arg_end(); 31 for (; AI + 1 != E; ++AI) { 32 Name << (*AI)->getName(); 33 Name << ','; 34 } 35 36 // Last argument. 37 if ((*AI)->getName() == "__VA_ARGS__") 38 Name << "..."; 39 else 40 Name << (*AI)->getName(); 41 } 42 43 if (MI.isGNUVarargs()) 44 // #define foo(x...) 45 Name << "..."; 46 47 Name << ')'; 48 } 49 50 SmallString<128> SpellingBuffer; 51 bool First = true; 52 for (const auto &T : MI.tokens()) { 53 if (!First && T.hasLeadingSpace()) 54 Value << ' '; 55 56 Value << PP.getSpelling(T, SpellingBuffer); 57 First = false; 58 } 59 } 60 61 MacroPPCallbacks::MacroPPCallbacks(CodeGenerator *Gen, Preprocessor &PP) 62 : Gen(Gen), PP(PP), Status(NoScope) {} 63 64 /* 65 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) 76 */ 77 78 llvm::DIMacroFile *MacroPPCallbacks::getCurrentScope() { 79 if (Status == MainFileScope || Status == CommandLineIncludeScope) 80 return Scopes.back(); 81 return nullptr; 82 } 83 84 SourceLocation MacroPPCallbacks::getCorrectLocation(SourceLocation Loc) { 85 if (Status == MainFileScope || EnteredCommandLineIncludeFiles) 86 return Loc; 87 88 // While parsing skipped files, location of macros is invalid. 89 // Invalid location represents line zero. 90 return SourceLocation(); 91 } 92 93 static bool isBuiltinFile(SourceManager &SM, SourceLocation Loc) { 94 StringRef Filename(SM.getPresumedLoc(Loc).getFilename()); 95 return Filename.equals("<built-in>"); 96 } 97 98 static bool isCommandLineFile(SourceManager &SM, SourceLocation Loc) { 99 StringRef Filename(SM.getPresumedLoc(Loc).getFilename()); 100 return Filename.equals("<command line>"); 101 } 102 103 void MacroPPCallbacks::updateStatusToNextScope() { 104 switch (Status) { 105 case NoScope: 106 Status = InitializedScope; 107 break; 108 case InitializedScope: 109 Status = BuiltinScope; 110 break; 111 case BuiltinScope: 112 Status = CommandLineIncludeScope; 113 break; 114 case CommandLineIncludeScope: 115 Status = MainFileScope; 116 break; 117 case MainFileScope: 118 llvm_unreachable("There is no next scope, already in the final scope"); 119 } 120 } 121 122 void MacroPPCallbacks::FileEntered(SourceLocation Loc) { 123 SourceLocation LineLoc = getCorrectLocation(LastHashLoc); 124 switch (Status) { 125 default: 126 llvm_unreachable("Do not expect to enter a file from current scope"); 127 case NoScope: 128 updateStatusToNextScope(); 129 break; 130 case InitializedScope: 131 updateStatusToNextScope(); 132 return; 133 case BuiltinScope: 134 if (isCommandLineFile(PP.getSourceManager(), Loc)) 135 return; 136 updateStatusToNextScope(); 137 LLVM_FALLTHROUGH; 138 case CommandLineIncludeScope: 139 EnteredCommandLineIncludeFiles++; 140 break; 141 case MainFileScope: 142 break; 143 } 144 145 Scopes.push_back(Gen->getCGDebugInfo()->CreateTempMacroFile(getCurrentScope(), 146 LineLoc, Loc)); 147 } 148 149 void MacroPPCallbacks::FileExited(SourceLocation Loc) { 150 switch (Status) { 151 default: 152 llvm_unreachable("Do not expect to exit a file from current scope"); 153 case BuiltinScope: 154 if (!isBuiltinFile(PP.getSourceManager(), Loc)) 155 // Skip next scope and change status to MainFileScope. 156 Status = MainFileScope; 157 return; 158 case CommandLineIncludeScope: 159 if (!EnteredCommandLineIncludeFiles) { 160 updateStatusToNextScope(); 161 return; 162 } 163 EnteredCommandLineIncludeFiles--; 164 break; 165 case MainFileScope: 166 break; 167 } 168 169 Scopes.pop_back(); 170 } 171 172 void MacroPPCallbacks::FileChanged(SourceLocation Loc, FileChangeReason Reason, 173 SrcMgr::CharacteristicKind FileType, 174 FileID PrevFID) { 175 // Only care about enter file or exit file changes. 176 if (Reason == EnterFile) 177 FileEntered(Loc); 178 else if (Reason == ExitFile) 179 FileExited(Loc); 180 } 181 182 void MacroPPCallbacks::InclusionDirective( 183 SourceLocation HashLoc, const Token &IncludeTok, StringRef FileName, 184 bool IsAngled, CharSourceRange FilenameRange, const FileEntry *File, 185 StringRef SearchPath, StringRef RelativePath, const Module *Imported) { 186 187 // Record the line location of the current included file. 188 LastHashLoc = HashLoc; 189 } 190 191 void MacroPPCallbacks::MacroDefined(const Token &MacroNameTok, 192 const MacroDirective *MD) { 193 IdentifierInfo *Id = MacroNameTok.getIdentifierInfo(); 194 SourceLocation location = getCorrectLocation(MacroNameTok.getLocation()); 195 std::string NameBuffer, ValueBuffer; 196 llvm::raw_string_ostream Name(NameBuffer); 197 llvm::raw_string_ostream Value(ValueBuffer); 198 writeMacroDefinition(*Id, *MD->getMacroInfo(), PP, Name, Value); 199 Gen->getCGDebugInfo()->CreateMacro(getCurrentScope(), 200 llvm::dwarf::DW_MACINFO_define, location, 201 Name.str(), Value.str()); 202 } 203 204 void MacroPPCallbacks::MacroUndefined(const Token &MacroNameTok, 205 const MacroDefinition &MD) { 206 IdentifierInfo *Id = MacroNameTok.getIdentifierInfo(); 207 SourceLocation location = getCorrectLocation(MacroNameTok.getLocation()); 208 Gen->getCGDebugInfo()->CreateMacro(getCurrentScope(), 209 llvm::dwarf::DW_MACINFO_undef, location, 210 Id->getName(), ""); 211 } 212