Coverage Report

Created: 2020-02-25 14:32

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