xref: /freebsd/contrib/llvm-project/clang/lib/Basic/SourceLocation.cpp (revision 7ec1ec4fdb98d87602c8501dae9b9cbd24b7d22b)
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  
25  using namespace clang;
26  
27  //===----------------------------------------------------------------------===//
28  // PrettyStackTraceLoc
29  //===----------------------------------------------------------------------===//
30  
31  void 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  
43  void 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  
69  LLVM_DUMP_METHOD std::string
70  SourceLocation::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  
77  LLVM_DUMP_METHOD void SourceLocation::dump(const SourceManager &SM) const {
78    print(llvm::errs(), SM);
79    llvm::errs() << '\n';
80  }
81  
82  LLVM_DUMP_METHOD void SourceRange::dump(const SourceManager &SM) const {
83    print(llvm::errs(), SM);
84    llvm::errs() << '\n';
85  }
86  
87  static 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  
117  void 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  
128  LLVM_DUMP_METHOD std::string
129  SourceRange::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  
140  FileID FullSourceLoc::getFileID() const {
141    assert(isValid());
142    return SrcMgr->getFileID(*this);
143  }
144  
145  FullSourceLoc FullSourceLoc::getExpansionLoc() const {
146    assert(isValid());
147    return FullSourceLoc(SrcMgr->getExpansionLoc(*this), *SrcMgr);
148  }
149  
150  FullSourceLoc FullSourceLoc::getSpellingLoc() const {
151    assert(isValid());
152    return FullSourceLoc(SrcMgr->getSpellingLoc(*this), *SrcMgr);
153  }
154  
155  FullSourceLoc FullSourceLoc::getFileLoc() const {
156    assert(isValid());
157    return FullSourceLoc(SrcMgr->getFileLoc(*this), *SrcMgr);
158  }
159  
160  PresumedLoc FullSourceLoc::getPresumedLoc(bool UseLineDirectives) const {
161    if (!isValid())
162      return PresumedLoc();
163  
164    return SrcMgr->getPresumedLoc(*this, UseLineDirectives);
165  }
166  
167  bool FullSourceLoc::isMacroArgExpansion(FullSourceLoc *StartLoc) const {
168    assert(isValid());
169    return SrcMgr->isMacroArgExpansion(*this, StartLoc);
170  }
171  
172  FullSourceLoc FullSourceLoc::getImmediateMacroCallerLoc() const {
173    assert(isValid());
174    return FullSourceLoc(SrcMgr->getImmediateMacroCallerLoc(*this), *SrcMgr);
175  }
176  
177  std::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  
187  unsigned FullSourceLoc::getFileOffset() const {
188    assert(isValid());
189    return SrcMgr->getFileOffset(*this);
190  }
191  
192  unsigned FullSourceLoc::getLineNumber(bool *Invalid) const {
193    assert(isValid());
194    return SrcMgr->getLineNumber(getFileID(), getFileOffset(), Invalid);
195  }
196  
197  unsigned FullSourceLoc::getColumnNumber(bool *Invalid) const {
198    assert(isValid());
199    return SrcMgr->getColumnNumber(getFileID(), getFileOffset(), Invalid);
200  }
201  
202  const FileEntry *FullSourceLoc::getFileEntry() const {
203    assert(isValid());
204    return SrcMgr->getFileEntryForID(getFileID());
205  }
206  
207  unsigned FullSourceLoc::getExpansionLineNumber(bool *Invalid) const {
208    assert(isValid());
209    return SrcMgr->getExpansionLineNumber(*this, Invalid);
210  }
211  
212  unsigned FullSourceLoc::getExpansionColumnNumber(bool *Invalid) const {
213    assert(isValid());
214    return SrcMgr->getExpansionColumnNumber(*this, Invalid);
215  }
216  
217  unsigned FullSourceLoc::getSpellingLineNumber(bool *Invalid) const {
218    assert(isValid());
219    return SrcMgr->getSpellingLineNumber(*this, Invalid);
220  }
221  
222  unsigned FullSourceLoc::getSpellingColumnNumber(bool *Invalid) const {
223    assert(isValid());
224    return SrcMgr->getSpellingColumnNumber(*this, Invalid);
225  }
226  
227  bool FullSourceLoc::isInSystemHeader() const {
228    assert(isValid());
229    return SrcMgr->isInSystemHeader(*this);
230  }
231  
232  bool FullSourceLoc::isBeforeInTranslationUnitThan(SourceLocation Loc) const {
233    assert(isValid());
234    return SrcMgr->isBeforeInTranslationUnit(*this, Loc);
235  }
236  
237  LLVM_DUMP_METHOD void FullSourceLoc::dump() const {
238    SourceLocation::dump(*SrcMgr);
239  }
240  
241  const char *FullSourceLoc::getCharacterData(bool *Invalid) const {
242    assert(isValid());
243    return SrcMgr->getCharacterData(*this, Invalid);
244  }
245  
246  StringRef FullSourceLoc::getBufferData(bool *Invalid) const {
247    assert(isValid());
248    return SrcMgr->getBuffer(SrcMgr->getFileID(*this), Invalid)->getBuffer();
249  }
250  
251  std::pair<FileID, unsigned> FullSourceLoc::getDecomposedLoc() const {
252    return SrcMgr->getDecomposedLoc(*this);
253  }
254