1f4a2713aSLionel Sambuc //===- CXSourceLocation.cpp - CXSourceLocations APIs ------------*- C++ -*-===//
2f4a2713aSLionel Sambuc //
3f4a2713aSLionel Sambuc // The LLVM Compiler Infrastructure
4f4a2713aSLionel Sambuc //
5f4a2713aSLionel Sambuc // This file is distributed under the University of Illinois Open Source
6f4a2713aSLionel Sambuc // License. See LICENSE.TXT for details.
7f4a2713aSLionel Sambuc //
8f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
9f4a2713aSLionel Sambuc //
10f4a2713aSLionel Sambuc // This file defines routines for manipulating CXSourceLocations.
11f4a2713aSLionel Sambuc //
12f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
13f4a2713aSLionel Sambuc
14f4a2713aSLionel Sambuc #include "clang/Frontend/ASTUnit.h"
15f4a2713aSLionel Sambuc #include "CIndexer.h"
16f4a2713aSLionel Sambuc #include "CLog.h"
17f4a2713aSLionel Sambuc #include "CXLoadedDiagnostic.h"
18f4a2713aSLionel Sambuc #include "CXSourceLocation.h"
19f4a2713aSLionel Sambuc #include "CXString.h"
20f4a2713aSLionel Sambuc #include "CXTranslationUnit.h"
21f4a2713aSLionel Sambuc #include "llvm/Support/Compiler.h"
22f4a2713aSLionel Sambuc #include "llvm/Support/Format.h"
23f4a2713aSLionel Sambuc
24f4a2713aSLionel Sambuc using namespace clang;
25f4a2713aSLionel Sambuc using namespace clang::cxindex;
26f4a2713aSLionel Sambuc
27f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
28f4a2713aSLionel Sambuc // Internal predicates on CXSourceLocations.
29f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
30f4a2713aSLionel Sambuc
isASTUnitSourceLocation(const CXSourceLocation & L)31f4a2713aSLionel Sambuc static bool isASTUnitSourceLocation(const CXSourceLocation &L) {
32f4a2713aSLionel Sambuc // If the lowest bit is clear then the first ptr_data entry is a SourceManager
33f4a2713aSLionel Sambuc // pointer, or the CXSourceLocation is a null location.
34f4a2713aSLionel Sambuc return ((uintptr_t)L.ptr_data[0] & 0x1) == 0;
35f4a2713aSLionel Sambuc }
36f4a2713aSLionel Sambuc
37f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
38f4a2713aSLionel Sambuc // Basic construction and comparison of CXSourceLocations and CXSourceRanges.
39f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
40f4a2713aSLionel Sambuc
41f4a2713aSLionel Sambuc extern "C" {
42f4a2713aSLionel Sambuc
clang_getNullLocation()43f4a2713aSLionel Sambuc CXSourceLocation clang_getNullLocation() {
44*0a6a1f1dSLionel Sambuc CXSourceLocation Result = { { nullptr, nullptr }, 0 };
45f4a2713aSLionel Sambuc return Result;
46f4a2713aSLionel Sambuc }
47f4a2713aSLionel Sambuc
clang_equalLocations(CXSourceLocation loc1,CXSourceLocation loc2)48f4a2713aSLionel Sambuc unsigned clang_equalLocations(CXSourceLocation loc1, CXSourceLocation loc2) {
49f4a2713aSLionel Sambuc return (loc1.ptr_data[0] == loc2.ptr_data[0] &&
50f4a2713aSLionel Sambuc loc1.ptr_data[1] == loc2.ptr_data[1] &&
51f4a2713aSLionel Sambuc loc1.int_data == loc2.int_data);
52f4a2713aSLionel Sambuc }
53f4a2713aSLionel Sambuc
clang_getNullRange()54f4a2713aSLionel Sambuc CXSourceRange clang_getNullRange() {
55*0a6a1f1dSLionel Sambuc CXSourceRange Result = { { nullptr, nullptr }, 0, 0 };
56f4a2713aSLionel Sambuc return Result;
57f4a2713aSLionel Sambuc }
58f4a2713aSLionel Sambuc
clang_getRange(CXSourceLocation begin,CXSourceLocation end)59f4a2713aSLionel Sambuc CXSourceRange clang_getRange(CXSourceLocation begin, CXSourceLocation end) {
60f4a2713aSLionel Sambuc if (!isASTUnitSourceLocation(begin)) {
61f4a2713aSLionel Sambuc if (isASTUnitSourceLocation(end))
62f4a2713aSLionel Sambuc return clang_getNullRange();
63f4a2713aSLionel Sambuc CXSourceRange Result = { { begin.ptr_data[0], end.ptr_data[0] }, 0, 0 };
64f4a2713aSLionel Sambuc return Result;
65f4a2713aSLionel Sambuc }
66f4a2713aSLionel Sambuc
67f4a2713aSLionel Sambuc if (begin.ptr_data[0] != end.ptr_data[0] ||
68f4a2713aSLionel Sambuc begin.ptr_data[1] != end.ptr_data[1])
69f4a2713aSLionel Sambuc return clang_getNullRange();
70f4a2713aSLionel Sambuc
71f4a2713aSLionel Sambuc CXSourceRange Result = { { begin.ptr_data[0], begin.ptr_data[1] },
72f4a2713aSLionel Sambuc begin.int_data, end.int_data };
73f4a2713aSLionel Sambuc
74f4a2713aSLionel Sambuc return Result;
75f4a2713aSLionel Sambuc }
76f4a2713aSLionel Sambuc
clang_equalRanges(CXSourceRange range1,CXSourceRange range2)77f4a2713aSLionel Sambuc unsigned clang_equalRanges(CXSourceRange range1, CXSourceRange range2) {
78f4a2713aSLionel Sambuc return range1.ptr_data[0] == range2.ptr_data[0]
79f4a2713aSLionel Sambuc && range1.ptr_data[1] == range2.ptr_data[1]
80f4a2713aSLionel Sambuc && range1.begin_int_data == range2.begin_int_data
81f4a2713aSLionel Sambuc && range1.end_int_data == range2.end_int_data;
82f4a2713aSLionel Sambuc }
83f4a2713aSLionel Sambuc
clang_Range_isNull(CXSourceRange range)84f4a2713aSLionel Sambuc int clang_Range_isNull(CXSourceRange range) {
85f4a2713aSLionel Sambuc return clang_equalRanges(range, clang_getNullRange());
86f4a2713aSLionel Sambuc }
87f4a2713aSLionel Sambuc
88f4a2713aSLionel Sambuc
clang_getRangeStart(CXSourceRange range)89f4a2713aSLionel Sambuc CXSourceLocation clang_getRangeStart(CXSourceRange range) {
90f4a2713aSLionel Sambuc // Special decoding for CXSourceLocations for CXLoadedDiagnostics.
91f4a2713aSLionel Sambuc if ((uintptr_t)range.ptr_data[0] & 0x1) {
92*0a6a1f1dSLionel Sambuc CXSourceLocation Result = { { range.ptr_data[0], nullptr }, 0 };
93f4a2713aSLionel Sambuc return Result;
94f4a2713aSLionel Sambuc }
95f4a2713aSLionel Sambuc
96f4a2713aSLionel Sambuc CXSourceLocation Result = { { range.ptr_data[0], range.ptr_data[1] },
97f4a2713aSLionel Sambuc range.begin_int_data };
98f4a2713aSLionel Sambuc return Result;
99f4a2713aSLionel Sambuc }
100f4a2713aSLionel Sambuc
clang_getRangeEnd(CXSourceRange range)101f4a2713aSLionel Sambuc CXSourceLocation clang_getRangeEnd(CXSourceRange range) {
102f4a2713aSLionel Sambuc // Special decoding for CXSourceLocations for CXLoadedDiagnostics.
103f4a2713aSLionel Sambuc if ((uintptr_t)range.ptr_data[0] & 0x1) {
104*0a6a1f1dSLionel Sambuc CXSourceLocation Result = { { range.ptr_data[1], nullptr }, 0 };
105f4a2713aSLionel Sambuc return Result;
106f4a2713aSLionel Sambuc }
107f4a2713aSLionel Sambuc
108f4a2713aSLionel Sambuc CXSourceLocation Result = { { range.ptr_data[0], range.ptr_data[1] },
109f4a2713aSLionel Sambuc range.end_int_data };
110f4a2713aSLionel Sambuc return Result;
111f4a2713aSLionel Sambuc }
112f4a2713aSLionel Sambuc
113f4a2713aSLionel Sambuc } // end extern "C"
114f4a2713aSLionel Sambuc
115f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
116f4a2713aSLionel Sambuc // Getting CXSourceLocations and CXSourceRanges from a translation unit.
117f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
118f4a2713aSLionel Sambuc
119f4a2713aSLionel Sambuc extern "C" {
120f4a2713aSLionel Sambuc
clang_getLocation(CXTranslationUnit TU,CXFile file,unsigned line,unsigned column)121f4a2713aSLionel Sambuc CXSourceLocation clang_getLocation(CXTranslationUnit TU,
122f4a2713aSLionel Sambuc CXFile file,
123f4a2713aSLionel Sambuc unsigned line,
124f4a2713aSLionel Sambuc unsigned column) {
125*0a6a1f1dSLionel Sambuc if (cxtu::isNotUsableTU(TU)) {
126*0a6a1f1dSLionel Sambuc LOG_BAD_TU(TU);
127*0a6a1f1dSLionel Sambuc return clang_getNullLocation();
128*0a6a1f1dSLionel Sambuc }
129*0a6a1f1dSLionel Sambuc if (!file)
130f4a2713aSLionel Sambuc return clang_getNullLocation();
131f4a2713aSLionel Sambuc if (line == 0 || column == 0)
132f4a2713aSLionel Sambuc return clang_getNullLocation();
133f4a2713aSLionel Sambuc
134f4a2713aSLionel Sambuc LogRef Log = Logger::make(LLVM_FUNCTION_NAME);
135f4a2713aSLionel Sambuc ASTUnit *CXXUnit = cxtu::getASTUnit(TU);
136f4a2713aSLionel Sambuc ASTUnit::ConcurrencyCheck Check(*CXXUnit);
137f4a2713aSLionel Sambuc const FileEntry *File = static_cast<const FileEntry *>(file);
138f4a2713aSLionel Sambuc SourceLocation SLoc = CXXUnit->getLocation(File, line, column);
139f4a2713aSLionel Sambuc if (SLoc.isInvalid()) {
140f4a2713aSLionel Sambuc if (Log)
141f4a2713aSLionel Sambuc *Log << llvm::format("(\"%s\", %d, %d) = invalid",
142f4a2713aSLionel Sambuc File->getName(), line, column);
143f4a2713aSLionel Sambuc return clang_getNullLocation();
144f4a2713aSLionel Sambuc }
145f4a2713aSLionel Sambuc
146f4a2713aSLionel Sambuc CXSourceLocation CXLoc =
147f4a2713aSLionel Sambuc cxloc::translateSourceLocation(CXXUnit->getASTContext(), SLoc);
148f4a2713aSLionel Sambuc if (Log)
149f4a2713aSLionel Sambuc *Log << llvm::format("(\"%s\", %d, %d) = ", File->getName(), line, column)
150f4a2713aSLionel Sambuc << CXLoc;
151f4a2713aSLionel Sambuc
152f4a2713aSLionel Sambuc return CXLoc;
153f4a2713aSLionel Sambuc }
154f4a2713aSLionel Sambuc
clang_getLocationForOffset(CXTranslationUnit TU,CXFile file,unsigned offset)155f4a2713aSLionel Sambuc CXSourceLocation clang_getLocationForOffset(CXTranslationUnit TU,
156f4a2713aSLionel Sambuc CXFile file,
157f4a2713aSLionel Sambuc unsigned offset) {
158*0a6a1f1dSLionel Sambuc if (cxtu::isNotUsableTU(TU)) {
159*0a6a1f1dSLionel Sambuc LOG_BAD_TU(TU);
160*0a6a1f1dSLionel Sambuc return clang_getNullLocation();
161*0a6a1f1dSLionel Sambuc }
162*0a6a1f1dSLionel Sambuc if (!file)
163f4a2713aSLionel Sambuc return clang_getNullLocation();
164f4a2713aSLionel Sambuc
165f4a2713aSLionel Sambuc ASTUnit *CXXUnit = cxtu::getASTUnit(TU);
166f4a2713aSLionel Sambuc
167f4a2713aSLionel Sambuc SourceLocation SLoc
168f4a2713aSLionel Sambuc = CXXUnit->getLocation(static_cast<const FileEntry *>(file), offset);
169f4a2713aSLionel Sambuc
170f4a2713aSLionel Sambuc if (SLoc.isInvalid())
171f4a2713aSLionel Sambuc return clang_getNullLocation();
172f4a2713aSLionel Sambuc
173f4a2713aSLionel Sambuc return cxloc::translateSourceLocation(CXXUnit->getASTContext(), SLoc);
174f4a2713aSLionel Sambuc }
175f4a2713aSLionel Sambuc
176f4a2713aSLionel Sambuc } // end extern "C"
177f4a2713aSLionel Sambuc
178f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
179f4a2713aSLionel Sambuc // Routines for expanding and manipulating CXSourceLocations, regardless
180f4a2713aSLionel Sambuc // of their origin.
181f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
182f4a2713aSLionel Sambuc
createNullLocation(CXFile * file,unsigned * line,unsigned * column,unsigned * offset)183f4a2713aSLionel Sambuc static void createNullLocation(CXFile *file, unsigned *line,
184f4a2713aSLionel Sambuc unsigned *column, unsigned *offset) {
185f4a2713aSLionel Sambuc if (file)
186*0a6a1f1dSLionel Sambuc *file = nullptr;
187f4a2713aSLionel Sambuc if (line)
188f4a2713aSLionel Sambuc *line = 0;
189f4a2713aSLionel Sambuc if (column)
190f4a2713aSLionel Sambuc *column = 0;
191f4a2713aSLionel Sambuc if (offset)
192f4a2713aSLionel Sambuc *offset = 0;
193f4a2713aSLionel Sambuc return;
194f4a2713aSLionel Sambuc }
195f4a2713aSLionel Sambuc
createNullLocation(CXString * filename,unsigned * line,unsigned * column,unsigned * offset=nullptr)196f4a2713aSLionel Sambuc static void createNullLocation(CXString *filename, unsigned *line,
197*0a6a1f1dSLionel Sambuc unsigned *column, unsigned *offset = nullptr) {
198f4a2713aSLionel Sambuc if (filename)
199f4a2713aSLionel Sambuc *filename = cxstring::createEmpty();
200f4a2713aSLionel Sambuc if (line)
201f4a2713aSLionel Sambuc *line = 0;
202f4a2713aSLionel Sambuc if (column)
203f4a2713aSLionel Sambuc *column = 0;
204f4a2713aSLionel Sambuc if (offset)
205f4a2713aSLionel Sambuc *offset = 0;
206f4a2713aSLionel Sambuc return;
207f4a2713aSLionel Sambuc }
208f4a2713aSLionel Sambuc
209f4a2713aSLionel Sambuc extern "C" {
210f4a2713aSLionel Sambuc
clang_Location_isInSystemHeader(CXSourceLocation location)211f4a2713aSLionel Sambuc int clang_Location_isInSystemHeader(CXSourceLocation location) {
212f4a2713aSLionel Sambuc const SourceLocation Loc =
213f4a2713aSLionel Sambuc SourceLocation::getFromRawEncoding(location.int_data);
214f4a2713aSLionel Sambuc if (Loc.isInvalid())
215f4a2713aSLionel Sambuc return 0;
216f4a2713aSLionel Sambuc
217f4a2713aSLionel Sambuc const SourceManager &SM =
218f4a2713aSLionel Sambuc *static_cast<const SourceManager*>(location.ptr_data[0]);
219f4a2713aSLionel Sambuc return SM.isInSystemHeader(Loc);
220f4a2713aSLionel Sambuc }
221f4a2713aSLionel Sambuc
clang_Location_isFromMainFile(CXSourceLocation location)222f4a2713aSLionel Sambuc int clang_Location_isFromMainFile(CXSourceLocation location) {
223f4a2713aSLionel Sambuc const SourceLocation Loc =
224f4a2713aSLionel Sambuc SourceLocation::getFromRawEncoding(location.int_data);
225f4a2713aSLionel Sambuc if (Loc.isInvalid())
226f4a2713aSLionel Sambuc return 0;
227f4a2713aSLionel Sambuc
228f4a2713aSLionel Sambuc const SourceManager &SM =
229f4a2713aSLionel Sambuc *static_cast<const SourceManager*>(location.ptr_data[0]);
230f4a2713aSLionel Sambuc return SM.isWrittenInMainFile(Loc);
231f4a2713aSLionel Sambuc }
232f4a2713aSLionel Sambuc
clang_getExpansionLocation(CXSourceLocation location,CXFile * file,unsigned * line,unsigned * column,unsigned * offset)233f4a2713aSLionel Sambuc void clang_getExpansionLocation(CXSourceLocation location,
234f4a2713aSLionel Sambuc CXFile *file,
235f4a2713aSLionel Sambuc unsigned *line,
236f4a2713aSLionel Sambuc unsigned *column,
237f4a2713aSLionel Sambuc unsigned *offset) {
238f4a2713aSLionel Sambuc
239f4a2713aSLionel Sambuc if (!isASTUnitSourceLocation(location)) {
240f4a2713aSLionel Sambuc CXLoadedDiagnostic::decodeLocation(location, file, line, column, offset);
241f4a2713aSLionel Sambuc return;
242f4a2713aSLionel Sambuc }
243f4a2713aSLionel Sambuc
244f4a2713aSLionel Sambuc SourceLocation Loc = SourceLocation::getFromRawEncoding(location.int_data);
245f4a2713aSLionel Sambuc
246f4a2713aSLionel Sambuc if (!location.ptr_data[0] || Loc.isInvalid()) {
247f4a2713aSLionel Sambuc createNullLocation(file, line, column, offset);
248f4a2713aSLionel Sambuc return;
249f4a2713aSLionel Sambuc }
250f4a2713aSLionel Sambuc
251f4a2713aSLionel Sambuc const SourceManager &SM =
252f4a2713aSLionel Sambuc *static_cast<const SourceManager*>(location.ptr_data[0]);
253f4a2713aSLionel Sambuc SourceLocation ExpansionLoc = SM.getExpansionLoc(Loc);
254f4a2713aSLionel Sambuc
255f4a2713aSLionel Sambuc // Check that the FileID is invalid on the expansion location.
256f4a2713aSLionel Sambuc // This can manifest in invalid code.
257f4a2713aSLionel Sambuc FileID fileID = SM.getFileID(ExpansionLoc);
258f4a2713aSLionel Sambuc bool Invalid = false;
259f4a2713aSLionel Sambuc const SrcMgr::SLocEntry &sloc = SM.getSLocEntry(fileID, &Invalid);
260f4a2713aSLionel Sambuc if (Invalid || !sloc.isFile()) {
261f4a2713aSLionel Sambuc createNullLocation(file, line, column, offset);
262f4a2713aSLionel Sambuc return;
263f4a2713aSLionel Sambuc }
264f4a2713aSLionel Sambuc
265f4a2713aSLionel Sambuc if (file)
266f4a2713aSLionel Sambuc *file = const_cast<FileEntry *>(SM.getFileEntryForSLocEntry(sloc));
267f4a2713aSLionel Sambuc if (line)
268f4a2713aSLionel Sambuc *line = SM.getExpansionLineNumber(ExpansionLoc);
269f4a2713aSLionel Sambuc if (column)
270f4a2713aSLionel Sambuc *column = SM.getExpansionColumnNumber(ExpansionLoc);
271f4a2713aSLionel Sambuc if (offset)
272f4a2713aSLionel Sambuc *offset = SM.getDecomposedLoc(ExpansionLoc).second;
273f4a2713aSLionel Sambuc }
274f4a2713aSLionel Sambuc
clang_getPresumedLocation(CXSourceLocation location,CXString * filename,unsigned * line,unsigned * column)275f4a2713aSLionel Sambuc void clang_getPresumedLocation(CXSourceLocation location,
276f4a2713aSLionel Sambuc CXString *filename,
277f4a2713aSLionel Sambuc unsigned *line,
278f4a2713aSLionel Sambuc unsigned *column) {
279f4a2713aSLionel Sambuc
280f4a2713aSLionel Sambuc if (!isASTUnitSourceLocation(location)) {
281f4a2713aSLionel Sambuc // Other SourceLocation implementations do not support presumed locations
282f4a2713aSLionel Sambuc // at this time.
283f4a2713aSLionel Sambuc createNullLocation(filename, line, column);
284f4a2713aSLionel Sambuc return;
285f4a2713aSLionel Sambuc }
286f4a2713aSLionel Sambuc
287f4a2713aSLionel Sambuc SourceLocation Loc = SourceLocation::getFromRawEncoding(location.int_data);
288f4a2713aSLionel Sambuc
289f4a2713aSLionel Sambuc if (!location.ptr_data[0] || Loc.isInvalid()) {
290f4a2713aSLionel Sambuc createNullLocation(filename, line, column);
291f4a2713aSLionel Sambuc return;
292f4a2713aSLionel Sambuc }
293f4a2713aSLionel Sambuc
294f4a2713aSLionel Sambuc const SourceManager &SM =
295f4a2713aSLionel Sambuc *static_cast<const SourceManager *>(location.ptr_data[0]);
296f4a2713aSLionel Sambuc PresumedLoc PreLoc = SM.getPresumedLoc(Loc);
297f4a2713aSLionel Sambuc if (PreLoc.isInvalid()) {
298f4a2713aSLionel Sambuc createNullLocation(filename, line, column);
299f4a2713aSLionel Sambuc return;
300f4a2713aSLionel Sambuc }
301f4a2713aSLionel Sambuc
302f4a2713aSLionel Sambuc if (filename) *filename = cxstring::createRef(PreLoc.getFilename());
303f4a2713aSLionel Sambuc if (line) *line = PreLoc.getLine();
304f4a2713aSLionel Sambuc if (column) *column = PreLoc.getColumn();
305f4a2713aSLionel Sambuc }
306f4a2713aSLionel Sambuc
clang_getInstantiationLocation(CXSourceLocation location,CXFile * file,unsigned * line,unsigned * column,unsigned * offset)307f4a2713aSLionel Sambuc void clang_getInstantiationLocation(CXSourceLocation location,
308f4a2713aSLionel Sambuc CXFile *file,
309f4a2713aSLionel Sambuc unsigned *line,
310f4a2713aSLionel Sambuc unsigned *column,
311f4a2713aSLionel Sambuc unsigned *offset) {
312f4a2713aSLionel Sambuc // Redirect to new API.
313f4a2713aSLionel Sambuc clang_getExpansionLocation(location, file, line, column, offset);
314f4a2713aSLionel Sambuc }
315f4a2713aSLionel Sambuc
clang_getSpellingLocation(CXSourceLocation location,CXFile * file,unsigned * line,unsigned * column,unsigned * offset)316f4a2713aSLionel Sambuc void clang_getSpellingLocation(CXSourceLocation location,
317f4a2713aSLionel Sambuc CXFile *file,
318f4a2713aSLionel Sambuc unsigned *line,
319f4a2713aSLionel Sambuc unsigned *column,
320f4a2713aSLionel Sambuc unsigned *offset) {
321f4a2713aSLionel Sambuc
322f4a2713aSLionel Sambuc if (!isASTUnitSourceLocation(location)) {
323f4a2713aSLionel Sambuc CXLoadedDiagnostic::decodeLocation(location, file, line,
324f4a2713aSLionel Sambuc column, offset);
325f4a2713aSLionel Sambuc return;
326f4a2713aSLionel Sambuc }
327f4a2713aSLionel Sambuc
328f4a2713aSLionel Sambuc SourceLocation Loc = SourceLocation::getFromRawEncoding(location.int_data);
329f4a2713aSLionel Sambuc
330f4a2713aSLionel Sambuc if (!location.ptr_data[0] || Loc.isInvalid())
331f4a2713aSLionel Sambuc return createNullLocation(file, line, column, offset);
332f4a2713aSLionel Sambuc
333f4a2713aSLionel Sambuc const SourceManager &SM =
334f4a2713aSLionel Sambuc *static_cast<const SourceManager*>(location.ptr_data[0]);
335f4a2713aSLionel Sambuc // FIXME: This should call SourceManager::getSpellingLoc().
336f4a2713aSLionel Sambuc SourceLocation SpellLoc = SM.getFileLoc(Loc);
337f4a2713aSLionel Sambuc std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(SpellLoc);
338f4a2713aSLionel Sambuc FileID FID = LocInfo.first;
339f4a2713aSLionel Sambuc unsigned FileOffset = LocInfo.second;
340f4a2713aSLionel Sambuc
341f4a2713aSLionel Sambuc if (FID.isInvalid())
342f4a2713aSLionel Sambuc return createNullLocation(file, line, column, offset);
343f4a2713aSLionel Sambuc
344f4a2713aSLionel Sambuc if (file)
345f4a2713aSLionel Sambuc *file = const_cast<FileEntry *>(SM.getFileEntryForID(FID));
346f4a2713aSLionel Sambuc if (line)
347f4a2713aSLionel Sambuc *line = SM.getLineNumber(FID, FileOffset);
348f4a2713aSLionel Sambuc if (column)
349f4a2713aSLionel Sambuc *column = SM.getColumnNumber(FID, FileOffset);
350f4a2713aSLionel Sambuc if (offset)
351f4a2713aSLionel Sambuc *offset = FileOffset;
352f4a2713aSLionel Sambuc }
353f4a2713aSLionel Sambuc
clang_getFileLocation(CXSourceLocation location,CXFile * file,unsigned * line,unsigned * column,unsigned * offset)354f4a2713aSLionel Sambuc void clang_getFileLocation(CXSourceLocation location,
355f4a2713aSLionel Sambuc CXFile *file,
356f4a2713aSLionel Sambuc unsigned *line,
357f4a2713aSLionel Sambuc unsigned *column,
358f4a2713aSLionel Sambuc unsigned *offset) {
359f4a2713aSLionel Sambuc
360f4a2713aSLionel Sambuc if (!isASTUnitSourceLocation(location)) {
361f4a2713aSLionel Sambuc CXLoadedDiagnostic::decodeLocation(location, file, line,
362f4a2713aSLionel Sambuc column, offset);
363f4a2713aSLionel Sambuc return;
364f4a2713aSLionel Sambuc }
365f4a2713aSLionel Sambuc
366f4a2713aSLionel Sambuc SourceLocation Loc = SourceLocation::getFromRawEncoding(location.int_data);
367f4a2713aSLionel Sambuc
368f4a2713aSLionel Sambuc if (!location.ptr_data[0] || Loc.isInvalid())
369f4a2713aSLionel Sambuc return createNullLocation(file, line, column, offset);
370f4a2713aSLionel Sambuc
371f4a2713aSLionel Sambuc const SourceManager &SM =
372f4a2713aSLionel Sambuc *static_cast<const SourceManager*>(location.ptr_data[0]);
373f4a2713aSLionel Sambuc SourceLocation FileLoc = SM.getFileLoc(Loc);
374f4a2713aSLionel Sambuc std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(FileLoc);
375f4a2713aSLionel Sambuc FileID FID = LocInfo.first;
376f4a2713aSLionel Sambuc unsigned FileOffset = LocInfo.second;
377f4a2713aSLionel Sambuc
378f4a2713aSLionel Sambuc if (FID.isInvalid())
379f4a2713aSLionel Sambuc return createNullLocation(file, line, column, offset);
380f4a2713aSLionel Sambuc
381f4a2713aSLionel Sambuc if (file)
382f4a2713aSLionel Sambuc *file = const_cast<FileEntry *>(SM.getFileEntryForID(FID));
383f4a2713aSLionel Sambuc if (line)
384f4a2713aSLionel Sambuc *line = SM.getLineNumber(FID, FileOffset);
385f4a2713aSLionel Sambuc if (column)
386f4a2713aSLionel Sambuc *column = SM.getColumnNumber(FID, FileOffset);
387f4a2713aSLionel Sambuc if (offset)
388f4a2713aSLionel Sambuc *offset = FileOffset;
389f4a2713aSLionel Sambuc }
390f4a2713aSLionel Sambuc
391f4a2713aSLionel Sambuc } // end extern "C"
392