Home | History | Annotate | Line # | Download | only in Basic
      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<unsigned>::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 OS.str();
     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 OS.str();
    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