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.param_empty()) { 30 MacroInfo::param_iterator AI = MI.param_begin(), E = MI.param_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 // This is the expected flow of enter/exit compiler and user files: 65 // - Main File Enter 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) 75 76 llvm::DIMacroFile *MacroPPCallbacks::getCurrentScope() { 77 if (Status == MainFileScope || Status == CommandLineIncludeScope) 78 return Scopes.back(); 79 return nullptr; 80 } 81 82 SourceLocation MacroPPCallbacks::getCorrectLocation(SourceLocation Loc) { 83 if (Status == MainFileScope || EnteredCommandLineIncludeFiles) 84 return Loc; 85 86 // While parsing skipped files, location of macros is invalid. 87 // Invalid location represents line zero. 88 return SourceLocation(); 89 } 90 91 static bool isBuiltinFile(SourceManager &SM, SourceLocation Loc) { 92 StringRef Filename(SM.getPresumedLoc(Loc).getFilename()); 93 return Filename.equals("<built-in>"); 94 } 95 96 static bool isCommandLineFile(SourceManager &SM, SourceLocation Loc) { 97 StringRef Filename(SM.getPresumedLoc(Loc).getFilename()); 98 return Filename.equals("<command line>"); 99 } 100 101 void MacroPPCallbacks::updateStatusToNextScope() { 102 switch (Status) { 103 case NoScope: 104 Status = InitializedScope; 105 break; 106 case InitializedScope: 107 Status = BuiltinScope; 108 break; 109 case BuiltinScope: 110 Status = CommandLineIncludeScope; 111 break; 112 case CommandLineIncludeScope: 113 Status = MainFileScope; 114 break; 115 case MainFileScope: 116 llvm_unreachable("There is no next scope, already in the final scope"); 117 } 118 } 119 120 void MacroPPCallbacks::FileEntered(SourceLocation Loc) { 121 SourceLocation LineLoc = getCorrectLocation(LastHashLoc); 122 switch (Status) { 123 case NoScope: 124 updateStatusToNextScope(); 125 break; 126 case InitializedScope: 127 updateStatusToNextScope(); 128 return; 129 case BuiltinScope: 130 if (isCommandLineFile(PP.getSourceManager(), Loc)) 131 return; 132 updateStatusToNextScope(); 133 LLVM_FALLTHROUGH; 134 case CommandLineIncludeScope: 135 EnteredCommandLineIncludeFiles++; 136 break; 137 case MainFileScope: 138 break; 139 } 140 141 Scopes.push_back(Gen->getCGDebugInfo()->CreateTempMacroFile(getCurrentScope(), 142 LineLoc, Loc)); 143 } 144 145 void MacroPPCallbacks::FileExited(SourceLocation Loc) { 146 switch (Status) { 147 default: 148 llvm_unreachable("Do not expect to exit a file from current scope"); 149 case BuiltinScope: 150 if (!isBuiltinFile(PP.getSourceManager(), Loc)) 151 // Skip next scope and change status to MainFileScope. 152 Status = MainFileScope; 153 return; 154 case CommandLineIncludeScope: 155 if (!EnteredCommandLineIncludeFiles) { 156 updateStatusToNextScope(); 157 return; 158 } 159 EnteredCommandLineIncludeFiles--; 160 break; 161 case MainFileScope: 162 break; 163 } 164 165 Scopes.pop_back(); 166 } 167 168 void MacroPPCallbacks::FileChanged(SourceLocation Loc, FileChangeReason Reason, 169 SrcMgr::CharacteristicKind FileType, 170 FileID PrevFID) { 171 // Only care about enter file or exit file changes. 172 if (Reason == EnterFile) 173 FileEntered(Loc); 174 else if (Reason == ExitFile) 175 FileExited(Loc); 176 } 177 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) { 183 184 // Record the line location of the current included file. 185 LastHashLoc = HashLoc; 186 } 187 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()); 199 } 200 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, 208 Id->getName(), ""); 209 } 210