CXSourceLocation.cpp revision b4efaa0a14dd2382aa028c03283b5a7f5345e24d
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" 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//===----------------------------------------------------------------------===// 25// 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//===----------------------------------------------------------------------===// 35// 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 151static 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 164static 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 177extern "C" { 178 179void clang_getExpansionLocation(CXSourceLocation location, 180 CXFile *file, 181 unsigned *line, 182 unsigned *column, 183 unsigned *offset) { 184 185 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; 215 return; 216 } 217 218 // FIXME: 219 createNullLocation(file, line, column, offset); 220} 221 222void clang_getPresumedLocation(CXSourceLocation location, 223 CXString *filename, 224 unsigned *line, 225 unsigned *column) { 226 227 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; 245 } 246 247 // FIXME: 248 createNullLocation(filename, line, column); 249} 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) { 265 266 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; 300 } 301 302 // FIXME: 303 createNullLocation(file, line, column, offset); 304} 305 306} // end extern "C" 307 308