1 //===- SourceLocation.cpp - Compact identifier for Source Files -----------===// 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 defines accessor methods for the FullSourceLoc class. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "clang/Basic/SourceLocation.h" 15 #include "clang/Basic/LLVM.h" 16 #include "clang/Basic/PrettyStackTrace.h" 17 #include "clang/Basic/SourceManager.h" 18 #include "llvm/ADT/StringRef.h" 19 #include "llvm/Support/Compiler.h" 20 #include "llvm/Support/MemoryBuffer.h" 21 #include "llvm/Support/raw_ostream.h" 22 #include <cassert> 23 #include <string> 24 #include <utility> 25 26 using namespace clang; 27 28 //===----------------------------------------------------------------------===// 29 // PrettyStackTraceLoc 30 //===----------------------------------------------------------------------===// 31 32 void PrettyStackTraceLoc::print(raw_ostream &OS) const { 33 if (Loc.isValid()) { 34 Loc.print(OS, SM); 35 OS << ": "; 36 } 37 OS << Message << '\n'; 38 } 39 40 //===----------------------------------------------------------------------===// 41 // SourceLocation 42 //===----------------------------------------------------------------------===// 43 44 void SourceLocation::print(raw_ostream &OS, const SourceManager &SM)const{ 45 if (!isValid()) { 46 OS << "<invalid loc>"; 47 return; 48 } 49 50 if (isFileID()) { 51 PresumedLoc PLoc = SM.getPresumedLoc(*this); 52 53 if (PLoc.isInvalid()) { 54 OS << "<invalid>"; 55 return; 56 } 57 // The macro expansion and spelling pos is identical for file locs. 58 OS << PLoc.getFilename() << ':' << PLoc.getLine() 59 << ':' << PLoc.getColumn(); 60 return; 61 } 62 63 SM.getExpansionLoc(*this).print(OS, SM); 64 65 OS << " <Spelling="; 66 SM.getSpellingLoc(*this).print(OS, SM); 67 OS << '>'; 68 } 69 70 LLVM_DUMP_METHOD std::string 71 SourceLocation::printToString(const SourceManager &SM) const { 72 std::string S; 73 llvm::raw_string_ostream OS(S); 74 print(OS, SM); 75 return OS.str(); 76 } 77 78 LLVM_DUMP_METHOD void SourceLocation::dump(const SourceManager &SM) const { 79 print(llvm::errs(), SM); 80 llvm::errs() << '\n'; 81 } 82 83 LLVM_DUMP_METHOD void SourceRange::dump(const SourceManager &SM) const { 84 print(llvm::errs(), SM); 85 llvm::errs() << '\n'; 86 } 87 88 static PresumedLoc PrintDifference(raw_ostream &OS, const SourceManager &SM, 89 SourceLocation Loc, PresumedLoc Previous) { 90 if (Loc.isFileID()) { 91 92 PresumedLoc PLoc = SM.getPresumedLoc(Loc); 93 94 if (PLoc.isInvalid()) { 95 OS << "<invalid sloc>"; 96 return Previous; 97 } 98 99 if (Previous.isInvalid() || 100 strcmp(PLoc.getFilename(), Previous.getFilename()) != 0) { 101 OS << PLoc.getFilename() << ':' << PLoc.getLine() << ':' 102 << PLoc.getColumn(); 103 } else if (Previous.isInvalid() || PLoc.getLine() != Previous.getLine()) { 104 OS << "line" << ':' << PLoc.getLine() << ':' << PLoc.getColumn(); 105 } else { 106 OS << "col" << ':' << PLoc.getColumn(); 107 } 108 return PLoc; 109 } 110 auto PrintedLoc = PrintDifference(OS, SM, SM.getExpansionLoc(Loc), Previous); 111 112 OS << " <Spelling="; 113 PrintedLoc = PrintDifference(OS, SM, SM.getSpellingLoc(Loc), PrintedLoc); 114 OS << '>'; 115 return PrintedLoc; 116 } 117 118 void SourceRange::print(raw_ostream &OS, const SourceManager &SM) const { 119 120 OS << '<'; 121 auto PrintedLoc = PrintDifference(OS, SM, B, {}); 122 if (B != E) { 123 OS << ", "; 124 PrintDifference(OS, SM, E, PrintedLoc); 125 } 126 OS << '>'; 127 } 128 129 LLVM_DUMP_METHOD std::string 130 SourceRange::printToString(const SourceManager &SM) const { 131 std::string S; 132 llvm::raw_string_ostream OS(S); 133 print(OS, SM); 134 return OS.str(); 135 } 136 137 //===----------------------------------------------------------------------===// 138 // FullSourceLoc 139 //===----------------------------------------------------------------------===// 140 141 FileID FullSourceLoc::getFileID() const { 142 assert(isValid()); 143 return SrcMgr->getFileID(*this); 144 } 145 146 FullSourceLoc FullSourceLoc::getExpansionLoc() const { 147 assert(isValid()); 148 return FullSourceLoc(SrcMgr->getExpansionLoc(*this), *SrcMgr); 149 } 150 151 FullSourceLoc FullSourceLoc::getSpellingLoc() const { 152 assert(isValid()); 153 return FullSourceLoc(SrcMgr->getSpellingLoc(*this), *SrcMgr); 154 } 155 156 FullSourceLoc FullSourceLoc::getFileLoc() const { 157 assert(isValid()); 158 return FullSourceLoc(SrcMgr->getFileLoc(*this), *SrcMgr); 159 } 160 161 PresumedLoc FullSourceLoc::getPresumedLoc(bool UseLineDirectives) const { 162 if (!isValid()) 163 return PresumedLoc(); 164 165 return SrcMgr->getPresumedLoc(*this, UseLineDirectives); 166 } 167 168 bool FullSourceLoc::isMacroArgExpansion(FullSourceLoc *StartLoc) const { 169 assert(isValid()); 170 return SrcMgr->isMacroArgExpansion(*this, StartLoc); 171 } 172 173 FullSourceLoc FullSourceLoc::getImmediateMacroCallerLoc() const { 174 assert(isValid()); 175 return FullSourceLoc(SrcMgr->getImmediateMacroCallerLoc(*this), *SrcMgr); 176 } 177 178 std::pair<FullSourceLoc, StringRef> FullSourceLoc::getModuleImportLoc() const { 179 if (!isValid()) 180 return std::make_pair(FullSourceLoc(), StringRef()); 181 182 std::pair<SourceLocation, StringRef> ImportLoc = 183 SrcMgr->getModuleImportLoc(*this); 184 return std::make_pair(FullSourceLoc(ImportLoc.first, *SrcMgr), 185 ImportLoc.second); 186 } 187 188 unsigned FullSourceLoc::getFileOffset() const { 189 assert(isValid()); 190 return SrcMgr->getFileOffset(*this); 191 } 192 193 unsigned FullSourceLoc::getLineNumber(bool *Invalid) const { 194 assert(isValid()); 195 return SrcMgr->getLineNumber(getFileID(), getFileOffset(), Invalid); 196 } 197 198 unsigned FullSourceLoc::getColumnNumber(bool *Invalid) const { 199 assert(isValid()); 200 return SrcMgr->getColumnNumber(getFileID(), getFileOffset(), Invalid); 201 } 202 203 const FileEntry *FullSourceLoc::getFileEntry() const { 204 assert(isValid()); 205 return SrcMgr->getFileEntryForID(getFileID()); 206 } 207 208 unsigned FullSourceLoc::getExpansionLineNumber(bool *Invalid) const { 209 assert(isValid()); 210 return SrcMgr->getExpansionLineNumber(*this, Invalid); 211 } 212 213 unsigned FullSourceLoc::getExpansionColumnNumber(bool *Invalid) const { 214 assert(isValid()); 215 return SrcMgr->getExpansionColumnNumber(*this, Invalid); 216 } 217 218 unsigned FullSourceLoc::getSpellingLineNumber(bool *Invalid) const { 219 assert(isValid()); 220 return SrcMgr->getSpellingLineNumber(*this, Invalid); 221 } 222 223 unsigned FullSourceLoc::getSpellingColumnNumber(bool *Invalid) const { 224 assert(isValid()); 225 return SrcMgr->getSpellingColumnNumber(*this, Invalid); 226 } 227 228 bool FullSourceLoc::isInSystemHeader() const { 229 assert(isValid()); 230 return SrcMgr->isInSystemHeader(*this); 231 } 232 233 bool FullSourceLoc::isBeforeInTranslationUnitThan(SourceLocation Loc) const { 234 assert(isValid()); 235 return SrcMgr->isBeforeInTranslationUnit(*this, Loc); 236 } 237 238 LLVM_DUMP_METHOD void FullSourceLoc::dump() const { 239 SourceLocation::dump(*SrcMgr); 240 } 241 242 const char *FullSourceLoc::getCharacterData(bool *Invalid) const { 243 assert(isValid()); 244 return SrcMgr->getCharacterData(*this, Invalid); 245 } 246 247 StringRef FullSourceLoc::getBufferData(bool *Invalid) const { 248 assert(isValid()); 249 return SrcMgr->getBuffer(SrcMgr->getFileID(*this), Invalid)->getBuffer(); 250 } 251 252 std::pair<FileID, unsigned> FullSourceLoc::getDecomposedLoc() const { 253 return SrcMgr->getDecomposedLoc(*this); 254 } 255