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 27using namespace clang; 28 29//===----------------------------------------------------------------------===// 30// PrettyStackTraceLoc 31//===----------------------------------------------------------------------===// 32 33void 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 45static_assert(std::is_trivially_destructible_v<SourceLocation>, 46 "SourceLocation must be trivially destructible because it is " 47 "used in unions"); 48 49static_assert(std::is_trivially_destructible_v<SourceRange>, 50 "SourceRange must be trivially destructible because it is " 51 "used in unions"); 52 53unsigned SourceLocation::getHashValue() const { 54 return llvm::DenseMapInfo<UIntTy>::getHashValue(ID); 55} 56 57void llvm::FoldingSetTrait<SourceLocation>::Profile( 58 const SourceLocation &X, llvm::FoldingSetNodeID &ID) { 59 ID.AddInteger(X.ID); 60} 61 62void 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 88LLVM_DUMP_METHOD std::string 89SourceLocation::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 96LLVM_DUMP_METHOD void SourceLocation::dump(const SourceManager &SM) const { 97 print(llvm::errs(), SM); 98 llvm::errs() << '\n'; 99} 100 101LLVM_DUMP_METHOD void SourceRange::dump(const SourceManager &SM) const { 102 print(llvm::errs(), SM); 103 llvm::errs() << '\n'; 104} 105 106static 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 136void 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 147LLVM_DUMP_METHOD std::string 148SourceRange::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 159FileID FullSourceLoc::getFileID() const { 160 assert(isValid()); 161 return SrcMgr->getFileID(*this); 162} 163 164FullSourceLoc FullSourceLoc::getExpansionLoc() const { 165 assert(isValid()); 166 return FullSourceLoc(SrcMgr->getExpansionLoc(*this), *SrcMgr); 167} 168 169std::pair<FileID, unsigned> FullSourceLoc::getDecomposedExpansionLoc() const { 170 return SrcMgr->getDecomposedExpansionLoc(*this); 171} 172 173FullSourceLoc FullSourceLoc::getSpellingLoc() const { 174 assert(isValid()); 175 return FullSourceLoc(SrcMgr->getSpellingLoc(*this), *SrcMgr); 176} 177 178FullSourceLoc FullSourceLoc::getFileLoc() const { 179 assert(isValid()); 180 return FullSourceLoc(SrcMgr->getFileLoc(*this), *SrcMgr); 181} 182 183PresumedLoc FullSourceLoc::getPresumedLoc(bool UseLineDirectives) const { 184 if (!isValid()) 185 return PresumedLoc(); 186 187 return SrcMgr->getPresumedLoc(*this, UseLineDirectives); 188} 189 190bool FullSourceLoc::isMacroArgExpansion(FullSourceLoc *StartLoc) const { 191 assert(isValid()); 192 return SrcMgr->isMacroArgExpansion(*this, StartLoc); 193} 194 195FullSourceLoc FullSourceLoc::getImmediateMacroCallerLoc() const { 196 assert(isValid()); 197 return FullSourceLoc(SrcMgr->getImmediateMacroCallerLoc(*this), *SrcMgr); 198} 199 200std::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 210unsigned FullSourceLoc::getFileOffset() const { 211 assert(isValid()); 212 return SrcMgr->getFileOffset(*this); 213} 214 215unsigned FullSourceLoc::getLineNumber(bool *Invalid) const { 216 assert(isValid()); 217 return SrcMgr->getLineNumber(getFileID(), getFileOffset(), Invalid); 218} 219 220unsigned FullSourceLoc::getColumnNumber(bool *Invalid) const { 221 assert(isValid()); 222 return SrcMgr->getColumnNumber(getFileID(), getFileOffset(), Invalid); 223} 224 225const FileEntry *FullSourceLoc::getFileEntry() const { 226 assert(isValid()); 227 return SrcMgr->getFileEntryForID(getFileID()); 228} 229 230unsigned FullSourceLoc::getExpansionLineNumber(bool *Invalid) const { 231 assert(isValid()); 232 return SrcMgr->getExpansionLineNumber(*this, Invalid); 233} 234 235unsigned FullSourceLoc::getExpansionColumnNumber(bool *Invalid) const { 236 assert(isValid()); 237 return SrcMgr->getExpansionColumnNumber(*this, Invalid); 238} 239 240unsigned FullSourceLoc::getSpellingLineNumber(bool *Invalid) const { 241 assert(isValid()); 242 return SrcMgr->getSpellingLineNumber(*this, Invalid); 243} 244 245unsigned FullSourceLoc::getSpellingColumnNumber(bool *Invalid) const { 246 assert(isValid()); 247 return SrcMgr->getSpellingColumnNumber(*this, Invalid); 248} 249 250bool FullSourceLoc::isInSystemHeader() const { 251 assert(isValid()); 252 return SrcMgr->isInSystemHeader(*this); 253} 254 255bool FullSourceLoc::isBeforeInTranslationUnitThan(SourceLocation Loc) const { 256 assert(isValid()); 257 return SrcMgr->isBeforeInTranslationUnit(*this, Loc); 258} 259 260LLVM_DUMP_METHOD void FullSourceLoc::dump() const { 261 SourceLocation::dump(*SrcMgr); 262} 263 264const char *FullSourceLoc::getCharacterData(bool *Invalid) const { 265 assert(isValid()); 266 return SrcMgr->getCharacterData(*this, Invalid); 267} 268 269StringRef FullSourceLoc::getBufferData(bool *Invalid) const { 270 assert(isValid()); 271 return SrcMgr->getBufferData(SrcMgr->getFileID(*this), Invalid); 272} 273 274std::pair<FileID, unsigned> FullSourceLoc::getDecomposedLoc() const { 275 return SrcMgr->getDecomposedLoc(*this); 276} 277