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<SourceLocation>::value, 46 "SourceLocation must be trivially destructible because it is " 47 "used in unions"); 48 49 static_assert(std::is_trivially_destructible<SourceRange>::value, 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 FullSourceLoc FullSourceLoc::getSpellingLoc() const { 170 assert(isValid()); 171 return FullSourceLoc(SrcMgr->getSpellingLoc(*this), *SrcMgr); 172 } 173 174 FullSourceLoc FullSourceLoc::getFileLoc() const { 175 assert(isValid()); 176 return FullSourceLoc(SrcMgr->getFileLoc(*this), *SrcMgr); 177 } 178 179 PresumedLoc FullSourceLoc::getPresumedLoc(bool UseLineDirectives) const { 180 if (!isValid()) 181 return PresumedLoc(); 182 183 return SrcMgr->getPresumedLoc(*this, UseLineDirectives); 184 } 185 186 bool FullSourceLoc::isMacroArgExpansion(FullSourceLoc *StartLoc) const { 187 assert(isValid()); 188 return SrcMgr->isMacroArgExpansion(*this, StartLoc); 189 } 190 191 FullSourceLoc FullSourceLoc::getImmediateMacroCallerLoc() const { 192 assert(isValid()); 193 return FullSourceLoc(SrcMgr->getImmediateMacroCallerLoc(*this), *SrcMgr); 194 } 195 196 std::pair<FullSourceLoc, StringRef> FullSourceLoc::getModuleImportLoc() const { 197 if (!isValid()) 198 return std::make_pair(FullSourceLoc(), StringRef()); 199 200 std::pair<SourceLocation, StringRef> ImportLoc = 201 SrcMgr->getModuleImportLoc(*this); 202 return std::make_pair(FullSourceLoc(ImportLoc.first, *SrcMgr), 203 ImportLoc.second); 204 } 205 206 unsigned FullSourceLoc::getFileOffset() const { 207 assert(isValid()); 208 return SrcMgr->getFileOffset(*this); 209 } 210 211 unsigned FullSourceLoc::getLineNumber(bool *Invalid) const { 212 assert(isValid()); 213 return SrcMgr->getLineNumber(getFileID(), getFileOffset(), Invalid); 214 } 215 216 unsigned FullSourceLoc::getColumnNumber(bool *Invalid) const { 217 assert(isValid()); 218 return SrcMgr->getColumnNumber(getFileID(), getFileOffset(), Invalid); 219 } 220 221 const FileEntry *FullSourceLoc::getFileEntry() const { 222 assert(isValid()); 223 return SrcMgr->getFileEntryForID(getFileID()); 224 } 225 226 unsigned FullSourceLoc::getExpansionLineNumber(bool *Invalid) const { 227 assert(isValid()); 228 return SrcMgr->getExpansionLineNumber(*this, Invalid); 229 } 230 231 unsigned FullSourceLoc::getExpansionColumnNumber(bool *Invalid) const { 232 assert(isValid()); 233 return SrcMgr->getExpansionColumnNumber(*this, Invalid); 234 } 235 236 unsigned FullSourceLoc::getSpellingLineNumber(bool *Invalid) const { 237 assert(isValid()); 238 return SrcMgr->getSpellingLineNumber(*this, Invalid); 239 } 240 241 unsigned FullSourceLoc::getSpellingColumnNumber(bool *Invalid) const { 242 assert(isValid()); 243 return SrcMgr->getSpellingColumnNumber(*this, Invalid); 244 } 245 246 bool FullSourceLoc::isInSystemHeader() const { 247 assert(isValid()); 248 return SrcMgr->isInSystemHeader(*this); 249 } 250 251 bool FullSourceLoc::isBeforeInTranslationUnitThan(SourceLocation Loc) const { 252 assert(isValid()); 253 return SrcMgr->isBeforeInTranslationUnit(*this, Loc); 254 } 255 256 LLVM_DUMP_METHOD void FullSourceLoc::dump() const { 257 SourceLocation::dump(*SrcMgr); 258 } 259 260 const char *FullSourceLoc::getCharacterData(bool *Invalid) const { 261 assert(isValid()); 262 return SrcMgr->getCharacterData(*this, Invalid); 263 } 264 265 StringRef FullSourceLoc::getBufferData(bool *Invalid) const { 266 assert(isValid()); 267 return SrcMgr->getBufferData(SrcMgr->getFileID(*this), Invalid); 268 } 269 270 std::pair<FileID, unsigned> FullSourceLoc::getDecomposedLoc() const { 271 return SrcMgr->getDecomposedLoc(*this); 272 } 273