Coverage Report

Created: 2020-09-15 12:33

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