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