| Ted Kremenek | 3ddef06 | 2011-10-31 22:05:42 +0000 | [diff] [blame] | 1 | //===- 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 Kremenek | 3ddef06 | 2011-10-31 22:05:42 +0000 | [diff] [blame] | 15 | #include "CIndexer.h" | 
| Chandler Carruth | b1ba0ef | 2013-01-19 08:09:44 +0000 | [diff] [blame] | 16 | #include "CLog.h" | 
| Ted Kremenek | 1532217 | 2011-11-10 08:43:12 +0000 | [diff] [blame] | 17 | #include "CXLoadedDiagnostic.h" | 
| Chandler Carruth | f59edb9 | 2012-12-04 09:25:21 +0000 | [diff] [blame] | 18 | #include "CXSourceLocation.h" | 
 | 19 | #include "CXString.h" | 
 | 20 | #include "CXTranslationUnit.h" | 
| Dmitri Gribenko | acbe4ba | 2013-01-11 02:23:13 +0000 | [diff] [blame] | 21 | #include "llvm/Support/Compiler.h" | 
| Argyrios Kyrtzidis | c6f5c6a | 2013-01-10 18:54:52 +0000 | [diff] [blame] | 22 | #include "llvm/Support/Format.h" | 
| Ted Kremenek | 3ddef06 | 2011-10-31 22:05:42 +0000 | [diff] [blame] | 23 |  | 
 | 24 | using namespace clang; | 
| Argyrios Kyrtzidis | c6f5c6a | 2013-01-10 18:54:52 +0000 | [diff] [blame] | 25 | using namespace clang::cxindex; | 
| Ted Kremenek | 3ddef06 | 2011-10-31 22:05:42 +0000 | [diff] [blame] | 26 |  | 
 | 27 | //===----------------------------------------------------------------------===// | 
| Ted Kremenek | 51a7d5d | 2011-10-31 22:23:51 +0000 | [diff] [blame] | 28 | // Internal predicates on CXSourceLocations. | 
 | 29 | //===----------------------------------------------------------------------===// | 
 | 30 |  | 
 | 31 | static 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 Kremenek | 3ddef06 | 2011-10-31 22:05:42 +0000 | [diff] [blame] | 38 | // Basic construction and comparison of CXSourceLocations and CXSourceRanges. | 
 | 39 | //===----------------------------------------------------------------------===// | 
 | 40 |  | 
 | 41 | extern "C" { | 
 | 42 |    | 
 | 43 | CXSourceLocation clang_getNullLocation() { | 
 | 44 |   CXSourceLocation Result = { { 0, 0 }, 0 }; | 
 | 45 |   return Result; | 
 | 46 | } | 
 | 47 |  | 
 | 48 | unsigned 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 |  | 
 | 54 | CXSourceRange clang_getNullRange() { | 
 | 55 |   CXSourceRange Result = { { 0, 0 }, 0, 0 }; | 
 | 56 |   return Result; | 
 | 57 | } | 
 | 58 |  | 
 | 59 | CXSourceRange clang_getRange(CXSourceLocation begin, CXSourceLocation end) { | 
| Ted Kremenek | 1532217 | 2011-11-10 08:43:12 +0000 | [diff] [blame] | 60 |   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 Kremenek | 3ddef06 | 2011-10-31 22:05:42 +0000 | [diff] [blame] | 67 |   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 Kremenek | 3ddef06 | 2011-10-31 22:05:42 +0000 | [diff] [blame] | 77 | unsigned 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 |  | 
 | 84 | int clang_Range_isNull(CXSourceRange range) { | 
 | 85 |   return clang_equalRanges(range, clang_getNullRange()); | 
 | 86 | } | 
 | 87 |    | 
 | 88 |    | 
 | 89 | CXSourceLocation clang_getRangeStart(CXSourceRange range) { | 
| Ted Kremenek | 1532217 | 2011-11-10 08:43:12 +0000 | [diff] [blame] | 90 |   // Special decoding for CXSourceLocations for CXLoadedDiagnostics. | 
 | 91 |   if ((uintptr_t)range.ptr_data[0] & 0x1) { | 
 | 92 |     CXSourceLocation Result = { { range.ptr_data[0], 0 }, 0 }; | 
 | 93 |     return Result;     | 
 | 94 |   } | 
 | 95 |    | 
| Ted Kremenek | 3ddef06 | 2011-10-31 22:05:42 +0000 | [diff] [blame] | 96 |   CXSourceLocation Result = { { range.ptr_data[0], range.ptr_data[1] }, | 
 | 97 |     range.begin_int_data }; | 
 | 98 |   return Result; | 
 | 99 | } | 
 | 100 |  | 
 | 101 | CXSourceLocation clang_getRangeEnd(CXSourceRange range) { | 
| Ted Kremenek | 1532217 | 2011-11-10 08:43:12 +0000 | [diff] [blame] | 102 |   // Special decoding for CXSourceLocations for CXLoadedDiagnostics. | 
 | 103 |   if ((uintptr_t)range.ptr_data[0] & 0x1) { | 
 | 104 |     CXSourceLocation Result = { { range.ptr_data[1], 0 }, 0 }; | 
 | 105 |     return Result;     | 
 | 106 |   } | 
 | 107 |  | 
| Ted Kremenek | 3ddef06 | 2011-10-31 22:05:42 +0000 | [diff] [blame] | 108 |   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 |  | 
 | 119 | extern "C" { | 
 | 120 |    | 
| Dmitri Gribenko | 5694feb | 2013-01-26 18:53:38 +0000 | [diff] [blame] | 121 | CXSourceLocation clang_getLocation(CXTranslationUnit TU, | 
| Ted Kremenek | 3ddef06 | 2011-10-31 22:05:42 +0000 | [diff] [blame] | 122 |                                    CXFile file, | 
 | 123 |                                    unsigned line, | 
 | 124 |                                    unsigned column) { | 
| Stephen Hines | 651f13c | 2014-04-23 16:59:28 -0700 | [diff] [blame] | 125 |   if (cxtu::isNotUsableTU(TU)) { | 
 | 126 |     LOG_BAD_TU(TU); | 
 | 127 |     return clang_getNullLocation(); | 
 | 128 |   } | 
 | 129 |   if (!file) | 
| Ted Kremenek | 3ddef06 | 2011-10-31 22:05:42 +0000 | [diff] [blame] | 130 |     return clang_getNullLocation(); | 
| Argyrios Kyrtzidis | 8644aa9 | 2013-09-12 01:10:36 +0000 | [diff] [blame] | 131 |   if (line == 0 || column == 0) | 
 | 132 |     return clang_getNullLocation(); | 
| Ted Kremenek | 3ddef06 | 2011-10-31 22:05:42 +0000 | [diff] [blame] | 133 |    | 
| Dmitri Gribenko | acbe4ba | 2013-01-11 02:23:13 +0000 | [diff] [blame] | 134 |   LogRef Log = Logger::make(LLVM_FUNCTION_NAME); | 
| Dmitri Gribenko | 5694feb | 2013-01-26 18:53:38 +0000 | [diff] [blame] | 135 |   ASTUnit *CXXUnit = cxtu::getASTUnit(TU); | 
| Ted Kremenek | 3ddef06 | 2011-10-31 22:05:42 +0000 | [diff] [blame] | 136 |   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 Kyrtzidis | c6f5c6a | 2013-01-10 18:54:52 +0000 | [diff] [blame] | 140 |     if (Log) | 
 | 141 |       *Log << llvm::format("(\"%s\", %d, %d) = invalid", | 
 | 142 |                            File->getName(), line, column); | 
| Ted Kremenek | 3ddef06 | 2011-10-31 22:05:42 +0000 | [diff] [blame] | 143 |     return clang_getNullLocation(); | 
 | 144 |   } | 
 | 145 |    | 
| Argyrios Kyrtzidis | c6f5c6a | 2013-01-10 18:54:52 +0000 | [diff] [blame] | 146 |   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 Kremenek | 3ddef06 | 2011-10-31 22:05:42 +0000 | [diff] [blame] | 151 |    | 
| Argyrios Kyrtzidis | c6f5c6a | 2013-01-10 18:54:52 +0000 | [diff] [blame] | 152 |   return CXLoc; | 
| Ted Kremenek | 3ddef06 | 2011-10-31 22:05:42 +0000 | [diff] [blame] | 153 | } | 
 | 154 |    | 
| Dmitri Gribenko | 5694feb | 2013-01-26 18:53:38 +0000 | [diff] [blame] | 155 | CXSourceLocation clang_getLocationForOffset(CXTranslationUnit TU, | 
| Ted Kremenek | 3ddef06 | 2011-10-31 22:05:42 +0000 | [diff] [blame] | 156 |                                             CXFile file, | 
 | 157 |                                             unsigned offset) { | 
| Stephen Hines | 651f13c | 2014-04-23 16:59:28 -0700 | [diff] [blame] | 158 |   if (cxtu::isNotUsableTU(TU)) { | 
 | 159 |     LOG_BAD_TU(TU); | 
| Ted Kremenek | 3ddef06 | 2011-10-31 22:05:42 +0000 | [diff] [blame] | 160 |     return clang_getNullLocation(); | 
| Stephen Hines | 651f13c | 2014-04-23 16:59:28 -0700 | [diff] [blame] | 161 |   } | 
 | 162 |   if (!file) | 
 | 163 |     return clang_getNullLocation(); | 
 | 164 |  | 
| Dmitri Gribenko | 5694feb | 2013-01-26 18:53:38 +0000 | [diff] [blame] | 165 |   ASTUnit *CXXUnit = cxtu::getASTUnit(TU); | 
| Ted Kremenek | 3ddef06 | 2011-10-31 22:05:42 +0000 | [diff] [blame] | 166 |  | 
 | 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 Kremenek | 3ddef06 | 2011-10-31 22:05:42 +0000 | [diff] [blame] | 183 | static void createNullLocation(CXFile *file, unsigned *line, | 
 | 184 |                                unsigned *column, unsigned *offset) { | 
 | 185 |   if (file) | 
 | 186 |     *file = 0; | 
 | 187 |   if (line) | 
 | 188 |     *line = 0; | 
 | 189 |   if (column) | 
 | 190 |     *column = 0; | 
 | 191 |   if (offset) | 
 | 192 |     *offset = 0; | 
 | 193 |   return; | 
 | 194 | } | 
 | 195 |  | 
| Ted Kremenek | 51a7d5d | 2011-10-31 22:23:51 +0000 | [diff] [blame] | 196 | static void createNullLocation(CXString *filename, unsigned *line, | 
 | 197 |                                unsigned *column, unsigned *offset = 0) { | 
 | 198 |   if (filename) | 
| Dmitri Gribenko | dc66adb | 2013-02-01 14:21:22 +0000 | [diff] [blame] | 199 |     *filename = cxstring::createEmpty(); | 
| Ted Kremenek | 51a7d5d | 2011-10-31 22:23:51 +0000 | [diff] [blame] | 200 |   if (line) | 
 | 201 |     *line = 0; | 
 | 202 |   if (column) | 
 | 203 |     *column = 0; | 
 | 204 |   if (offset) | 
 | 205 |     *offset = 0; | 
 | 206 |   return; | 
 | 207 | } | 
 | 208 |  | 
| Ted Kremenek | 3ddef06 | 2011-10-31 22:05:42 +0000 | [diff] [blame] | 209 | extern "C" { | 
 | 210 |  | 
| Argyrios Kyrtzidis | 4522f63 | 2013-04-12 17:06:51 +0000 | [diff] [blame] | 211 | int 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 Toit | ad0d570 | 2013-08-08 17:48:14 +0000 | [diff] [blame] | 222 | int 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 Friedman | 2414697 | 2013-08-22 00:27:10 +0000 | [diff] [blame] | 230 |   return SM.isWrittenInMainFile(Loc); | 
| Stefanus Du Toit | ad0d570 | 2013-08-08 17:48:14 +0000 | [diff] [blame] | 231 | } | 
 | 232 |  | 
| Ted Kremenek | 3ddef06 | 2011-10-31 22:05:42 +0000 | [diff] [blame] | 233 | void clang_getExpansionLocation(CXSourceLocation location, | 
 | 234 |                                 CXFile *file, | 
 | 235 |                                 unsigned *line, | 
 | 236 |                                 unsigned *column, | 
 | 237 |                                 unsigned *offset) { | 
| Ted Kremenek | 3ddef06 | 2011-10-31 22:05:42 +0000 | [diff] [blame] | 238 |    | 
| Ted Kremenek | 1532217 | 2011-11-10 08:43:12 +0000 | [diff] [blame] | 239 |   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 Kremenek | 51a7d5d | 2011-10-31 22:23:51 +0000 | [diff] [blame] | 254 |    | 
| Ted Kremenek | 1532217 | 2011-11-10 08:43:12 +0000 | [diff] [blame] | 255 |   // 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 Kyrtzidis | b4efaa0 | 2011-11-03 02:20:36 +0000 | [diff] [blame] | 262 |     return; | 
| Ted Kremenek | 3ddef06 | 2011-10-31 22:05:42 +0000 | [diff] [blame] | 263 |   } | 
 | 264 |    | 
| Ted Kremenek | 1532217 | 2011-11-10 08:43:12 +0000 | [diff] [blame] | 265 |   if (file) | 
| David Greene | 3cfa532 | 2013-01-15 22:09:49 +0000 | [diff] [blame] | 266 |     *file = const_cast<FileEntry *>(SM.getFileEntryForSLocEntry(sloc)); | 
| Ted Kremenek | 1532217 | 2011-11-10 08:43:12 +0000 | [diff] [blame] | 267 |   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 Kremenek | 3ddef06 | 2011-10-31 22:05:42 +0000 | [diff] [blame] | 273 | } | 
 | 274 |  | 
 | 275 | void clang_getPresumedLocation(CXSourceLocation location, | 
 | 276 |                                CXString *filename, | 
 | 277 |                                unsigned *line, | 
 | 278 |                                unsigned *column) { | 
| Evgeniy Stepanov | 2bb6dad | 2013-09-11 12:33:58 +0000 | [diff] [blame] | 279 |  | 
| Ted Kremenek | 1532217 | 2011-11-10 08:43:12 +0000 | [diff] [blame] | 280 |   if (!isASTUnitSourceLocation(location)) { | 
 | 281 |     // Other SourceLocation implementations do not support presumed locations | 
 | 282 |     // at this time. | 
 | 283 |     createNullLocation(filename, line, column); | 
| Ted Kremenek | 51a7d5d | 2011-10-31 22:23:51 +0000 | [diff] [blame] | 284 |     return; | 
| Ted Kremenek | 3ddef06 | 2011-10-31 22:05:42 +0000 | [diff] [blame] | 285 |   } | 
| Ted Kremenek | 1532217 | 2011-11-10 08:43:12 +0000 | [diff] [blame] | 286 |  | 
 | 287 |   SourceLocation Loc = SourceLocation::getFromRawEncoding(location.int_data); | 
 | 288 |  | 
| Evgeniy Stepanov | 2bb6dad | 2013-09-11 12:33:58 +0000 | [diff] [blame] | 289 |   if (!location.ptr_data[0] || Loc.isInvalid()) { | 
| Ted Kremenek | 1532217 | 2011-11-10 08:43:12 +0000 | [diff] [blame] | 290 |     createNullLocation(filename, line, column); | 
| Evgeniy Stepanov | 2bb6dad | 2013-09-11 12:33:58 +0000 | [diff] [blame] | 291 |     return; | 
| Ted Kremenek | 1532217 | 2011-11-10 08:43:12 +0000 | [diff] [blame] | 292 |   } | 
| Evgeniy Stepanov | 2bb6dad | 2013-09-11 12:33:58 +0000 | [diff] [blame] | 293 |  | 
 | 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 Kremenek | 3ddef06 | 2011-10-31 22:05:42 +0000 | [diff] [blame] | 305 | } | 
 | 306 |  | 
 | 307 | void 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 |  | 
 | 316 | void clang_getSpellingLocation(CXSourceLocation location, | 
 | 317 |                                CXFile *file, | 
 | 318 |                                unsigned *line, | 
 | 319 |                                unsigned *column, | 
 | 320 |                                unsigned *offset) { | 
| Ted Kremenek | 3ddef06 | 2011-10-31 22:05:42 +0000 | [diff] [blame] | 321 |    | 
| Ted Kremenek | 1532217 | 2011-11-10 08:43:12 +0000 | [diff] [blame] | 322 |   if (!isASTUnitSourceLocation(location)) { | 
 | 323 |     CXLoadedDiagnostic::decodeLocation(location, file, line, | 
 | 324 |                                            column, offset); | 
| Ted Kremenek | 51a7d5d | 2011-10-31 22:23:51 +0000 | [diff] [blame] | 325 |     return; | 
| Ted Kremenek | 3ddef06 | 2011-10-31 22:05:42 +0000 | [diff] [blame] | 326 |   } | 
| Ted Kremenek | 1532217 | 2011-11-10 08:43:12 +0000 | [diff] [blame] | 327 |    | 
 | 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 Kyrtzidis | 2d5c133 | 2013-01-04 18:30:13 +0000 | [diff] [blame] | 335 |   // FIXME: This should call SourceManager::getSpellingLoc(). | 
| Ted Kremenek | 6ee225c | 2012-12-19 01:16:49 +0000 | [diff] [blame] | 336 |   SourceLocation SpellLoc = SM.getFileLoc(Loc); | 
| Ted Kremenek | 1532217 | 2011-11-10 08:43:12 +0000 | [diff] [blame] | 337 |   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 Greene | 3cfa532 | 2013-01-15 22:09:49 +0000 | [diff] [blame] | 345 |     *file = const_cast<FileEntry *>(SM.getFileEntryForID(FID)); | 
| Ted Kremenek | 1532217 | 2011-11-10 08:43:12 +0000 | [diff] [blame] | 346 |   if (line) | 
 | 347 |     *line = SM.getLineNumber(FID, FileOffset); | 
 | 348 |   if (column) | 
 | 349 |     *column = SM.getColumnNumber(FID, FileOffset); | 
 | 350 |   if (offset) | 
 | 351 |     *offset = FileOffset; | 
| Ted Kremenek | 3ddef06 | 2011-10-31 22:05:42 +0000 | [diff] [blame] | 352 | } | 
 | 353 |  | 
| Argyrios Kyrtzidis | 2d5c133 | 2013-01-04 18:30:13 +0000 | [diff] [blame] | 354 | void clang_getFileLocation(CXSourceLocation location, | 
 | 355 |                            CXFile *file, | 
 | 356 |                            unsigned *line, | 
 | 357 |                            unsigned *column, | 
 | 358 |                            unsigned *offset) { | 
| Ted Kremenek | 3ddef06 | 2011-10-31 22:05:42 +0000 | [diff] [blame] | 359 |  | 
| Argyrios Kyrtzidis | 2d5c133 | 2013-01-04 18:30:13 +0000 | [diff] [blame] | 360 |   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 Gribenko | e4ea879 | 2013-01-23 15:56:07 +0000 | [diff] [blame] | 382 |     *file = const_cast<FileEntry *>(SM.getFileEntryForID(FID)); | 
| Argyrios Kyrtzidis | 2d5c133 | 2013-01-04 18:30:13 +0000 | [diff] [blame] | 383 |   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" |