xref: /freebsd/contrib/llvm-project/clang/lib/Basic/SourceLocation.cpp (revision 5f757f3ff9144b609b3c433dfd370cc6bdc191ad)
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