xref: /freebsd/contrib/llvm-project/clang/lib/Basic/SourceLocation.cpp (revision 21817992b3314c908ab50f0bb88d2ee750b9c4ac)
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_v<SourceLocation>,
46                "SourceLocation must be trivially destructible because it is "
47                "used in unions");
48  
49  static_assert(std::is_trivially_destructible_v<SourceRange>,
50                "SourceRange must be trivially destructible because it is "
51                "used in unions");
52  
53  unsigned SourceLocation::getHashValue() const {
54    return llvm::DenseMapInfo<UIntTy>::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 S;
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 S;
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  std::pair<FileID, unsigned> FullSourceLoc::getDecomposedExpansionLoc() const {
170    return SrcMgr->getDecomposedExpansionLoc(*this);
171  }
172  
173  FullSourceLoc FullSourceLoc::getSpellingLoc() const {
174    assert(isValid());
175    return FullSourceLoc(SrcMgr->getSpellingLoc(*this), *SrcMgr);
176  }
177  
178  FullSourceLoc FullSourceLoc::getFileLoc() const {
179    assert(isValid());
180    return FullSourceLoc(SrcMgr->getFileLoc(*this), *SrcMgr);
181  }
182  
183  PresumedLoc FullSourceLoc::getPresumedLoc(bool UseLineDirectives) const {
184    if (!isValid())
185      return PresumedLoc();
186  
187    return SrcMgr->getPresumedLoc(*this, UseLineDirectives);
188  }
189  
190  bool FullSourceLoc::isMacroArgExpansion(FullSourceLoc *StartLoc) const {
191    assert(isValid());
192    return SrcMgr->isMacroArgExpansion(*this, StartLoc);
193  }
194  
195  FullSourceLoc FullSourceLoc::getImmediateMacroCallerLoc() const {
196    assert(isValid());
197    return FullSourceLoc(SrcMgr->getImmediateMacroCallerLoc(*this), *SrcMgr);
198  }
199  
200  std::pair<FullSourceLoc, StringRef> FullSourceLoc::getModuleImportLoc() const {
201    if (!isValid())
202      return std::make_pair(FullSourceLoc(), StringRef());
203  
204    std::pair<SourceLocation, StringRef> ImportLoc =
205        SrcMgr->getModuleImportLoc(*this);
206    return std::make_pair(FullSourceLoc(ImportLoc.first, *SrcMgr),
207                          ImportLoc.second);
208  }
209  
210  unsigned FullSourceLoc::getFileOffset() const {
211    assert(isValid());
212    return SrcMgr->getFileOffset(*this);
213  }
214  
215  unsigned FullSourceLoc::getLineNumber(bool *Invalid) const {
216    assert(isValid());
217    return SrcMgr->getLineNumber(getFileID(), getFileOffset(), Invalid);
218  }
219  
220  unsigned FullSourceLoc::getColumnNumber(bool *Invalid) const {
221    assert(isValid());
222    return SrcMgr->getColumnNumber(getFileID(), getFileOffset(), Invalid);
223  }
224  
225  const FileEntry *FullSourceLoc::getFileEntry() const {
226    assert(isValid());
227    return SrcMgr->getFileEntryForID(getFileID());
228  }
229  
230  OptionalFileEntryRef FullSourceLoc::getFileEntryRef() const {
231    assert(isValid());
232    return SrcMgr->getFileEntryRefForID(getFileID());
233  }
234  
235  unsigned FullSourceLoc::getExpansionLineNumber(bool *Invalid) const {
236    assert(isValid());
237    return SrcMgr->getExpansionLineNumber(*this, Invalid);
238  }
239  
240  unsigned FullSourceLoc::getExpansionColumnNumber(bool *Invalid) const {
241    assert(isValid());
242    return SrcMgr->getExpansionColumnNumber(*this, Invalid);
243  }
244  
245  unsigned FullSourceLoc::getSpellingLineNumber(bool *Invalid) const {
246    assert(isValid());
247    return SrcMgr->getSpellingLineNumber(*this, Invalid);
248  }
249  
250  unsigned FullSourceLoc::getSpellingColumnNumber(bool *Invalid) const {
251    assert(isValid());
252    return SrcMgr->getSpellingColumnNumber(*this, Invalid);
253  }
254  
255  bool FullSourceLoc::isInSystemHeader() const {
256    assert(isValid());
257    return SrcMgr->isInSystemHeader(*this);
258  }
259  
260  bool FullSourceLoc::isBeforeInTranslationUnitThan(SourceLocation Loc) const {
261    assert(isValid());
262    return SrcMgr->isBeforeInTranslationUnit(*this, Loc);
263  }
264  
265  LLVM_DUMP_METHOD void FullSourceLoc::dump() const {
266    SourceLocation::dump(*SrcMgr);
267  }
268  
269  const char *FullSourceLoc::getCharacterData(bool *Invalid) const {
270    assert(isValid());
271    return SrcMgr->getCharacterData(*this, Invalid);
272  }
273  
274  StringRef FullSourceLoc::getBufferData(bool *Invalid) const {
275    assert(isValid());
276    return SrcMgr->getBufferData(SrcMgr->getFileID(*this), Invalid);
277  }
278  
279  std::pair<FileID, unsigned> FullSourceLoc::getDecomposedLoc() const {
280    return SrcMgr->getDecomposedLoc(*this);
281  }
282