1 //===- SourceLocation.cpp - Compact identifier for Source Files -----------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file defines accessor methods for the FullSourceLoc class.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "clang/Basic/SourceLocation.h"
15 #include "clang/Basic/LLVM.h"
16 #include "clang/Basic/PrettyStackTrace.h"
17 #include "clang/Basic/SourceManager.h"
18 #include "llvm/ADT/StringRef.h"
19 #include "llvm/Support/Compiler.h"
20 #include "llvm/Support/MemoryBuffer.h"
21 #include "llvm/Support/raw_ostream.h"
22 #include <cassert>
23 #include <string>
24 #include <utility>
25
26 using namespace clang;
27
28 //===----------------------------------------------------------------------===//
29 // PrettyStackTraceLoc
30 //===----------------------------------------------------------------------===//
31
print(raw_ostream & OS) const32 void PrettyStackTraceLoc::print(raw_ostream &OS) const {
33 if (Loc.isValid()) {
34 Loc.print(OS, SM);
35 OS << ": ";
36 }
37 OS << Message << '\n';
38 }
39
40 //===----------------------------------------------------------------------===//
41 // SourceLocation
42 //===----------------------------------------------------------------------===//
43
print(raw_ostream & OS,const SourceManager & SM) const44 void SourceLocation::print(raw_ostream &OS, const SourceManager &SM)const{
45 if (!isValid()) {
46 OS << "<invalid loc>";
47 return;
48 }
49
50 if (isFileID()) {
51 PresumedLoc PLoc = SM.getPresumedLoc(*this);
52
53 if (PLoc.isInvalid()) {
54 OS << "<invalid>";
55 return;
56 }
57 // The macro expansion and spelling pos is identical for file locs.
58 OS << PLoc.getFilename() << ':' << PLoc.getLine()
59 << ':' << PLoc.getColumn();
60 return;
61 }
62
63 SM.getExpansionLoc(*this).print(OS, SM);
64
65 OS << " <Spelling=";
66 SM.getSpellingLoc(*this).print(OS, SM);
67 OS << '>';
68 }
69
70 LLVM_DUMP_METHOD std::string
printToString(const SourceManager & SM) const71 SourceLocation::printToString(const SourceManager &SM) const {
72 std::string S;
73 llvm::raw_string_ostream OS(S);
74 print(OS, SM);
75 return OS.str();
76 }
77
dump(const SourceManager & SM) const78 LLVM_DUMP_METHOD void SourceLocation::dump(const SourceManager &SM) const {
79 print(llvm::errs(), SM);
80 llvm::errs() << '\n';
81 }
82
dump(const SourceManager & SM) const83 LLVM_DUMP_METHOD void SourceRange::dump(const SourceManager &SM) const {
84 print(llvm::errs(), SM);
85 llvm::errs() << '\n';
86 }
87
PrintDifference(raw_ostream & OS,const SourceManager & SM,SourceLocation Loc,PresumedLoc Previous)88 static PresumedLoc PrintDifference(raw_ostream &OS, const SourceManager &SM,
89 SourceLocation Loc, PresumedLoc Previous) {
90 if (Loc.isFileID()) {
91
92 PresumedLoc PLoc = SM.getPresumedLoc(Loc);
93
94 if (PLoc.isInvalid()) {
95 OS << "<invalid sloc>";
96 return Previous;
97 }
98
99 if (Previous.isInvalid() ||
100 strcmp(PLoc.getFilename(), Previous.getFilename()) != 0) {
101 OS << PLoc.getFilename() << ':' << PLoc.getLine() << ':'
102 << PLoc.getColumn();
103 } else if (Previous.isInvalid() || PLoc.getLine() != Previous.getLine()) {
104 OS << "line" << ':' << PLoc.getLine() << ':' << PLoc.getColumn();
105 } else {
106 OS << "col" << ':' << PLoc.getColumn();
107 }
108 return PLoc;
109 }
110 auto PrintedLoc = PrintDifference(OS, SM, SM.getExpansionLoc(Loc), Previous);
111
112 OS << " <Spelling=";
113 PrintedLoc = PrintDifference(OS, SM, SM.getSpellingLoc(Loc), PrintedLoc);
114 OS << '>';
115 return PrintedLoc;
116 }
117
print(raw_ostream & OS,const SourceManager & SM) const118 void SourceRange::print(raw_ostream &OS, const SourceManager &SM) const {
119
120 OS << '<';
121 auto PrintedLoc = PrintDifference(OS, SM, B, {});
122 if (B != E) {
123 OS << ", ";
124 PrintDifference(OS, SM, E, PrintedLoc);
125 }
126 OS << '>';
127 }
128
129 LLVM_DUMP_METHOD std::string
printToString(const SourceManager & SM) const130 SourceRange::printToString(const SourceManager &SM) const {
131 std::string S;
132 llvm::raw_string_ostream OS(S);
133 print(OS, SM);
134 return OS.str();
135 }
136
137 //===----------------------------------------------------------------------===//
138 // FullSourceLoc
139 //===----------------------------------------------------------------------===//
140
getFileID() const141 FileID FullSourceLoc::getFileID() const {
142 assert(isValid());
143 return SrcMgr->getFileID(*this);
144 }
145
getExpansionLoc() const146 FullSourceLoc FullSourceLoc::getExpansionLoc() const {
147 assert(isValid());
148 return FullSourceLoc(SrcMgr->getExpansionLoc(*this), *SrcMgr);
149 }
150
getSpellingLoc() const151 FullSourceLoc FullSourceLoc::getSpellingLoc() const {
152 assert(isValid());
153 return FullSourceLoc(SrcMgr->getSpellingLoc(*this), *SrcMgr);
154 }
155
getFileLoc() const156 FullSourceLoc FullSourceLoc::getFileLoc() const {
157 assert(isValid());
158 return FullSourceLoc(SrcMgr->getFileLoc(*this), *SrcMgr);
159 }
160
getPresumedLoc(bool UseLineDirectives) const161 PresumedLoc FullSourceLoc::getPresumedLoc(bool UseLineDirectives) const {
162 if (!isValid())
163 return PresumedLoc();
164
165 return SrcMgr->getPresumedLoc(*this, UseLineDirectives);
166 }
167
isMacroArgExpansion(FullSourceLoc * StartLoc) const168 bool FullSourceLoc::isMacroArgExpansion(FullSourceLoc *StartLoc) const {
169 assert(isValid());
170 return SrcMgr->isMacroArgExpansion(*this, StartLoc);
171 }
172
getImmediateMacroCallerLoc() const173 FullSourceLoc FullSourceLoc::getImmediateMacroCallerLoc() const {
174 assert(isValid());
175 return FullSourceLoc(SrcMgr->getImmediateMacroCallerLoc(*this), *SrcMgr);
176 }
177
getModuleImportLoc() const178 std::pair<FullSourceLoc, StringRef> FullSourceLoc::getModuleImportLoc() const {
179 if (!isValid())
180 return std::make_pair(FullSourceLoc(), StringRef());
181
182 std::pair<SourceLocation, StringRef> ImportLoc =
183 SrcMgr->getModuleImportLoc(*this);
184 return std::make_pair(FullSourceLoc(ImportLoc.first, *SrcMgr),
185 ImportLoc.second);
186 }
187
getFileOffset() const188 unsigned FullSourceLoc::getFileOffset() const {
189 assert(isValid());
190 return SrcMgr->getFileOffset(*this);
191 }
192
getLineNumber(bool * Invalid) const193 unsigned FullSourceLoc::getLineNumber(bool *Invalid) const {
194 assert(isValid());
195 return SrcMgr->getLineNumber(getFileID(), getFileOffset(), Invalid);
196 }
197
getColumnNumber(bool * Invalid) const198 unsigned FullSourceLoc::getColumnNumber(bool *Invalid) const {
199 assert(isValid());
200 return SrcMgr->getColumnNumber(getFileID(), getFileOffset(), Invalid);
201 }
202
getFileEntry() const203 const FileEntry *FullSourceLoc::getFileEntry() const {
204 assert(isValid());
205 return SrcMgr->getFileEntryForID(getFileID());
206 }
207
getExpansionLineNumber(bool * Invalid) const208 unsigned FullSourceLoc::getExpansionLineNumber(bool *Invalid) const {
209 assert(isValid());
210 return SrcMgr->getExpansionLineNumber(*this, Invalid);
211 }
212
getExpansionColumnNumber(bool * Invalid) const213 unsigned FullSourceLoc::getExpansionColumnNumber(bool *Invalid) const {
214 assert(isValid());
215 return SrcMgr->getExpansionColumnNumber(*this, Invalid);
216 }
217
getSpellingLineNumber(bool * Invalid) const218 unsigned FullSourceLoc::getSpellingLineNumber(bool *Invalid) const {
219 assert(isValid());
220 return SrcMgr->getSpellingLineNumber(*this, Invalid);
221 }
222
getSpellingColumnNumber(bool * Invalid) const223 unsigned FullSourceLoc::getSpellingColumnNumber(bool *Invalid) const {
224 assert(isValid());
225 return SrcMgr->getSpellingColumnNumber(*this, Invalid);
226 }
227
isInSystemHeader() const228 bool FullSourceLoc::isInSystemHeader() const {
229 assert(isValid());
230 return SrcMgr->isInSystemHeader(*this);
231 }
232
isBeforeInTranslationUnitThan(SourceLocation Loc) const233 bool FullSourceLoc::isBeforeInTranslationUnitThan(SourceLocation Loc) const {
234 assert(isValid());
235 return SrcMgr->isBeforeInTranslationUnit(*this, Loc);
236 }
237
dump() const238 LLVM_DUMP_METHOD void FullSourceLoc::dump() const {
239 SourceLocation::dump(*SrcMgr);
240 }
241
getCharacterData(bool * Invalid) const242 const char *FullSourceLoc::getCharacterData(bool *Invalid) const {
243 assert(isValid());
244 return SrcMgr->getCharacterData(*this, Invalid);
245 }
246
getBufferData(bool * Invalid) const247 StringRef FullSourceLoc::getBufferData(bool *Invalid) const {
248 assert(isValid());
249 return SrcMgr->getBuffer(SrcMgr->getFileID(*this), Invalid)->getBuffer();
250 }
251
getDecomposedLoc() const252 std::pair<FileID, unsigned> FullSourceLoc::getDecomposedLoc() const {
253 return SrcMgr->getDecomposedLoc(*this);
254 }
255