clang  19.0.0git
PreprocessingRecord.cpp
Go to the documentation of this file.
1 //===- PreprocessingRecord.cpp - Record of Preprocessing ------------------===//
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 implements the PreprocessingRecord class, which maintains a record
10 // of what occurred during preprocessing, and its helpers.
11 //
12 //===----------------------------------------------------------------------===//
13 
16 #include "clang/Basic/LLVM.h"
19 #include "clang/Basic/TokenKinds.h"
20 #include "clang/Lex/MacroInfo.h"
21 #include "clang/Lex/Token.h"
22 #include "llvm/ADT/DenseMap.h"
23 #include "llvm/ADT/StringRef.h"
24 #include "llvm/ADT/iterator_range.h"
25 #include "llvm/Support/Capacity.h"
26 #include "llvm/Support/Casting.h"
27 #include "llvm/Support/ErrorHandling.h"
28 #include <algorithm>
29 #include <cassert>
30 #include <cstddef>
31 #include <cstring>
32 #include <iterator>
33 #include <optional>
34 #include <utility>
35 #include <vector>
36 
37 using namespace clang;
38 
40  default;
41 
43  InclusionKind Kind, StringRef FileName,
44  bool InQuotes, bool ImportedModule,
46  SourceRange Range)
47  : PreprocessingDirective(InclusionDirectiveKind, Range), InQuotes(InQuotes),
48  Kind(Kind), ImportedModule(ImportedModule), File(File) {
49  char *Memory = (char *)PPRec.Allocate(FileName.size() + 1, alignof(char));
50  memcpy(Memory, FileName.data(), FileName.size());
51  Memory[FileName.size()] = 0;
52  this->FileName = StringRef(Memory, FileName.size());
53 }
54 
56 
57 /// Returns a pair of [Begin, End) iterators of preprocessed entities
58 /// that source range \p Range encompasses.
59 llvm::iterator_range<PreprocessingRecord::iterator>
61  if (Range.isInvalid())
62  return llvm::make_range(iterator(), iterator());
63 
64  if (CachedRangeQuery.Range == Range) {
65  return llvm::make_range(iterator(this, CachedRangeQuery.Result.first),
66  iterator(this, CachedRangeQuery.Result.second));
67  }
68 
69  std::pair<int, int> Res = getPreprocessedEntitiesInRangeSlow(Range);
70 
71  CachedRangeQuery.Range = Range;
72  CachedRangeQuery.Result = Res;
73 
74  return llvm::make_range(iterator(this, Res.first),
75  iterator(this, Res.second));
76 }
77 
79  SourceManager &SM) {
80  assert(FID.isValid());
81  if (!PPE)
82  return false;
83 
85  if (Loc.isInvalid())
86  return false;
87 
88  return SM.isInFileID(SM.getFileLoc(Loc), FID);
89 }
90 
91 /// Returns true if the preprocessed entity that \arg PPEI iterator
92 /// points to is coming from the file \arg FID.
93 ///
94 /// Can be used to avoid implicit deserializations of preallocated
95 /// preprocessed entities if we only care about entities of a specific file
96 /// and not from files \#included in the range given at
97 /// \see getPreprocessedEntitiesInRange.
99  if (FID.isInvalid())
100  return false;
101 
102  int Pos = std::distance(iterator(this, 0), PPEI);
103  if (Pos < 0) {
104  if (unsigned(-Pos-1) >= LoadedPreprocessedEntities.size()) {
105  assert(0 && "Out-of bounds loaded preprocessed entity");
106  return false;
107  }
108  assert(ExternalSource && "No external source to load from");
109  unsigned LoadedIndex = LoadedPreprocessedEntities.size()+Pos;
110  if (PreprocessedEntity *PPE = LoadedPreprocessedEntities[LoadedIndex])
111  return isPreprocessedEntityIfInFileID(PPE, FID, SourceMgr);
112 
113  // See if the external source can see if the entity is in the file without
114  // deserializing it.
115  if (std::optional<bool> IsInFile =
116  ExternalSource->isPreprocessedEntityInFileID(LoadedIndex, FID))
117  return *IsInFile;
118 
119  // The external source did not provide a definite answer, go and deserialize
120  // the entity to check it.
122  getLoadedPreprocessedEntity(LoadedIndex),
123  FID, SourceMgr);
124  }
125 
126  if (unsigned(Pos) >= PreprocessedEntities.size()) {
127  assert(0 && "Out-of bounds local preprocessed entity");
128  return false;
129  }
130  return isPreprocessedEntityIfInFileID(PreprocessedEntities[Pos],
131  FID, SourceMgr);
132 }
133 
134 /// Returns a pair of [Begin, End) iterators of preprocessed entities
135 /// that source range \arg R encompasses.
136 std::pair<int, int>
137 PreprocessingRecord::getPreprocessedEntitiesInRangeSlow(SourceRange Range) {
138  assert(Range.isValid());
139  assert(!SourceMgr.isBeforeInTranslationUnit(Range.getEnd(),Range.getBegin()));
140 
141  std::pair<unsigned, unsigned>
142  Local = findLocalPreprocessedEntitiesInRange(Range);
143 
144  // Check if range spans local entities.
145  if (!ExternalSource || SourceMgr.isLocalSourceLocation(Range.getBegin()))
146  return std::make_pair(Local.first, Local.second);
147 
148  std::pair<unsigned, unsigned>
149  Loaded = ExternalSource->findPreprocessedEntitiesInRange(Range);
150 
151  // Check if range spans local entities.
152  if (Loaded.first == Loaded.second)
153  return std::make_pair(Local.first, Local.second);
154 
155  unsigned TotalLoaded = LoadedPreprocessedEntities.size();
156 
157  // Check if range spans loaded entities.
158  if (Local.first == Local.second)
159  return std::make_pair(int(Loaded.first)-TotalLoaded,
160  int(Loaded.second)-TotalLoaded);
161 
162  // Range spands loaded and local entities.
163  return std::make_pair(int(Loaded.first)-TotalLoaded, Local.second);
164 }
165 
166 std::pair<unsigned, unsigned>
167 PreprocessingRecord::findLocalPreprocessedEntitiesInRange(
168  SourceRange Range) const {
169  if (Range.isInvalid())
170  return std::make_pair(0,0);
171  assert(!SourceMgr.isBeforeInTranslationUnit(Range.getEnd(),Range.getBegin()));
172 
173  unsigned Begin = findBeginLocalPreprocessedEntity(Range.getBegin());
174  unsigned End = findEndLocalPreprocessedEntity(Range.getEnd());
175  return std::make_pair(Begin, End);
176 }
177 
178 namespace {
179 
180 template <SourceLocation (SourceRange::*getRangeLoc)() const>
181 struct PPEntityComp {
182  const SourceManager &SM;
183 
184  explicit PPEntityComp(const SourceManager &SM) : SM(SM) {}
185 
186  bool operator()(PreprocessedEntity *L, PreprocessedEntity *R) const {
187  SourceLocation LHS = getLoc(L);
188  SourceLocation RHS = getLoc(R);
189  return SM.isBeforeInTranslationUnit(LHS, RHS);
190  }
191 
192  bool operator()(PreprocessedEntity *L, SourceLocation RHS) const {
193  SourceLocation LHS = getLoc(L);
194  return SM.isBeforeInTranslationUnit(LHS, RHS);
195  }
196 
197  bool operator()(SourceLocation LHS, PreprocessedEntity *R) const {
198  SourceLocation RHS = getLoc(R);
199  return SM.isBeforeInTranslationUnit(LHS, RHS);
200  }
201 
202  SourceLocation getLoc(PreprocessedEntity *PPE) const {
204  return (Range.*getRangeLoc)();
205  }
206 };
207 
208 } // namespace
209 
210 unsigned PreprocessingRecord::findBeginLocalPreprocessedEntity(
211  SourceLocation Loc) const {
212  if (SourceMgr.isLoadedSourceLocation(Loc))
213  return 0;
214 
215  size_t Count = PreprocessedEntities.size();
216  size_t Half;
217  std::vector<PreprocessedEntity *>::const_iterator
218  First = PreprocessedEntities.begin();
219  std::vector<PreprocessedEntity *>::const_iterator I;
220 
221  // Do a binary search manually instead of using std::lower_bound because
222  // The end locations of entities may be unordered (when a macro expansion
223  // is inside another macro argument), but for this case it is not important
224  // whether we get the first macro expansion or its containing macro.
225  while (Count > 0) {
226  Half = Count/2;
227  I = First;
228  std::advance(I, Half);
229  if (SourceMgr.isBeforeInTranslationUnit((*I)->getSourceRange().getEnd(),
230  Loc)){
231  First = I;
232  ++First;
233  Count = Count - Half - 1;
234  } else
235  Count = Half;
236  }
237 
238  return First - PreprocessedEntities.begin();
239 }
240 
241 unsigned
242 PreprocessingRecord::findEndLocalPreprocessedEntity(SourceLocation Loc) const {
243  if (SourceMgr.isLoadedSourceLocation(Loc))
244  return 0;
245 
246  auto I = llvm::upper_bound(PreprocessedEntities, Loc,
247  PPEntityComp<&SourceRange::getBegin>(SourceMgr));
248  return I - PreprocessedEntities.begin();
249 }
250 
251 PreprocessingRecord::PPEntityID
253  assert(Entity);
254  SourceLocation BeginLoc = Entity->getSourceRange().getBegin();
255 
256  if (isa<MacroDefinitionRecord>(Entity)) {
257  assert((PreprocessedEntities.empty() ||
258  !SourceMgr.isBeforeInTranslationUnit(
259  BeginLoc,
260  PreprocessedEntities.back()->getSourceRange().getBegin())) &&
261  "a macro definition was encountered out-of-order");
262  PreprocessedEntities.push_back(Entity);
263  return getPPEntityID(PreprocessedEntities.size()-1, /*isLoaded=*/false);
264  }
265 
266  // Check normal case, this entity begin location is after the previous one.
267  if (PreprocessedEntities.empty() ||
268  !SourceMgr.isBeforeInTranslationUnit(BeginLoc,
269  PreprocessedEntities.back()->getSourceRange().getBegin())) {
270  PreprocessedEntities.push_back(Entity);
271  return getPPEntityID(PreprocessedEntities.size()-1, /*isLoaded=*/false);
272  }
273 
274  // The entity's location is not after the previous one; this can happen with
275  // include directives that form the filename using macros, e.g:
276  // "#include MACRO(STUFF)"
277  // or with macro expansions inside macro arguments where the arguments are
278  // not expanded in the same order as listed, e.g:
279  // \code
280  // #define M1 1
281  // #define M2 2
282  // #define FM(x,y) y x
283  // FM(M1, M2)
284  // \endcode
285 
286  using pp_iter = std::vector<PreprocessedEntity *>::iterator;
287 
288  // Usually there are few macro expansions when defining the filename, do a
289  // linear search for a few entities.
290  unsigned count = 0;
291  for (pp_iter RI = PreprocessedEntities.end(),
292  Begin = PreprocessedEntities.begin();
293  RI != Begin && count < 4; --RI, ++count) {
294  pp_iter I = RI;
295  --I;
296  if (!SourceMgr.isBeforeInTranslationUnit(BeginLoc,
297  (*I)->getSourceRange().getBegin())) {
298  pp_iter insertI = PreprocessedEntities.insert(RI, Entity);
299  return getPPEntityID(insertI - PreprocessedEntities.begin(),
300  /*isLoaded=*/false);
301  }
302  }
303 
304  // Linear search unsuccessful. Do a binary search.
305  pp_iter I =
306  llvm::upper_bound(PreprocessedEntities, BeginLoc,
307  PPEntityComp<&SourceRange::getBegin>(SourceMgr));
308  pp_iter insertI = PreprocessedEntities.insert(I, Entity);
309  return getPPEntityID(insertI - PreprocessedEntities.begin(),
310  /*isLoaded=*/false);
311 }
312 
315  assert(!ExternalSource &&
316  "Preprocessing record already has an external source");
317  ExternalSource = &Source;
318 }
319 
320 unsigned PreprocessingRecord::allocateLoadedEntities(unsigned NumEntities) {
321  unsigned Result = LoadedPreprocessedEntities.size();
322  LoadedPreprocessedEntities.resize(LoadedPreprocessedEntities.size()
323  + NumEntities);
324  return Result;
325 }
326 
327 unsigned PreprocessingRecord::allocateSkippedRanges(unsigned NumRanges) {
328  unsigned Result = SkippedRanges.size();
329  SkippedRanges.resize(SkippedRanges.size() + NumRanges);
330  SkippedRangesAllLoaded = false;
331  return Result;
332 }
333 
334 void PreprocessingRecord::ensureSkippedRangesLoaded() {
335  if (SkippedRangesAllLoaded || !ExternalSource)
336  return;
337  for (unsigned Index = 0; Index != SkippedRanges.size(); ++Index) {
338  if (SkippedRanges[Index].isInvalid())
339  SkippedRanges[Index] = ExternalSource->ReadSkippedRange(Index);
340  }
341  SkippedRangesAllLoaded = true;
342 }
343 
344 void PreprocessingRecord::RegisterMacroDefinition(MacroInfo *Macro,
345  MacroDefinitionRecord *Def) {
346  MacroDefinitions[Macro] = Def;
347 }
348 
349 /// Retrieve the preprocessed entity at the given ID.
350 PreprocessedEntity *PreprocessingRecord::getPreprocessedEntity(PPEntityID PPID){
351  if (PPID.ID < 0) {
352  unsigned Index = -PPID.ID - 1;
353  assert(Index < LoadedPreprocessedEntities.size() &&
354  "Out-of bounds loaded preprocessed entity");
355  return getLoadedPreprocessedEntity(Index);
356  }
357 
358  if (PPID.ID == 0)
359  return nullptr;
360  unsigned Index = PPID.ID - 1;
361  assert(Index < PreprocessedEntities.size() &&
362  "Out-of bounds local preprocessed entity");
363  return PreprocessedEntities[Index];
364 }
365 
366 /// Retrieve the loaded preprocessed entity at the given index.
368 PreprocessingRecord::getLoadedPreprocessedEntity(unsigned Index) {
369  assert(Index < LoadedPreprocessedEntities.size() &&
370  "Out-of bounds loaded preprocessed entity");
371  assert(ExternalSource && "No external source to load from");
372  PreprocessedEntity *&Entity = LoadedPreprocessedEntities[Index];
373  if (!Entity) {
374  Entity = ExternalSource->ReadPreprocessedEntity(Index);
375  if (!Entity) // Failed to load.
376  Entity = new (*this)
378  }
379  return Entity;
380 }
381 
384  return MacroDefinitions.lookup(MI);
385 }
386 
387 void PreprocessingRecord::addMacroExpansion(const Token &Id,
388  const MacroInfo *MI,
389  SourceRange Range) {
390  // We don't record nested macro expansions.
391  if (Id.getLocation().isMacroID())
392  return;
393 
394  if (MI->isBuiltinMacro())
395  addPreprocessedEntity(new (*this)
396  MacroExpansion(Id.getIdentifierInfo(), Range));
397  else if (MacroDefinitionRecord *Def = findMacroDefinition(MI))
398  addPreprocessedEntity(new (*this) MacroExpansion(Def, Range));
399 }
400 
401 void PreprocessingRecord::Ifdef(SourceLocation Loc, const Token &MacroNameTok,
402  const MacroDefinition &MD) {
403  // This is not actually a macro expansion but record it as a macro reference.
404  if (MD)
405  addMacroExpansion(MacroNameTok, MD.getMacroInfo(),
406  MacroNameTok.getLocation());
407 }
408 
409 void PreprocessingRecord::Elifdef(SourceLocation Loc, const Token &MacroNameTok,
410  const MacroDefinition &MD) {
411  // This is not actually a macro expansion but record it as a macro reference.
412  if (MD)
413  addMacroExpansion(MacroNameTok, MD.getMacroInfo(),
414  MacroNameTok.getLocation());
415 }
416 
417 void PreprocessingRecord::Ifndef(SourceLocation Loc, const Token &MacroNameTok,
418  const MacroDefinition &MD) {
419  // This is not actually a macro expansion but record it as a macro reference.
420  if (MD)
421  addMacroExpansion(MacroNameTok, MD.getMacroInfo(),
422  MacroNameTok.getLocation());
423 }
424 
425 void PreprocessingRecord::Elifndef(SourceLocation Loc,
426  const Token &MacroNameTok,
427  const MacroDefinition &MD) {
428  // This is not actually a macro expansion but record it as a macro reference.
429  if (MD)
430  addMacroExpansion(MacroNameTok, MD.getMacroInfo(),
431  MacroNameTok.getLocation());
432 }
433 
434 void PreprocessingRecord::Defined(const Token &MacroNameTok,
435  const MacroDefinition &MD,
436  SourceRange Range) {
437  // This is not actually a macro expansion but record it as a macro reference.
438  if (MD)
439  addMacroExpansion(MacroNameTok, MD.getMacroInfo(),
440  MacroNameTok.getLocation());
441 }
442 
443 void PreprocessingRecord::SourceRangeSkipped(SourceRange Range,
444  SourceLocation EndifLoc) {
445  assert(Range.isValid());
446  SkippedRanges.emplace_back(Range.getBegin(), EndifLoc);
447 }
448 
449 void PreprocessingRecord::MacroExpands(const Token &Id,
450  const MacroDefinition &MD,
451  SourceRange Range,
452  const MacroArgs *Args) {
453  addMacroExpansion(Id, MD.getMacroInfo(), Range);
454 }
455 
456 void PreprocessingRecord::MacroDefined(const Token &Id,
457  const MacroDirective *MD) {
458  const MacroInfo *MI = MD->getMacroInfo();
460  MacroDefinitionRecord *Def =
461  new (*this) MacroDefinitionRecord(Id.getIdentifierInfo(), R);
463  MacroDefinitions[MI] = Def;
464 }
465 
466 void PreprocessingRecord::MacroUndefined(const Token &Id,
467  const MacroDefinition &MD,
468  const MacroDirective *Undef) {
469  MD.forAllDefinitions([&](MacroInfo *MI) { MacroDefinitions.erase(MI); });
470 }
471 
472 void PreprocessingRecord::InclusionDirective(
473  SourceLocation HashLoc, const Token &IncludeTok, StringRef FileName,
474  bool IsAngled, CharSourceRange FilenameRange, OptionalFileEntryRef File,
475  StringRef SearchPath, StringRef RelativePath, const Module *SuggestedModule,
476  bool ModuleImported, SrcMgr::CharacteristicKind FileType) {
478 
479  switch (IncludeTok.getIdentifierInfo()->getPPKeywordID()) {
480  case tok::pp_include:
482  break;
483 
484  case tok::pp_import:
486  break;
487 
490  break;
491 
494  break;
495 
496  default:
497  llvm_unreachable("Unknown include directive kind");
498  }
499 
500  SourceLocation EndLoc;
501  if (!IsAngled) {
502  EndLoc = FilenameRange.getBegin();
503  } else {
504  EndLoc = FilenameRange.getEnd();
505  if (FilenameRange.isCharRange())
506  EndLoc = EndLoc.getLocWithOffset(-1); // the InclusionDirective expects
507  // a token range.
508  }
510  *this, Kind, FileName, !IsAngled, ModuleImported, File,
511  SourceRange(HashLoc, EndLoc));
513 }
514 
516  return BumpAlloc.getTotalMemory()
517  + llvm::capacity_in_bytes(MacroDefinitions)
518  + llvm::capacity_in_bytes(PreprocessedEntities)
519  + llvm::capacity_in_bytes(LoadedPreprocessedEntities)
520  + llvm::capacity_in_bytes(SkippedRanges);
521 }
int Id
Definition: ASTDiff.cpp:190
static char ID
Definition: Arena.cpp:183
#define SM(sm)
Definition: Cuda.cpp:83
Defines the clang::IdentifierInfo, clang::IdentifierTable, and clang::Selector interfaces.
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.
llvm::MachO::FileType FileType
Definition: MachO.h:45
Defines the clang::MacroInfo and clang::MacroDirective classes.
static ParseState advance(ParseState S, size_t N)
Definition: Parsing.cpp:144
static bool isPreprocessedEntityIfInFileID(PreprocessedEntity *PPE, FileID FID, SourceManager &SM)
SourceRange Range
Definition: SemaObjC.cpp:754
SourceLocation Loc
Definition: SemaObjC.cpp:755
Defines the clang::SourceLocation class and associated facilities.
static bool isInvalid(LocType Loc, bool *Invalid)
Defines the SourceManager interface.
Defines the clang::TokenKind enum and support functions.
SourceLocation End
SourceLocation Begin
__DEVICE__ void * memcpy(void *__a, const void *__b, size_t __c)
Represents a character-granular source range.
SourceLocation getEnd() const
SourceLocation getBegin() const
An abstract class that should be subclassed by any external source of preprocessing record entries.
An opaque identifier used by SourceManager which refers to a source file (MemoryBuffer) along with it...
bool isValid() const
bool isInvalid() const
tok::PPKeywordKind getPPKeywordID() const
Return the preprocessor keyword ID for this identifier.
Record the location of an inclusion directive, such as an #include or #import statement.
InclusionKind
The kind of inclusion directives known to the preprocessor.
@ IncludeMacros
A Clang #__include_macros directive.
@ Import
An Objective-C #import directive.
@ IncludeNext
A GNU #include_next directive.
@ Include
An #include directive.
InclusionDirective(PreprocessingRecord &PPRec, InclusionKind Kind, StringRef FileName, bool InQuotes, bool ImportedModule, OptionalFileEntryRef File, SourceRange Range)
MacroArgs - An instance of this class captures information about the formal arguments specified to a ...
Definition: MacroArgs.h:30
Record the location of a macro definition.
A description of the current definition of a macro.
Definition: MacroInfo.h:590
MacroInfo * getMacroInfo() const
Get the MacroInfo that should be used for this definition.
Definition: MacroInfo.h:606
void forAllDefinitions(Fn F) const
Definition: MacroInfo.h:626
Encapsulates changes to the "macros namespace" (the location where the macro name became active,...
Definition: MacroInfo.h:313
const MacroInfo * getMacroInfo() const
Definition: MacroInfo.h:416
Records the location of a macro expansion.
Encapsulates the data about a macro definition (e.g.
Definition: MacroInfo.h:39
SourceLocation getDefinitionEndLoc() const
Return the location of the last token in the macro.
Definition: MacroInfo.h:131
bool isBuiltinMacro() const
Return true if this macro requires processing before expansion.
Definition: MacroInfo.h:217
SourceLocation getDefinitionLoc() const
Return the location that the macro was defined at.
Definition: MacroInfo.h:125
Describes a module or submodule.
Definition: Module.h:105
Base class that describes a preprocessed entity, which may be a preprocessor directive or macro expan...
@ InvalidKind
Indicates a problem trying to load the preprocessed entity.
SourceRange getSourceRange() const LLVM_READONLY
Retrieve the source range that covers this entire preprocessed entity.
Records the presence of a preprocessor directive.
Iteration over the preprocessed entities.
A record of the steps taken while preprocessing a source file, including the various preprocessing di...
PreprocessingRecord(SourceManager &SM)
Construct a new preprocessing record.
llvm::iterator_range< iterator > getPreprocessedEntitiesInRange(SourceRange R)
Returns a range of preprocessed entities that source range R encompasses.
MacroDefinitionRecord * findMacroDefinition(const MacroInfo *MI)
Retrieve the macro definition that corresponds to the given MacroInfo.
PPEntityID addPreprocessedEntity(PreprocessedEntity *Entity)
Add a new preprocessed entity to this record.
bool isEntityInFileID(iterator PPEI, FileID FID)
Returns true if the preprocessed entity that PPEI iterator points to is coming from the file FID.
std::pair< int, int > Result
void SetExternalSource(ExternalPreprocessingRecordSource &Source)
Set the external source for preprocessed entities.
void * Allocate(unsigned Size, unsigned Align=8)
Allocate memory in the preprocessing record.
Encodes a location in the source.
SourceLocation getLocWithOffset(IntTy Offset) const
Return a source location with the specified offset from this SourceLocation.
This class handles loading and caching of source files into memory.
bool isLocalSourceLocation(SourceLocation Loc) const
Returns true if Loc did not come from a PCH/Module.
bool isLoadedSourceLocation(SourceLocation Loc) const
Returns true if Loc came from a PCH/Module.
bool isBeforeInTranslationUnit(SourceLocation LHS, SourceLocation RHS) const
Determines the order of 2 source locations in the translation unit.
A trivial tuple used to represent a source range.
bool isInvalid() const
SourceLocation getEnd() const
SourceLocation getBegin() const
bool isValid() const
Token - This structure provides full information about a lexed token.
Definition: Token.h:36
SourceLocation getLocation() const
Return a source location identifier for the specified offset in the current file.
Definition: Token.h:132
IdentifierInfo * getIdentifierInfo() const
Definition: Token.h:187
CharacteristicKind
Indicates whether a file or directory holds normal user code, system code, or system code which is im...
Definition: SourceManager.h:81
The JSON file list parser is used to communicate input to InstallAPI.
float __ovld __cnfn distance(float, float)
Returns the distance between p0 and p1.