[DFAJumpThreading] Remove incoming StartBlock from all phis when unfolding select...
[llvm-project.git] / clang / tools / libclang / CXSourceLocation.cpp
blobba70cbfee8995f25b9cef3e5f0cf59606331eb27
1 //===- CXSourceLocation.cpp - CXSourceLocations APIs ------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file defines routines for manipulating CXSourceLocations.
11 //===----------------------------------------------------------------------===//
13 #include "CXSourceLocation.h"
14 #include "CIndexer.h"
15 #include "CLog.h"
16 #include "CXFile.h"
17 #include "CXLoadedDiagnostic.h"
18 #include "CXString.h"
19 #include "CXTranslationUnit.h"
20 #include "clang/Basic/FileManager.h"
21 #include "clang/Frontend/ASTUnit.h"
22 #include "llvm/Support/Compiler.h"
23 #include "llvm/Support/Format.h"
25 using namespace clang;
26 using namespace clang::cxindex;
28 //===----------------------------------------------------------------------===//
29 // Internal predicates on CXSourceLocations.
30 //===----------------------------------------------------------------------===//
32 static bool isASTUnitSourceLocation(const CXSourceLocation &L) {
33 // If the lowest bit is clear then the first ptr_data entry is a SourceManager
34 // pointer, or the CXSourceLocation is a null location.
35 return ((uintptr_t)L.ptr_data[0] & 0x1) == 0;
38 //===----------------------------------------------------------------------===//
39 // Basic construction and comparison of CXSourceLocations and CXSourceRanges.
40 //===----------------------------------------------------------------------===//
42 CXSourceLocation clang_getNullLocation() {
43 CXSourceLocation Result = { { nullptr, nullptr }, 0 };
44 return Result;
47 unsigned clang_equalLocations(CXSourceLocation loc1, CXSourceLocation loc2) {
48 return (loc1.ptr_data[0] == loc2.ptr_data[0] &&
49 loc1.ptr_data[1] == loc2.ptr_data[1] &&
50 loc1.int_data == loc2.int_data);
53 CXSourceRange clang_getNullRange() {
54 CXSourceRange Result = { { nullptr, nullptr }, 0, 0 };
55 return Result;
58 CXSourceRange clang_getRange(CXSourceLocation begin, CXSourceLocation end) {
59 if (!isASTUnitSourceLocation(begin)) {
60 if (isASTUnitSourceLocation(end))
61 return clang_getNullRange();
62 CXSourceRange Result = { { begin.ptr_data[0], end.ptr_data[0] }, 0, 0 };
63 return Result;
66 if (begin.ptr_data[0] != end.ptr_data[0] ||
67 begin.ptr_data[1] != end.ptr_data[1])
68 return clang_getNullRange();
70 CXSourceRange Result = { { begin.ptr_data[0], begin.ptr_data[1] },
71 begin.int_data, end.int_data };
73 return Result;
76 unsigned clang_equalRanges(CXSourceRange range1, CXSourceRange range2) {
77 return range1.ptr_data[0] == range2.ptr_data[0]
78 && range1.ptr_data[1] == range2.ptr_data[1]
79 && range1.begin_int_data == range2.begin_int_data
80 && range1.end_int_data == range2.end_int_data;
83 int clang_Range_isNull(CXSourceRange range) {
84 return clang_equalRanges(range, clang_getNullRange());
88 CXSourceLocation clang_getRangeStart(CXSourceRange range) {
89 // Special decoding for CXSourceLocations for CXLoadedDiagnostics.
90 if ((uintptr_t)range.ptr_data[0] & 0x1) {
91 CXSourceLocation Result = { { range.ptr_data[0], nullptr }, 0 };
92 return Result;
95 CXSourceLocation Result = { { range.ptr_data[0], range.ptr_data[1] },
96 range.begin_int_data };
97 return Result;
100 CXSourceLocation clang_getRangeEnd(CXSourceRange range) {
101 // Special decoding for CXSourceLocations for CXLoadedDiagnostics.
102 if ((uintptr_t)range.ptr_data[0] & 0x1) {
103 CXSourceLocation Result = { { range.ptr_data[1], nullptr }, 0 };
104 return Result;
107 CXSourceLocation Result = { { range.ptr_data[0], range.ptr_data[1] },
108 range.end_int_data };
109 return Result;
112 //===----------------------------------------------------------------------===//
113 // Getting CXSourceLocations and CXSourceRanges from a translation unit.
114 //===----------------------------------------------------------------------===//
116 CXSourceLocation clang_getLocation(CXTranslationUnit TU,
117 CXFile file,
118 unsigned line,
119 unsigned column) {
120 if (cxtu::isNotUsableTU(TU)) {
121 LOG_BAD_TU(TU);
122 return clang_getNullLocation();
124 if (!file)
125 return clang_getNullLocation();
126 if (line == 0 || column == 0)
127 return clang_getNullLocation();
129 LogRef Log = Logger::make(__func__);
130 ASTUnit *CXXUnit = cxtu::getASTUnit(TU);
131 ASTUnit::ConcurrencyCheck Check(*CXXUnit);
132 FileEntryRef File = *cxfile::getFileEntryRef(file);
133 SourceLocation SLoc = CXXUnit->getLocation(File, line, column);
134 if (SLoc.isInvalid()) {
135 if (Log)
136 *Log << llvm::format("(\"%s\", %d, %d) = invalid",
137 File.getName().str().c_str(), line, column);
138 return clang_getNullLocation();
141 CXSourceLocation CXLoc =
142 cxloc::translateSourceLocation(CXXUnit->getASTContext(), SLoc);
143 if (Log)
144 *Log << llvm::format("(\"%s\", %d, %d) = ", File.getName().str().c_str(),
145 line, column)
146 << CXLoc;
148 return CXLoc;
151 CXSourceLocation clang_getLocationForOffset(CXTranslationUnit TU,
152 CXFile file,
153 unsigned offset) {
154 if (cxtu::isNotUsableTU(TU)) {
155 LOG_BAD_TU(TU);
156 return clang_getNullLocation();
158 if (!file)
159 return clang_getNullLocation();
161 ASTUnit *CXXUnit = cxtu::getASTUnit(TU);
163 SourceLocation SLoc
164 = CXXUnit->getLocation(*cxfile::getFileEntryRef(file), offset);
166 if (SLoc.isInvalid())
167 return clang_getNullLocation();
169 return cxloc::translateSourceLocation(CXXUnit->getASTContext(), SLoc);
172 //===----------------------------------------------------------------------===//
173 // Routines for expanding and manipulating CXSourceLocations, regardless
174 // of their origin.
175 //===----------------------------------------------------------------------===//
177 static void createNullLocation(CXFile *file, unsigned *line,
178 unsigned *column, unsigned *offset) {
179 if (file)
180 *file = nullptr;
181 if (line)
182 *line = 0;
183 if (column)
184 *column = 0;
185 if (offset)
186 *offset = 0;
189 static void createNullLocation(CXString *filename, unsigned *line,
190 unsigned *column, unsigned *offset = nullptr) {
191 if (filename)
192 *filename = cxstring::createEmpty();
193 if (line)
194 *line = 0;
195 if (column)
196 *column = 0;
197 if (offset)
198 *offset = 0;
201 int clang_Location_isInSystemHeader(CXSourceLocation location) {
202 const SourceLocation Loc =
203 SourceLocation::getFromRawEncoding(location.int_data);
204 if (Loc.isInvalid())
205 return 0;
207 const SourceManager &SM =
208 *static_cast<const SourceManager*>(location.ptr_data[0]);
209 return SM.isInSystemHeader(Loc);
212 int clang_Location_isFromMainFile(CXSourceLocation location) {
213 const SourceLocation Loc =
214 SourceLocation::getFromRawEncoding(location.int_data);
215 if (Loc.isInvalid())
216 return 0;
218 const SourceManager &SM =
219 *static_cast<const SourceManager*>(location.ptr_data[0]);
220 return SM.isWrittenInMainFile(Loc);
223 void clang_getExpansionLocation(CXSourceLocation location,
224 CXFile *file,
225 unsigned *line,
226 unsigned *column,
227 unsigned *offset) {
228 if (!isASTUnitSourceLocation(location)) {
229 CXLoadedDiagnostic::decodeLocation(location, file, line, column, offset);
230 return;
233 SourceLocation Loc = SourceLocation::getFromRawEncoding(location.int_data);
235 if (!location.ptr_data[0] || Loc.isInvalid()) {
236 createNullLocation(file, line, column, offset);
237 return;
240 const SourceManager &SM =
241 *static_cast<const SourceManager*>(location.ptr_data[0]);
242 SourceLocation ExpansionLoc = SM.getExpansionLoc(Loc);
244 // Check that the FileID is invalid on the expansion location.
245 // This can manifest in invalid code.
246 FileID fileID = SM.getFileID(ExpansionLoc);
247 bool Invalid = false;
248 const SrcMgr::SLocEntry &sloc = SM.getSLocEntry(fileID, &Invalid);
249 if (Invalid || !sloc.isFile()) {
250 createNullLocation(file, line, column, offset);
251 return;
254 if (file)
255 *file = cxfile::makeCXFile(SM.getFileEntryRefForID(fileID));
256 if (line)
257 *line = SM.getExpansionLineNumber(ExpansionLoc);
258 if (column)
259 *column = SM.getExpansionColumnNumber(ExpansionLoc);
260 if (offset)
261 *offset = SM.getDecomposedLoc(ExpansionLoc).second;
264 void clang_getPresumedLocation(CXSourceLocation location,
265 CXString *filename,
266 unsigned *line,
267 unsigned *column) {
268 if (!isASTUnitSourceLocation(location)) {
269 // Other SourceLocation implementations do not support presumed locations
270 // at this time.
271 createNullLocation(filename, line, column);
272 return;
275 SourceLocation Loc = SourceLocation::getFromRawEncoding(location.int_data);
277 if (!location.ptr_data[0] || Loc.isInvalid()) {
278 createNullLocation(filename, line, column);
279 return;
282 const SourceManager &SM =
283 *static_cast<const SourceManager *>(location.ptr_data[0]);
284 PresumedLoc PreLoc = SM.getPresumedLoc(Loc);
285 if (PreLoc.isInvalid()) {
286 createNullLocation(filename, line, column);
287 return;
290 if (filename) *filename = cxstring::createRef(PreLoc.getFilename());
291 if (line) *line = PreLoc.getLine();
292 if (column) *column = PreLoc.getColumn();
295 void clang_getInstantiationLocation(CXSourceLocation location,
296 CXFile *file,
297 unsigned *line,
298 unsigned *column,
299 unsigned *offset) {
300 // Redirect to new API.
301 clang_getExpansionLocation(location, file, line, column, offset);
304 void clang_getSpellingLocation(CXSourceLocation location,
305 CXFile *file,
306 unsigned *line,
307 unsigned *column,
308 unsigned *offset) {
309 if (!isASTUnitSourceLocation(location)) {
310 CXLoadedDiagnostic::decodeLocation(location, file, line,
311 column, offset);
312 return;
315 SourceLocation Loc = SourceLocation::getFromRawEncoding(location.int_data);
317 if (!location.ptr_data[0] || Loc.isInvalid())
318 return createNullLocation(file, line, column, offset);
320 const SourceManager &SM =
321 *static_cast<const SourceManager*>(location.ptr_data[0]);
322 // FIXME: This should call SourceManager::getSpellingLoc().
323 SourceLocation SpellLoc = SM.getFileLoc(Loc);
324 std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(SpellLoc);
325 FileID FID = LocInfo.first;
326 unsigned FileOffset = LocInfo.second;
328 if (FID.isInvalid())
329 return createNullLocation(file, line, column, offset);
331 if (file)
332 *file = cxfile::makeCXFile(SM.getFileEntryRefForID(FID));
333 if (line)
334 *line = SM.getLineNumber(FID, FileOffset);
335 if (column)
336 *column = SM.getColumnNumber(FID, FileOffset);
337 if (offset)
338 *offset = FileOffset;
341 void clang_getFileLocation(CXSourceLocation location,
342 CXFile *file,
343 unsigned *line,
344 unsigned *column,
345 unsigned *offset) {
346 if (!isASTUnitSourceLocation(location)) {
347 CXLoadedDiagnostic::decodeLocation(location, file, line,
348 column, offset);
349 return;
352 SourceLocation Loc = SourceLocation::getFromRawEncoding(location.int_data);
354 if (!location.ptr_data[0] || Loc.isInvalid())
355 return createNullLocation(file, line, column, offset);
357 const SourceManager &SM =
358 *static_cast<const SourceManager*>(location.ptr_data[0]);
359 SourceLocation FileLoc = SM.getFileLoc(Loc);
360 std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(FileLoc);
361 FileID FID = LocInfo.first;
362 unsigned FileOffset = LocInfo.second;
364 if (FID.isInvalid())
365 return createNullLocation(file, line, column, offset);
367 if (file)
368 *file = cxfile::makeCXFile(SM.getFileEntryRefForID(FID));
369 if (line)
370 *line = SM.getLineNumber(FID, FileOffset);
371 if (column)
372 *column = SM.getColumnNumber(FID, FileOffset);
373 if (offset)
374 *offset = FileOffset;