blob: 64a441e128072c419e0277eb6c58b6ce58b75f20 [file] [log] [blame]
Ted Kremenek3ddef062011-10-31 22:05:42 +00001//===- CXSourceLocation.cpp - CXSourceLocations APIs ------------*- C++ -*-===//
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 routines for manipulating CXSourceLocations.
11//
12//===----------------------------------------------------------------------===//
13
14#include "clang/Frontend/ASTUnit.h"
Ted Kremenek3ddef062011-10-31 22:05:42 +000015#include "CIndexer.h"
Chandler Carruthb1ba0ef2013-01-19 08:09:44 +000016#include "CLog.h"
Ted Kremenek15322172011-11-10 08:43:12 +000017#include "CXLoadedDiagnostic.h"
Chandler Carruthf59edb92012-12-04 09:25:21 +000018#include "CXSourceLocation.h"
19#include "CXString.h"
20#include "CXTranslationUnit.h"
Dmitri Gribenkoacbe4ba2013-01-11 02:23:13 +000021#include "llvm/Support/Compiler.h"
Argyrios Kyrtzidisc6f5c6a2013-01-10 18:54:52 +000022#include "llvm/Support/Format.h"
Ted Kremenek3ddef062011-10-31 22:05:42 +000023
24using namespace clang;
Argyrios Kyrtzidisc6f5c6a2013-01-10 18:54:52 +000025using namespace clang::cxindex;
Ted Kremenek3ddef062011-10-31 22:05:42 +000026
27//===----------------------------------------------------------------------===//
Ted Kremenek51a7d5d2011-10-31 22:23:51 +000028// Internal predicates on CXSourceLocations.
29//===----------------------------------------------------------------------===//
30
31static bool isASTUnitSourceLocation(const CXSourceLocation &L) {
32 // If the lowest bit is clear then the first ptr_data entry is a SourceManager
33 // pointer, or the CXSourceLocation is a null location.
34 return ((uintptr_t)L.ptr_data[0] & 0x1) == 0;
35}
36
37//===----------------------------------------------------------------------===//
Ted Kremenek3ddef062011-10-31 22:05:42 +000038// Basic construction and comparison of CXSourceLocations and CXSourceRanges.
39//===----------------------------------------------------------------------===//
40
41extern "C" {
42
43CXSourceLocation clang_getNullLocation() {
Stephen Hinesc568f1e2014-07-21 00:47:37 -070044 CXSourceLocation Result = { { nullptr, nullptr }, 0 };
Ted Kremenek3ddef062011-10-31 22:05:42 +000045 return Result;
46}
47
48unsigned clang_equalLocations(CXSourceLocation loc1, CXSourceLocation loc2) {
49 return (loc1.ptr_data[0] == loc2.ptr_data[0] &&
50 loc1.ptr_data[1] == loc2.ptr_data[1] &&
51 loc1.int_data == loc2.int_data);
52}
53
54CXSourceRange clang_getNullRange() {
Stephen Hinesc568f1e2014-07-21 00:47:37 -070055 CXSourceRange Result = { { nullptr, nullptr }, 0, 0 };
Ted Kremenek3ddef062011-10-31 22:05:42 +000056 return Result;
57}
58
59CXSourceRange clang_getRange(CXSourceLocation begin, CXSourceLocation end) {
Ted Kremenek15322172011-11-10 08:43:12 +000060 if (!isASTUnitSourceLocation(begin)) {
61 if (isASTUnitSourceLocation(end))
62 return clang_getNullRange();
63 CXSourceRange Result = { { begin.ptr_data[0], end.ptr_data[0] }, 0, 0 };
64 return Result;
65 }
66
Ted Kremenek3ddef062011-10-31 22:05:42 +000067 if (begin.ptr_data[0] != end.ptr_data[0] ||
68 begin.ptr_data[1] != end.ptr_data[1])
69 return clang_getNullRange();
70
71 CXSourceRange Result = { { begin.ptr_data[0], begin.ptr_data[1] },
72 begin.int_data, end.int_data };
73
74 return Result;
75}
76
Ted Kremenek3ddef062011-10-31 22:05:42 +000077unsigned clang_equalRanges(CXSourceRange range1, CXSourceRange range2) {
78 return range1.ptr_data[0] == range2.ptr_data[0]
79 && range1.ptr_data[1] == range2.ptr_data[1]
80 && range1.begin_int_data == range2.begin_int_data
81 && range1.end_int_data == range2.end_int_data;
82}
83
84int clang_Range_isNull(CXSourceRange range) {
85 return clang_equalRanges(range, clang_getNullRange());
86}
87
88
89CXSourceLocation clang_getRangeStart(CXSourceRange range) {
Ted Kremenek15322172011-11-10 08:43:12 +000090 // Special decoding for CXSourceLocations for CXLoadedDiagnostics.
91 if ((uintptr_t)range.ptr_data[0] & 0x1) {
Stephen Hinesc568f1e2014-07-21 00:47:37 -070092 CXSourceLocation Result = { { range.ptr_data[0], nullptr }, 0 };
Ted Kremenek15322172011-11-10 08:43:12 +000093 return Result;
94 }
95
Ted Kremenek3ddef062011-10-31 22:05:42 +000096 CXSourceLocation Result = { { range.ptr_data[0], range.ptr_data[1] },
97 range.begin_int_data };
98 return Result;
99}
100
101CXSourceLocation clang_getRangeEnd(CXSourceRange range) {
Ted Kremenek15322172011-11-10 08:43:12 +0000102 // Special decoding for CXSourceLocations for CXLoadedDiagnostics.
103 if ((uintptr_t)range.ptr_data[0] & 0x1) {
Stephen Hinesc568f1e2014-07-21 00:47:37 -0700104 CXSourceLocation Result = { { range.ptr_data[1], nullptr }, 0 };
Ted Kremenek15322172011-11-10 08:43:12 +0000105 return Result;
106 }
107
Ted Kremenek3ddef062011-10-31 22:05:42 +0000108 CXSourceLocation Result = { { range.ptr_data[0], range.ptr_data[1] },
109 range.end_int_data };
110 return Result;
111}
112
113} // end extern "C"
114
115//===----------------------------------------------------------------------===//
116// Getting CXSourceLocations and CXSourceRanges from a translation unit.
117//===----------------------------------------------------------------------===//
118
119extern "C" {
120
Dmitri Gribenko5694feb2013-01-26 18:53:38 +0000121CXSourceLocation clang_getLocation(CXTranslationUnit TU,
Ted Kremenek3ddef062011-10-31 22:05:42 +0000122 CXFile file,
123 unsigned line,
124 unsigned column) {
Stephen Hines651f13c2014-04-23 16:59:28 -0700125 if (cxtu::isNotUsableTU(TU)) {
126 LOG_BAD_TU(TU);
127 return clang_getNullLocation();
128 }
129 if (!file)
Ted Kremenek3ddef062011-10-31 22:05:42 +0000130 return clang_getNullLocation();
Argyrios Kyrtzidis8644aa92013-09-12 01:10:36 +0000131 if (line == 0 || column == 0)
132 return clang_getNullLocation();
Ted Kremenek3ddef062011-10-31 22:05:42 +0000133
Dmitri Gribenkoacbe4ba2013-01-11 02:23:13 +0000134 LogRef Log = Logger::make(LLVM_FUNCTION_NAME);
Dmitri Gribenko5694feb2013-01-26 18:53:38 +0000135 ASTUnit *CXXUnit = cxtu::getASTUnit(TU);
Ted Kremenek3ddef062011-10-31 22:05:42 +0000136 ASTUnit::ConcurrencyCheck Check(*CXXUnit);
137 const FileEntry *File = static_cast<const FileEntry *>(file);
138 SourceLocation SLoc = CXXUnit->getLocation(File, line, column);
139 if (SLoc.isInvalid()) {
Argyrios Kyrtzidisc6f5c6a2013-01-10 18:54:52 +0000140 if (Log)
141 *Log << llvm::format("(\"%s\", %d, %d) = invalid",
142 File->getName(), line, column);
Ted Kremenek3ddef062011-10-31 22:05:42 +0000143 return clang_getNullLocation();
144 }
145
Argyrios Kyrtzidisc6f5c6a2013-01-10 18:54:52 +0000146 CXSourceLocation CXLoc =
147 cxloc::translateSourceLocation(CXXUnit->getASTContext(), SLoc);
148 if (Log)
149 *Log << llvm::format("(\"%s\", %d, %d) = ", File->getName(), line, column)
150 << CXLoc;
Ted Kremenek3ddef062011-10-31 22:05:42 +0000151
Argyrios Kyrtzidisc6f5c6a2013-01-10 18:54:52 +0000152 return CXLoc;
Ted Kremenek3ddef062011-10-31 22:05:42 +0000153}
154
Dmitri Gribenko5694feb2013-01-26 18:53:38 +0000155CXSourceLocation clang_getLocationForOffset(CXTranslationUnit TU,
Ted Kremenek3ddef062011-10-31 22:05:42 +0000156 CXFile file,
157 unsigned offset) {
Stephen Hines651f13c2014-04-23 16:59:28 -0700158 if (cxtu::isNotUsableTU(TU)) {
159 LOG_BAD_TU(TU);
Ted Kremenek3ddef062011-10-31 22:05:42 +0000160 return clang_getNullLocation();
Stephen Hines651f13c2014-04-23 16:59:28 -0700161 }
162 if (!file)
163 return clang_getNullLocation();
164
Dmitri Gribenko5694feb2013-01-26 18:53:38 +0000165 ASTUnit *CXXUnit = cxtu::getASTUnit(TU);
Ted Kremenek3ddef062011-10-31 22:05:42 +0000166
167 SourceLocation SLoc
168 = CXXUnit->getLocation(static_cast<const FileEntry *>(file), offset);
169
170 if (SLoc.isInvalid())
171 return clang_getNullLocation();
172
173 return cxloc::translateSourceLocation(CXXUnit->getASTContext(), SLoc);
174}
175
176} // end extern "C"
177
178//===----------------------------------------------------------------------===//
179// Routines for expanding and manipulating CXSourceLocations, regardless
180// of their origin.
181//===----------------------------------------------------------------------===//
182
Ted Kremenek3ddef062011-10-31 22:05:42 +0000183static void createNullLocation(CXFile *file, unsigned *line,
184 unsigned *column, unsigned *offset) {
185 if (file)
Stephen Hinesc568f1e2014-07-21 00:47:37 -0700186 *file = nullptr;
Ted Kremenek3ddef062011-10-31 22:05:42 +0000187 if (line)
188 *line = 0;
189 if (column)
190 *column = 0;
191 if (offset)
192 *offset = 0;
193 return;
194}
195
Ted Kremenek51a7d5d2011-10-31 22:23:51 +0000196static void createNullLocation(CXString *filename, unsigned *line,
Stephen Hinesc568f1e2014-07-21 00:47:37 -0700197 unsigned *column, unsigned *offset = nullptr) {
Ted Kremenek51a7d5d2011-10-31 22:23:51 +0000198 if (filename)
Dmitri Gribenkodc66adb2013-02-01 14:21:22 +0000199 *filename = cxstring::createEmpty();
Ted Kremenek51a7d5d2011-10-31 22:23:51 +0000200 if (line)
201 *line = 0;
202 if (column)
203 *column = 0;
204 if (offset)
205 *offset = 0;
206 return;
207}
208
Ted Kremenek3ddef062011-10-31 22:05:42 +0000209extern "C" {
210
Argyrios Kyrtzidis4522f632013-04-12 17:06:51 +0000211int clang_Location_isInSystemHeader(CXSourceLocation location) {
212 const SourceLocation Loc =
213 SourceLocation::getFromRawEncoding(location.int_data);
214 if (Loc.isInvalid())
215 return 0;
216
217 const SourceManager &SM =
218 *static_cast<const SourceManager*>(location.ptr_data[0]);
219 return SM.isInSystemHeader(Loc);
220}
221
Stefanus Du Toitad0d5702013-08-08 17:48:14 +0000222int clang_Location_isFromMainFile(CXSourceLocation location) {
223 const SourceLocation Loc =
224 SourceLocation::getFromRawEncoding(location.int_data);
225 if (Loc.isInvalid())
226 return 0;
227
228 const SourceManager &SM =
229 *static_cast<const SourceManager*>(location.ptr_data[0]);
Eli Friedman24146972013-08-22 00:27:10 +0000230 return SM.isWrittenInMainFile(Loc);
Stefanus Du Toitad0d5702013-08-08 17:48:14 +0000231}
232
Ted Kremenek3ddef062011-10-31 22:05:42 +0000233void clang_getExpansionLocation(CXSourceLocation location,
234 CXFile *file,
235 unsigned *line,
236 unsigned *column,
237 unsigned *offset) {
Ted Kremenek3ddef062011-10-31 22:05:42 +0000238
Ted Kremenek15322172011-11-10 08:43:12 +0000239 if (!isASTUnitSourceLocation(location)) {
240 CXLoadedDiagnostic::decodeLocation(location, file, line, column, offset);
241 return;
242 }
243
244 SourceLocation Loc = SourceLocation::getFromRawEncoding(location.int_data);
245
246 if (!location.ptr_data[0] || Loc.isInvalid()) {
247 createNullLocation(file, line, column, offset);
248 return;
249 }
250
251 const SourceManager &SM =
252 *static_cast<const SourceManager*>(location.ptr_data[0]);
253 SourceLocation ExpansionLoc = SM.getExpansionLoc(Loc);
Ted Kremenek51a7d5d2011-10-31 22:23:51 +0000254
Ted Kremenek15322172011-11-10 08:43:12 +0000255 // Check that the FileID is invalid on the expansion location.
256 // This can manifest in invalid code.
257 FileID fileID = SM.getFileID(ExpansionLoc);
258 bool Invalid = false;
259 const SrcMgr::SLocEntry &sloc = SM.getSLocEntry(fileID, &Invalid);
260 if (Invalid || !sloc.isFile()) {
261 createNullLocation(file, line, column, offset);
Argyrios Kyrtzidisb4efaa02011-11-03 02:20:36 +0000262 return;
Ted Kremenek3ddef062011-10-31 22:05:42 +0000263 }
264
Ted Kremenek15322172011-11-10 08:43:12 +0000265 if (file)
David Greene3cfa5322013-01-15 22:09:49 +0000266 *file = const_cast<FileEntry *>(SM.getFileEntryForSLocEntry(sloc));
Ted Kremenek15322172011-11-10 08:43:12 +0000267 if (line)
268 *line = SM.getExpansionLineNumber(ExpansionLoc);
269 if (column)
270 *column = SM.getExpansionColumnNumber(ExpansionLoc);
271 if (offset)
272 *offset = SM.getDecomposedLoc(ExpansionLoc).second;
Ted Kremenek3ddef062011-10-31 22:05:42 +0000273}
274
275void clang_getPresumedLocation(CXSourceLocation location,
276 CXString *filename,
277 unsigned *line,
278 unsigned *column) {
Evgeniy Stepanov2bb6dad2013-09-11 12:33:58 +0000279
Ted Kremenek15322172011-11-10 08:43:12 +0000280 if (!isASTUnitSourceLocation(location)) {
281 // Other SourceLocation implementations do not support presumed locations
282 // at this time.
283 createNullLocation(filename, line, column);
Ted Kremenek51a7d5d2011-10-31 22:23:51 +0000284 return;
Ted Kremenek3ddef062011-10-31 22:05:42 +0000285 }
Ted Kremenek15322172011-11-10 08:43:12 +0000286
287 SourceLocation Loc = SourceLocation::getFromRawEncoding(location.int_data);
288
Evgeniy Stepanov2bb6dad2013-09-11 12:33:58 +0000289 if (!location.ptr_data[0] || Loc.isInvalid()) {
Ted Kremenek15322172011-11-10 08:43:12 +0000290 createNullLocation(filename, line, column);
Evgeniy Stepanov2bb6dad2013-09-11 12:33:58 +0000291 return;
Ted Kremenek15322172011-11-10 08:43:12 +0000292 }
Evgeniy Stepanov2bb6dad2013-09-11 12:33:58 +0000293
294 const SourceManager &SM =
295 *static_cast<const SourceManager *>(location.ptr_data[0]);
296 PresumedLoc PreLoc = SM.getPresumedLoc(Loc);
297 if (PreLoc.isInvalid()) {
298 createNullLocation(filename, line, column);
299 return;
300 }
301
302 if (filename) *filename = cxstring::createRef(PreLoc.getFilename());
303 if (line) *line = PreLoc.getLine();
304 if (column) *column = PreLoc.getColumn();
Ted Kremenek3ddef062011-10-31 22:05:42 +0000305}
306
307void clang_getInstantiationLocation(CXSourceLocation location,
308 CXFile *file,
309 unsigned *line,
310 unsigned *column,
311 unsigned *offset) {
312 // Redirect to new API.
313 clang_getExpansionLocation(location, file, line, column, offset);
314}
315
316void clang_getSpellingLocation(CXSourceLocation location,
317 CXFile *file,
318 unsigned *line,
319 unsigned *column,
320 unsigned *offset) {
Ted Kremenek3ddef062011-10-31 22:05:42 +0000321
Ted Kremenek15322172011-11-10 08:43:12 +0000322 if (!isASTUnitSourceLocation(location)) {
323 CXLoadedDiagnostic::decodeLocation(location, file, line,
324 column, offset);
Ted Kremenek51a7d5d2011-10-31 22:23:51 +0000325 return;
Ted Kremenek3ddef062011-10-31 22:05:42 +0000326 }
Ted Kremenek15322172011-11-10 08:43:12 +0000327
328 SourceLocation Loc = SourceLocation::getFromRawEncoding(location.int_data);
329
330 if (!location.ptr_data[0] || Loc.isInvalid())
331 return createNullLocation(file, line, column, offset);
332
333 const SourceManager &SM =
334 *static_cast<const SourceManager*>(location.ptr_data[0]);
Argyrios Kyrtzidis2d5c1332013-01-04 18:30:13 +0000335 // FIXME: This should call SourceManager::getSpellingLoc().
Ted Kremenek6ee225c2012-12-19 01:16:49 +0000336 SourceLocation SpellLoc = SM.getFileLoc(Loc);
Ted Kremenek15322172011-11-10 08:43:12 +0000337 std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(SpellLoc);
338 FileID FID = LocInfo.first;
339 unsigned FileOffset = LocInfo.second;
340
341 if (FID.isInvalid())
342 return createNullLocation(file, line, column, offset);
343
344 if (file)
David Greene3cfa5322013-01-15 22:09:49 +0000345 *file = const_cast<FileEntry *>(SM.getFileEntryForID(FID));
Ted Kremenek15322172011-11-10 08:43:12 +0000346 if (line)
347 *line = SM.getLineNumber(FID, FileOffset);
348 if (column)
349 *column = SM.getColumnNumber(FID, FileOffset);
350 if (offset)
351 *offset = FileOffset;
Ted Kremenek3ddef062011-10-31 22:05:42 +0000352}
353
Argyrios Kyrtzidis2d5c1332013-01-04 18:30:13 +0000354void clang_getFileLocation(CXSourceLocation location,
355 CXFile *file,
356 unsigned *line,
357 unsigned *column,
358 unsigned *offset) {
Ted Kremenek3ddef062011-10-31 22:05:42 +0000359
Argyrios Kyrtzidis2d5c1332013-01-04 18:30:13 +0000360 if (!isASTUnitSourceLocation(location)) {
361 CXLoadedDiagnostic::decodeLocation(location, file, line,
362 column, offset);
363 return;
364 }
365
366 SourceLocation Loc = SourceLocation::getFromRawEncoding(location.int_data);
367
368 if (!location.ptr_data[0] || Loc.isInvalid())
369 return createNullLocation(file, line, column, offset);
370
371 const SourceManager &SM =
372 *static_cast<const SourceManager*>(location.ptr_data[0]);
373 SourceLocation FileLoc = SM.getFileLoc(Loc);
374 std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(FileLoc);
375 FileID FID = LocInfo.first;
376 unsigned FileOffset = LocInfo.second;
377
378 if (FID.isInvalid())
379 return createNullLocation(file, line, column, offset);
380
381 if (file)
Dmitri Gribenkoe4ea8792013-01-23 15:56:07 +0000382 *file = const_cast<FileEntry *>(SM.getFileEntryForID(FID));
Argyrios Kyrtzidis2d5c1332013-01-04 18:30:13 +0000383 if (line)
384 *line = SM.getLineNumber(FID, FileOffset);
385 if (column)
386 *column = SM.getColumnNumber(FID, FileOffset);
387 if (offset)
388 *offset = FileOffset;
389}
390
391} // end extern "C"