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