10b57cec5SDimitry Andric //===- SourceLocation.cpp - Compact identifier for Source Files -----------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This file defines accessor methods for the FullSourceLoc class. 100b57cec5SDimitry Andric // 110b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 120b57cec5SDimitry Andric 130b57cec5SDimitry Andric #include "clang/Basic/SourceLocation.h" 140b57cec5SDimitry Andric #include "clang/Basic/LLVM.h" 150b57cec5SDimitry Andric #include "clang/Basic/PrettyStackTrace.h" 160b57cec5SDimitry Andric #include "clang/Basic/SourceManager.h" 17e8d8bef9SDimitry Andric #include "llvm/ADT/DenseMapInfo.h" 18e8d8bef9SDimitry Andric #include "llvm/ADT/FoldingSet.h" 190b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h" 200b57cec5SDimitry Andric #include "llvm/Support/Compiler.h" 210b57cec5SDimitry Andric #include "llvm/Support/MemoryBuffer.h" 220b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 230b57cec5SDimitry Andric #include <cassert> 240b57cec5SDimitry Andric #include <string> 250b57cec5SDimitry Andric #include <utility> 260b57cec5SDimitry Andric 270b57cec5SDimitry Andric using namespace clang; 280b57cec5SDimitry Andric 290b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 300b57cec5SDimitry Andric // PrettyStackTraceLoc 310b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 320b57cec5SDimitry Andric 330b57cec5SDimitry Andric void PrettyStackTraceLoc::print(raw_ostream &OS) const { 340b57cec5SDimitry Andric if (Loc.isValid()) { 350b57cec5SDimitry Andric Loc.print(OS, SM); 360b57cec5SDimitry Andric OS << ": "; 370b57cec5SDimitry Andric } 380b57cec5SDimitry Andric OS << Message << '\n'; 390b57cec5SDimitry Andric } 400b57cec5SDimitry Andric 410b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 420b57cec5SDimitry Andric // SourceLocation 430b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 440b57cec5SDimitry Andric 45bdd1243dSDimitry Andric static_assert(std::is_trivially_destructible_v<SourceLocation>, 46e8d8bef9SDimitry Andric "SourceLocation must be trivially destructible because it is " 47e8d8bef9SDimitry Andric "used in unions"); 48e8d8bef9SDimitry Andric 49bdd1243dSDimitry Andric static_assert(std::is_trivially_destructible_v<SourceRange>, 50e8d8bef9SDimitry Andric "SourceRange must be trivially destructible because it is " 51e8d8bef9SDimitry Andric "used in unions"); 52e8d8bef9SDimitry Andric 53e8d8bef9SDimitry Andric unsigned SourceLocation::getHashValue() const { 54fe6060f1SDimitry Andric return llvm::DenseMapInfo<UIntTy>::getHashValue(ID); 55e8d8bef9SDimitry Andric } 56e8d8bef9SDimitry Andric 57e8d8bef9SDimitry Andric void llvm::FoldingSetTrait<SourceLocation>::Profile( 58e8d8bef9SDimitry Andric const SourceLocation &X, llvm::FoldingSetNodeID &ID) { 59e8d8bef9SDimitry Andric ID.AddInteger(X.ID); 60e8d8bef9SDimitry Andric } 61e8d8bef9SDimitry Andric 620b57cec5SDimitry Andric void SourceLocation::print(raw_ostream &OS, const SourceManager &SM)const{ 630b57cec5SDimitry Andric if (!isValid()) { 640b57cec5SDimitry Andric OS << "<invalid loc>"; 650b57cec5SDimitry Andric return; 660b57cec5SDimitry Andric } 670b57cec5SDimitry Andric 680b57cec5SDimitry Andric if (isFileID()) { 690b57cec5SDimitry Andric PresumedLoc PLoc = SM.getPresumedLoc(*this); 700b57cec5SDimitry Andric 710b57cec5SDimitry Andric if (PLoc.isInvalid()) { 720b57cec5SDimitry Andric OS << "<invalid>"; 730b57cec5SDimitry Andric return; 740b57cec5SDimitry Andric } 750b57cec5SDimitry Andric // The macro expansion and spelling pos is identical for file locs. 760b57cec5SDimitry Andric OS << PLoc.getFilename() << ':' << PLoc.getLine() 770b57cec5SDimitry Andric << ':' << PLoc.getColumn(); 780b57cec5SDimitry Andric return; 790b57cec5SDimitry Andric } 800b57cec5SDimitry Andric 810b57cec5SDimitry Andric SM.getExpansionLoc(*this).print(OS, SM); 820b57cec5SDimitry Andric 830b57cec5SDimitry Andric OS << " <Spelling="; 840b57cec5SDimitry Andric SM.getSpellingLoc(*this).print(OS, SM); 850b57cec5SDimitry Andric OS << '>'; 860b57cec5SDimitry Andric } 870b57cec5SDimitry Andric 880b57cec5SDimitry Andric LLVM_DUMP_METHOD std::string 890b57cec5SDimitry Andric SourceLocation::printToString(const SourceManager &SM) const { 900b57cec5SDimitry Andric std::string S; 910b57cec5SDimitry Andric llvm::raw_string_ostream OS(S); 920b57cec5SDimitry Andric print(OS, SM); 930eae32dcSDimitry Andric return S; 940b57cec5SDimitry Andric } 950b57cec5SDimitry Andric 960b57cec5SDimitry Andric LLVM_DUMP_METHOD void SourceLocation::dump(const SourceManager &SM) const { 970b57cec5SDimitry Andric print(llvm::errs(), SM); 980b57cec5SDimitry Andric llvm::errs() << '\n'; 990b57cec5SDimitry Andric } 1000b57cec5SDimitry Andric 1010b57cec5SDimitry Andric LLVM_DUMP_METHOD void SourceRange::dump(const SourceManager &SM) const { 1020b57cec5SDimitry Andric print(llvm::errs(), SM); 1030b57cec5SDimitry Andric llvm::errs() << '\n'; 1040b57cec5SDimitry Andric } 1050b57cec5SDimitry Andric 1060b57cec5SDimitry Andric static PresumedLoc PrintDifference(raw_ostream &OS, const SourceManager &SM, 1070b57cec5SDimitry Andric SourceLocation Loc, PresumedLoc Previous) { 1080b57cec5SDimitry Andric if (Loc.isFileID()) { 1090b57cec5SDimitry Andric 1100b57cec5SDimitry Andric PresumedLoc PLoc = SM.getPresumedLoc(Loc); 1110b57cec5SDimitry Andric 1120b57cec5SDimitry Andric if (PLoc.isInvalid()) { 1130b57cec5SDimitry Andric OS << "<invalid sloc>"; 1140b57cec5SDimitry Andric return Previous; 1150b57cec5SDimitry Andric } 1160b57cec5SDimitry Andric 1170b57cec5SDimitry Andric if (Previous.isInvalid() || 1180b57cec5SDimitry Andric strcmp(PLoc.getFilename(), Previous.getFilename()) != 0) { 1190b57cec5SDimitry Andric OS << PLoc.getFilename() << ':' << PLoc.getLine() << ':' 1200b57cec5SDimitry Andric << PLoc.getColumn(); 1210b57cec5SDimitry Andric } else if (Previous.isInvalid() || PLoc.getLine() != Previous.getLine()) { 1220b57cec5SDimitry Andric OS << "line" << ':' << PLoc.getLine() << ':' << PLoc.getColumn(); 1230b57cec5SDimitry Andric } else { 1240b57cec5SDimitry Andric OS << "col" << ':' << PLoc.getColumn(); 1250b57cec5SDimitry Andric } 1260b57cec5SDimitry Andric return PLoc; 1270b57cec5SDimitry Andric } 1280b57cec5SDimitry Andric auto PrintedLoc = PrintDifference(OS, SM, SM.getExpansionLoc(Loc), Previous); 1290b57cec5SDimitry Andric 1300b57cec5SDimitry Andric OS << " <Spelling="; 1310b57cec5SDimitry Andric PrintedLoc = PrintDifference(OS, SM, SM.getSpellingLoc(Loc), PrintedLoc); 1320b57cec5SDimitry Andric OS << '>'; 1330b57cec5SDimitry Andric return PrintedLoc; 1340b57cec5SDimitry Andric } 1350b57cec5SDimitry Andric 1360b57cec5SDimitry Andric void SourceRange::print(raw_ostream &OS, const SourceManager &SM) const { 1370b57cec5SDimitry Andric 1380b57cec5SDimitry Andric OS << '<'; 1390b57cec5SDimitry Andric auto PrintedLoc = PrintDifference(OS, SM, B, {}); 1400b57cec5SDimitry Andric if (B != E) { 1410b57cec5SDimitry Andric OS << ", "; 1420b57cec5SDimitry Andric PrintDifference(OS, SM, E, PrintedLoc); 1430b57cec5SDimitry Andric } 1440b57cec5SDimitry Andric OS << '>'; 1450b57cec5SDimitry Andric } 1460b57cec5SDimitry Andric 1470b57cec5SDimitry Andric LLVM_DUMP_METHOD std::string 1480b57cec5SDimitry Andric SourceRange::printToString(const SourceManager &SM) const { 1490b57cec5SDimitry Andric std::string S; 1500b57cec5SDimitry Andric llvm::raw_string_ostream OS(S); 1510b57cec5SDimitry Andric print(OS, SM); 1520eae32dcSDimitry Andric return S; 1530b57cec5SDimitry Andric } 1540b57cec5SDimitry Andric 1550b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 1560b57cec5SDimitry Andric // FullSourceLoc 1570b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 1580b57cec5SDimitry Andric 1590b57cec5SDimitry Andric FileID FullSourceLoc::getFileID() const { 1600b57cec5SDimitry Andric assert(isValid()); 1610b57cec5SDimitry Andric return SrcMgr->getFileID(*this); 1620b57cec5SDimitry Andric } 1630b57cec5SDimitry Andric 1640b57cec5SDimitry Andric FullSourceLoc FullSourceLoc::getExpansionLoc() const { 1650b57cec5SDimitry Andric assert(isValid()); 1660b57cec5SDimitry Andric return FullSourceLoc(SrcMgr->getExpansionLoc(*this), *SrcMgr); 1670b57cec5SDimitry Andric } 1680b57cec5SDimitry Andric 169bdd1243dSDimitry Andric std::pair<FileID, unsigned> FullSourceLoc::getDecomposedExpansionLoc() const { 170bdd1243dSDimitry Andric return SrcMgr->getDecomposedExpansionLoc(*this); 171bdd1243dSDimitry Andric } 172bdd1243dSDimitry Andric 1730b57cec5SDimitry Andric FullSourceLoc FullSourceLoc::getSpellingLoc() const { 1740b57cec5SDimitry Andric assert(isValid()); 1750b57cec5SDimitry Andric return FullSourceLoc(SrcMgr->getSpellingLoc(*this), *SrcMgr); 1760b57cec5SDimitry Andric } 1770b57cec5SDimitry Andric 1780b57cec5SDimitry Andric FullSourceLoc FullSourceLoc::getFileLoc() const { 1790b57cec5SDimitry Andric assert(isValid()); 1800b57cec5SDimitry Andric return FullSourceLoc(SrcMgr->getFileLoc(*this), *SrcMgr); 1810b57cec5SDimitry Andric } 1820b57cec5SDimitry Andric 1830b57cec5SDimitry Andric PresumedLoc FullSourceLoc::getPresumedLoc(bool UseLineDirectives) const { 1840b57cec5SDimitry Andric if (!isValid()) 1850b57cec5SDimitry Andric return PresumedLoc(); 1860b57cec5SDimitry Andric 1870b57cec5SDimitry Andric return SrcMgr->getPresumedLoc(*this, UseLineDirectives); 1880b57cec5SDimitry Andric } 1890b57cec5SDimitry Andric 1900b57cec5SDimitry Andric bool FullSourceLoc::isMacroArgExpansion(FullSourceLoc *StartLoc) const { 1910b57cec5SDimitry Andric assert(isValid()); 1920b57cec5SDimitry Andric return SrcMgr->isMacroArgExpansion(*this, StartLoc); 1930b57cec5SDimitry Andric } 1940b57cec5SDimitry Andric 1950b57cec5SDimitry Andric FullSourceLoc FullSourceLoc::getImmediateMacroCallerLoc() const { 1960b57cec5SDimitry Andric assert(isValid()); 1970b57cec5SDimitry Andric return FullSourceLoc(SrcMgr->getImmediateMacroCallerLoc(*this), *SrcMgr); 1980b57cec5SDimitry Andric } 1990b57cec5SDimitry Andric 2000b57cec5SDimitry Andric std::pair<FullSourceLoc, StringRef> FullSourceLoc::getModuleImportLoc() const { 2010b57cec5SDimitry Andric if (!isValid()) 2020b57cec5SDimitry Andric return std::make_pair(FullSourceLoc(), StringRef()); 2030b57cec5SDimitry Andric 2040b57cec5SDimitry Andric std::pair<SourceLocation, StringRef> ImportLoc = 2050b57cec5SDimitry Andric SrcMgr->getModuleImportLoc(*this); 2060b57cec5SDimitry Andric return std::make_pair(FullSourceLoc(ImportLoc.first, *SrcMgr), 2070b57cec5SDimitry Andric ImportLoc.second); 2080b57cec5SDimitry Andric } 2090b57cec5SDimitry Andric 2100b57cec5SDimitry Andric unsigned FullSourceLoc::getFileOffset() const { 2110b57cec5SDimitry Andric assert(isValid()); 2120b57cec5SDimitry Andric return SrcMgr->getFileOffset(*this); 2130b57cec5SDimitry Andric } 2140b57cec5SDimitry Andric 2150b57cec5SDimitry Andric unsigned FullSourceLoc::getLineNumber(bool *Invalid) const { 2160b57cec5SDimitry Andric assert(isValid()); 2170b57cec5SDimitry Andric return SrcMgr->getLineNumber(getFileID(), getFileOffset(), Invalid); 2180b57cec5SDimitry Andric } 2190b57cec5SDimitry Andric 2200b57cec5SDimitry Andric unsigned FullSourceLoc::getColumnNumber(bool *Invalid) const { 2210b57cec5SDimitry Andric assert(isValid()); 2220b57cec5SDimitry Andric return SrcMgr->getColumnNumber(getFileID(), getFileOffset(), Invalid); 2230b57cec5SDimitry Andric } 2240b57cec5SDimitry Andric 2250b57cec5SDimitry Andric const FileEntry *FullSourceLoc::getFileEntry() const { 2260b57cec5SDimitry Andric assert(isValid()); 2270b57cec5SDimitry Andric return SrcMgr->getFileEntryForID(getFileID()); 2280b57cec5SDimitry Andric } 2290b57cec5SDimitry Andric 230*5f757f3fSDimitry Andric OptionalFileEntryRef FullSourceLoc::getFileEntryRef() const { 231*5f757f3fSDimitry Andric assert(isValid()); 232*5f757f3fSDimitry Andric return SrcMgr->getFileEntryRefForID(getFileID()); 233*5f757f3fSDimitry Andric } 234*5f757f3fSDimitry Andric 2350b57cec5SDimitry Andric unsigned FullSourceLoc::getExpansionLineNumber(bool *Invalid) const { 2360b57cec5SDimitry Andric assert(isValid()); 2370b57cec5SDimitry Andric return SrcMgr->getExpansionLineNumber(*this, Invalid); 2380b57cec5SDimitry Andric } 2390b57cec5SDimitry Andric 2400b57cec5SDimitry Andric unsigned FullSourceLoc::getExpansionColumnNumber(bool *Invalid) const { 2410b57cec5SDimitry Andric assert(isValid()); 2420b57cec5SDimitry Andric return SrcMgr->getExpansionColumnNumber(*this, Invalid); 2430b57cec5SDimitry Andric } 2440b57cec5SDimitry Andric 2450b57cec5SDimitry Andric unsigned FullSourceLoc::getSpellingLineNumber(bool *Invalid) const { 2460b57cec5SDimitry Andric assert(isValid()); 2470b57cec5SDimitry Andric return SrcMgr->getSpellingLineNumber(*this, Invalid); 2480b57cec5SDimitry Andric } 2490b57cec5SDimitry Andric 2500b57cec5SDimitry Andric unsigned FullSourceLoc::getSpellingColumnNumber(bool *Invalid) const { 2510b57cec5SDimitry Andric assert(isValid()); 2520b57cec5SDimitry Andric return SrcMgr->getSpellingColumnNumber(*this, Invalid); 2530b57cec5SDimitry Andric } 2540b57cec5SDimitry Andric 2550b57cec5SDimitry Andric bool FullSourceLoc::isInSystemHeader() const { 2560b57cec5SDimitry Andric assert(isValid()); 2570b57cec5SDimitry Andric return SrcMgr->isInSystemHeader(*this); 2580b57cec5SDimitry Andric } 2590b57cec5SDimitry Andric 2600b57cec5SDimitry Andric bool FullSourceLoc::isBeforeInTranslationUnitThan(SourceLocation Loc) const { 2610b57cec5SDimitry Andric assert(isValid()); 2620b57cec5SDimitry Andric return SrcMgr->isBeforeInTranslationUnit(*this, Loc); 2630b57cec5SDimitry Andric } 2640b57cec5SDimitry Andric 2650b57cec5SDimitry Andric LLVM_DUMP_METHOD void FullSourceLoc::dump() const { 2660b57cec5SDimitry Andric SourceLocation::dump(*SrcMgr); 2670b57cec5SDimitry Andric } 2680b57cec5SDimitry Andric 2690b57cec5SDimitry Andric const char *FullSourceLoc::getCharacterData(bool *Invalid) const { 2700b57cec5SDimitry Andric assert(isValid()); 2710b57cec5SDimitry Andric return SrcMgr->getCharacterData(*this, Invalid); 2720b57cec5SDimitry Andric } 2730b57cec5SDimitry Andric 2740b57cec5SDimitry Andric StringRef FullSourceLoc::getBufferData(bool *Invalid) const { 2750b57cec5SDimitry Andric assert(isValid()); 276e8d8bef9SDimitry Andric return SrcMgr->getBufferData(SrcMgr->getFileID(*this), Invalid); 2770b57cec5SDimitry Andric } 2780b57cec5SDimitry Andric 2790b57cec5SDimitry Andric std::pair<FileID, unsigned> FullSourceLoc::getDecomposedLoc() const { 2800b57cec5SDimitry Andric return SrcMgr->getDecomposedLoc(*this); 2810b57cec5SDimitry Andric } 282