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