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