xref: /minix3/external/bsd/llvm/dist/clang/tools/libclang/CXSourceLocation.cpp (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
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