blob: d8d4c96e48d349c6d86416f7191691aa234d29a1 [file] [log] [blame]
Ted Kremenek4c4f08d2011-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"
15
16#include "CIndexer.h"
17#include "CXString.h"
18#include "CXSourceLocation.h"
19#include "CXTranslationUnit.h"
20
21using namespace clang;
22using namespace clang::cxstring;
23
24//===----------------------------------------------------------------------===//
Ted Kremenekce6a5712011-10-31 22:23:51 +000025// Internal predicates on CXSourceLocations.
26//===----------------------------------------------------------------------===//
27
28static bool isASTUnitSourceLocation(const CXSourceLocation &L) {
29 // If the lowest bit is clear then the first ptr_data entry is a SourceManager
30 // pointer, or the CXSourceLocation is a null location.
31 return ((uintptr_t)L.ptr_data[0] & 0x1) == 0;
32}
33
34//===----------------------------------------------------------------------===//
Ted Kremenek4c4f08d2011-10-31 22:05:42 +000035// Basic construction and comparison of CXSourceLocations and CXSourceRanges.
36//===----------------------------------------------------------------------===//
37
38extern "C" {
39
40CXSourceLocation clang_getNullLocation() {
41 CXSourceLocation Result = { { 0, 0 }, 0 };
42 return Result;
43}
44
45unsigned clang_equalLocations(CXSourceLocation loc1, CXSourceLocation loc2) {
46 return (loc1.ptr_data[0] == loc2.ptr_data[0] &&
47 loc1.ptr_data[1] == loc2.ptr_data[1] &&
48 loc1.int_data == loc2.int_data);
49}
50
51CXSourceRange clang_getNullRange() {
52 CXSourceRange Result = { { 0, 0 }, 0, 0 };
53 return Result;
54}
55
56CXSourceRange clang_getRange(CXSourceLocation begin, CXSourceLocation end) {
57 if (begin.ptr_data[0] != end.ptr_data[0] ||
58 begin.ptr_data[1] != end.ptr_data[1])
59 return clang_getNullRange();
60
61 CXSourceRange Result = { { begin.ptr_data[0], begin.ptr_data[1] },
62 begin.int_data, end.int_data };
63
64 return Result;
65}
66
67
68unsigned clang_equalRanges(CXSourceRange range1, CXSourceRange range2) {
69 return range1.ptr_data[0] == range2.ptr_data[0]
70 && range1.ptr_data[1] == range2.ptr_data[1]
71 && range1.begin_int_data == range2.begin_int_data
72 && range1.end_int_data == range2.end_int_data;
73}
74
75int clang_Range_isNull(CXSourceRange range) {
76 return clang_equalRanges(range, clang_getNullRange());
77}
78
79
80CXSourceLocation clang_getRangeStart(CXSourceRange range) {
81 CXSourceLocation Result = { { range.ptr_data[0], range.ptr_data[1] },
82 range.begin_int_data };
83 return Result;
84}
85
86CXSourceLocation clang_getRangeEnd(CXSourceRange range) {
87 CXSourceLocation Result = { { range.ptr_data[0], range.ptr_data[1] },
88 range.end_int_data };
89 return Result;
90}
91
92} // end extern "C"
93
94//===----------------------------------------------------------------------===//
95// Getting CXSourceLocations and CXSourceRanges from a translation unit.
96//===----------------------------------------------------------------------===//
97
98extern "C" {
99
100CXSourceLocation clang_getLocation(CXTranslationUnit tu,
101 CXFile file,
102 unsigned line,
103 unsigned column) {
104 if (!tu || !file)
105 return clang_getNullLocation();
106
107 bool Logging = ::getenv("LIBCLANG_LOGGING");
108 ASTUnit *CXXUnit = static_cast<ASTUnit *>(tu->TUData);
109 ASTUnit::ConcurrencyCheck Check(*CXXUnit);
110 const FileEntry *File = static_cast<const FileEntry *>(file);
111 SourceLocation SLoc = CXXUnit->getLocation(File, line, column);
112 if (SLoc.isInvalid()) {
113 if (Logging)
114 llvm::errs() << "clang_getLocation(\"" << File->getName()
115 << "\", " << line << ", " << column << ") = invalid\n";
116 return clang_getNullLocation();
117 }
118
119 if (Logging)
120 llvm::errs() << "clang_getLocation(\"" << File->getName()
121 << "\", " << line << ", " << column << ") = "
122 << SLoc.getRawEncoding() << "\n";
123
124 return cxloc::translateSourceLocation(CXXUnit->getASTContext(), SLoc);
125}
126
127CXSourceLocation clang_getLocationForOffset(CXTranslationUnit tu,
128 CXFile file,
129 unsigned offset) {
130 if (!tu || !file)
131 return clang_getNullLocation();
132
133 ASTUnit *CXXUnit = static_cast<ASTUnit *>(tu->TUData);
134
135 SourceLocation SLoc
136 = CXXUnit->getLocation(static_cast<const FileEntry *>(file), offset);
137
138 if (SLoc.isInvalid())
139 return clang_getNullLocation();
140
141 return cxloc::translateSourceLocation(CXXUnit->getASTContext(), SLoc);
142}
143
144} // end extern "C"
145
146//===----------------------------------------------------------------------===//
147// Routines for expanding and manipulating CXSourceLocations, regardless
148// of their origin.
149//===----------------------------------------------------------------------===//
150
Ted Kremenek4c4f08d2011-10-31 22:05:42 +0000151static void createNullLocation(CXFile *file, unsigned *line,
152 unsigned *column, unsigned *offset) {
153 if (file)
154 *file = 0;
155 if (line)
156 *line = 0;
157 if (column)
158 *column = 0;
159 if (offset)
160 *offset = 0;
161 return;
162}
163
Ted Kremenekce6a5712011-10-31 22:23:51 +0000164static void createNullLocation(CXString *filename, unsigned *line,
165 unsigned *column, unsigned *offset = 0) {
166 if (filename)
167 *filename = createCXString("");
168 if (line)
169 *line = 0;
170 if (column)
171 *column = 0;
172 if (offset)
173 *offset = 0;
174 return;
175}
176
Ted Kremenek4c4f08d2011-10-31 22:05:42 +0000177extern "C" {
178
179void clang_getExpansionLocation(CXSourceLocation location,
180 CXFile *file,
181 unsigned *line,
182 unsigned *column,
183 unsigned *offset) {
Ted Kremenek4c4f08d2011-10-31 22:05:42 +0000184
Ted Kremenekce6a5712011-10-31 22:23:51 +0000185 if (isASTUnitSourceLocation(location)) {
186 SourceLocation Loc = SourceLocation::getFromRawEncoding(location.int_data);
187
188 if (!location.ptr_data[0] || Loc.isInvalid()) {
189 createNullLocation(file, line, column, offset);
190 return;
191 }
192
193 const SourceManager &SM =
194 *static_cast<const SourceManager*>(location.ptr_data[0]);
195 SourceLocation ExpansionLoc = SM.getExpansionLoc(Loc);
196
197 // Check that the FileID is invalid on the expansion location.
198 // This can manifest in invalid code.
199 FileID fileID = SM.getFileID(ExpansionLoc);
200 bool Invalid = false;
201 const SrcMgr::SLocEntry &sloc = SM.getSLocEntry(fileID, &Invalid);
202 if (Invalid || !sloc.isFile()) {
203 createNullLocation(file, line, column, offset);
204 return;
205 }
206
207 if (file)
208 *file = (void *)SM.getFileEntryForSLocEntry(sloc);
209 if (line)
210 *line = SM.getExpansionLineNumber(ExpansionLoc);
211 if (column)
212 *column = SM.getExpansionColumnNumber(ExpansionLoc);
213 if (offset)
214 *offset = SM.getDecomposedLoc(ExpansionLoc).second;
Argyrios Kyrtzidis7ca77352011-11-03 02:20:36 +0000215 return;
Ted Kremenek4c4f08d2011-10-31 22:05:42 +0000216 }
217
Ted Kremenekce6a5712011-10-31 22:23:51 +0000218 // FIXME:
219 createNullLocation(file, line, column, offset);
Ted Kremenek4c4f08d2011-10-31 22:05:42 +0000220}
221
222void clang_getPresumedLocation(CXSourceLocation location,
223 CXString *filename,
224 unsigned *line,
225 unsigned *column) {
Ted Kremenek4c4f08d2011-10-31 22:05:42 +0000226
Ted Kremenekce6a5712011-10-31 22:23:51 +0000227 if (isASTUnitSourceLocation(location)) {
228 SourceLocation Loc = SourceLocation::getFromRawEncoding(location.int_data);
229
230 if (!location.ptr_data[0] || Loc.isInvalid())
231 createNullLocation(filename, line, column);
232 else {
233 const SourceManager &SM =
234 *static_cast<const SourceManager*>(location.ptr_data[0]);
235 PresumedLoc PreLoc = SM.getPresumedLoc(Loc);
236
237 if (filename)
238 *filename = createCXString(PreLoc.getFilename());
239 if (line)
240 *line = PreLoc.getLine();
241 if (column)
242 *column = PreLoc.getColumn();
243 }
244 return;
Ted Kremenek4c4f08d2011-10-31 22:05:42 +0000245 }
Ted Kremenekce6a5712011-10-31 22:23:51 +0000246
247 // FIXME:
248 createNullLocation(filename, line, column);
Ted Kremenek4c4f08d2011-10-31 22:05:42 +0000249}
250
251void clang_getInstantiationLocation(CXSourceLocation location,
252 CXFile *file,
253 unsigned *line,
254 unsigned *column,
255 unsigned *offset) {
256 // Redirect to new API.
257 clang_getExpansionLocation(location, file, line, column, offset);
258}
259
260void clang_getSpellingLocation(CXSourceLocation location,
261 CXFile *file,
262 unsigned *line,
263 unsigned *column,
264 unsigned *offset) {
Ted Kremenek4c4f08d2011-10-31 22:05:42 +0000265
Ted Kremenekce6a5712011-10-31 22:23:51 +0000266 if (isASTUnitSourceLocation(location)) {
267 SourceLocation Loc = SourceLocation::getFromRawEncoding(location.int_data);
268
269 if (!location.ptr_data[0] || Loc.isInvalid())
270 return createNullLocation(file, line, column, offset);
271
272 const SourceManager &SM =
273 *static_cast<const SourceManager*>(location.ptr_data[0]);
274 SourceLocation SpellLoc = Loc;
275 if (SpellLoc.isMacroID()) {
276 SourceLocation SimpleSpellingLoc = SM.getImmediateSpellingLoc(SpellLoc);
277 if (SimpleSpellingLoc.isFileID() &&
278 SM.getFileEntryForID(SM.getDecomposedLoc(SimpleSpellingLoc).first))
279 SpellLoc = SimpleSpellingLoc;
280 else
281 SpellLoc = SM.getExpansionLoc(SpellLoc);
282 }
283
284 std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(SpellLoc);
285 FileID FID = LocInfo.first;
286 unsigned FileOffset = LocInfo.second;
287
288 if (FID.isInvalid())
289 return createNullLocation(file, line, column, offset);
290
291 if (file)
292 *file = (void *)SM.getFileEntryForID(FID);
293 if (line)
294 *line = SM.getLineNumber(FID, FileOffset);
295 if (column)
296 *column = SM.getColumnNumber(FID, FileOffset);
297 if (offset)
298 *offset = FileOffset;
299 return;
Ted Kremenek4c4f08d2011-10-31 22:05:42 +0000300 }
Ted Kremenekce6a5712011-10-31 22:23:51 +0000301
302 // FIXME:
303 createNullLocation(file, line, column, offset);
Ted Kremenek4c4f08d2011-10-31 22:05:42 +0000304}
305
306} // end extern "C"
307