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