blob: 440e4780ca062cda97bf95ddfd000cc7fb11c448 [file] [log] [blame]
Douglas Gregor065f8d12010-03-18 17:52:52 +00001//===--- PreprocessingRecord.cpp - Record of Preprocessing ------*- 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 implements the PreprocessingRecord class, which maintains a record
11// of what occurred during preprocessing, and its helpers.
12//
13//===----------------------------------------------------------------------===//
14#include "clang/Lex/PreprocessingRecord.h"
15#include "clang/Lex/MacroInfo.h"
16#include "clang/Lex/Token.h"
Douglas Gregor796d76a2010-10-20 22:00:55 +000017#include "llvm/Support/ErrorHandling.h"
Ted Kremenekf1c38812011-07-27 18:41:20 +000018#include "llvm/Support/Capacity.h"
Douglas Gregor065f8d12010-03-18 17:52:52 +000019
20using namespace clang;
21
Douglas Gregoraae92242010-03-19 21:51:54 +000022ExternalPreprocessingRecordSource::~ExternalPreprocessingRecordSource() { }
23
Douglas Gregorf09b6c92010-11-01 15:03:47 +000024
25InclusionDirective::InclusionDirective(PreprocessingRecord &PPRec,
26 InclusionKind Kind,
Chris Lattner0e62c1c2011-07-23 10:55:15 +000027 StringRef FileName,
Douglas Gregorf09b6c92010-11-01 15:03:47 +000028 bool InQuotes, const FileEntry *File,
29 SourceRange Range)
30 : PreprocessingDirective(InclusionDirectiveKind, Range),
31 InQuotes(InQuotes), Kind(Kind), File(File)
32{
33 char *Memory
34 = (char*)PPRec.Allocate(FileName.size() + 1, llvm::alignOf<char>());
35 memcpy(Memory, FileName.data(), FileName.size());
36 Memory[FileName.size()] = 0;
Chris Lattner0e62c1c2011-07-23 10:55:15 +000037 this->FileName = StringRef(Memory, FileName.size());
Douglas Gregorf09b6c92010-11-01 15:03:47 +000038}
39
Argyrios Kyrtzidis647dcd82012-03-05 05:48:17 +000040PreprocessingRecord::PreprocessingRecord(SourceManager &SM,
41 bool RecordConditionalDirectives)
42 : SourceMgr(SM),
43 RecordCondDirectives(RecordConditionalDirectives), CondDirectiveNextIdx(0),
44 ExternalSource(0)
Douglas Gregoraae92242010-03-19 21:51:54 +000045{
Argyrios Kyrtzidis647dcd82012-03-05 05:48:17 +000046 if (RecordCondDirectives)
47 CondDirectiveStack.push_back(CondDirectiveNextIdx++);
Douglas Gregoraae92242010-03-19 21:51:54 +000048}
49
Argyrios Kyrtzidis64f63812011-09-19 20:40:25 +000050/// \brief Returns a pair of [Begin, End) iterators of preprocessed entities
51/// that source range \arg R encompasses.
52std::pair<PreprocessingRecord::iterator, PreprocessingRecord::iterator>
53PreprocessingRecord::getPreprocessedEntitiesInRange(SourceRange Range) {
54 if (Range.isInvalid())
Argyrios Kyrtzidis429ec022011-10-25 00:29:50 +000055 return std::make_pair(iterator(), iterator());
Argyrios Kyrtzidis64f63812011-09-19 20:40:25 +000056
Argyrios Kyrtzidis429ec022011-10-25 00:29:50 +000057 if (CachedRangeQuery.Range == Range) {
58 return std::make_pair(iterator(this, CachedRangeQuery.Result.first),
59 iterator(this, CachedRangeQuery.Result.second));
60 }
61
62 std::pair<PPEntityID, PPEntityID>
63 Res = getPreprocessedEntitiesInRangeSlow(Range);
64
65 CachedRangeQuery.Range = Range;
66 CachedRangeQuery.Result = Res;
67
68 return std::make_pair(iterator(this, Res.first), iterator(this, Res.second));
69}
70
71static bool isPreprocessedEntityIfInFileID(PreprocessedEntity *PPE, FileID FID,
72 SourceManager &SM) {
73 assert(!FID.isInvalid());
74 if (!PPE)
75 return false;
76
77 SourceLocation Loc = PPE->getSourceRange().getBegin();
78 if (Loc.isInvalid())
79 return false;
80
81 if (SM.isInFileID(SM.getFileLoc(Loc), FID))
82 return true;
83 else
84 return false;
85}
86
87/// \brief Returns true if the preprocessed entity that \arg PPEI iterator
88/// points to is coming from the file \arg FID.
89///
90/// Can be used to avoid implicit deserializations of preallocated
91/// preprocessed entities if we only care about entities of a specific file
92/// and not from files #included in the range given at
93/// \see getPreprocessedEntitiesInRange.
94bool PreprocessingRecord::isEntityInFileID(iterator PPEI, FileID FID) {
95 if (FID.isInvalid())
96 return false;
97
98 PPEntityID PPID = PPEI.Position;
99 if (PPID < 0) {
100 assert(unsigned(-PPID-1) < LoadedPreprocessedEntities.size() &&
101 "Out-of bounds loaded preprocessed entity");
102 assert(ExternalSource && "No external source to load from");
103 unsigned LoadedIndex = LoadedPreprocessedEntities.size()+PPID;
104 if (PreprocessedEntity *PPE = LoadedPreprocessedEntities[LoadedIndex])
105 return isPreprocessedEntityIfInFileID(PPE, FID, SourceMgr);
106
107 // See if the external source can see if the entity is in the file without
108 // deserializing it.
109 llvm::Optional<bool>
110 IsInFile = ExternalSource->isPreprocessedEntityInFileID(LoadedIndex, FID);
111 if (IsInFile.hasValue())
112 return IsInFile.getValue();
113
114 // The external source did not provide a definite answer, go and deserialize
115 // the entity to check it.
116 return isPreprocessedEntityIfInFileID(
117 getLoadedPreprocessedEntity(LoadedIndex),
118 FID, SourceMgr);
119 }
120
121 assert(unsigned(PPID) < PreprocessedEntities.size() &&
122 "Out-of bounds local preprocessed entity");
123 return isPreprocessedEntityIfInFileID(PreprocessedEntities[PPID],
124 FID, SourceMgr);
125}
126
127/// \brief Returns a pair of [Begin, End) iterators of preprocessed entities
128/// that source range \arg R encompasses.
129std::pair<PreprocessingRecord::PPEntityID, PreprocessingRecord::PPEntityID>
130PreprocessingRecord::getPreprocessedEntitiesInRangeSlow(SourceRange Range) {
131 assert(Range.isValid());
132 assert(!SourceMgr.isBeforeInTranslationUnit(Range.getEnd(),Range.getBegin()));
133
Argyrios Kyrtzidis64f63812011-09-19 20:40:25 +0000134 std::pair<unsigned, unsigned>
135 Local = findLocalPreprocessedEntitiesInRange(Range);
Argyrios Kyrtzidis429ec022011-10-25 00:29:50 +0000136
Argyrios Kyrtzidis64f63812011-09-19 20:40:25 +0000137 // Check if range spans local entities.
138 if (!ExternalSource || SourceMgr.isLocalSourceLocation(Range.getBegin()))
Argyrios Kyrtzidis429ec022011-10-25 00:29:50 +0000139 return std::make_pair(Local.first, Local.second);
140
Argyrios Kyrtzidis64f63812011-09-19 20:40:25 +0000141 std::pair<unsigned, unsigned>
142 Loaded = ExternalSource->findPreprocessedEntitiesInRange(Range);
Argyrios Kyrtzidis429ec022011-10-25 00:29:50 +0000143
Argyrios Kyrtzidis64f63812011-09-19 20:40:25 +0000144 // Check if range spans local entities.
145 if (Loaded.first == Loaded.second)
Argyrios Kyrtzidis429ec022011-10-25 00:29:50 +0000146 return std::make_pair(Local.first, Local.second);
147
Argyrios Kyrtzidis64f63812011-09-19 20:40:25 +0000148 unsigned TotalLoaded = LoadedPreprocessedEntities.size();
Argyrios Kyrtzidis429ec022011-10-25 00:29:50 +0000149
Argyrios Kyrtzidis64f63812011-09-19 20:40:25 +0000150 // Check if range spans loaded entities.
151 if (Local.first == Local.second)
Argyrios Kyrtzidis429ec022011-10-25 00:29:50 +0000152 return std::make_pair(int(Loaded.first)-TotalLoaded,
153 int(Loaded.second)-TotalLoaded);
154
Argyrios Kyrtzidis64f63812011-09-19 20:40:25 +0000155 // Range spands loaded and local entities.
Argyrios Kyrtzidis429ec022011-10-25 00:29:50 +0000156 return std::make_pair(int(Loaded.first)-TotalLoaded, Local.second);
Argyrios Kyrtzidis64f63812011-09-19 20:40:25 +0000157}
158
159std::pair<unsigned, unsigned>
160PreprocessingRecord::findLocalPreprocessedEntitiesInRange(
161 SourceRange Range) const {
162 if (Range.isInvalid())
163 return std::make_pair(0,0);
164 assert(!SourceMgr.isBeforeInTranslationUnit(Range.getEnd(),Range.getBegin()));
165
166 unsigned Begin = findBeginLocalPreprocessedEntity(Range.getBegin());
167 unsigned End = findEndLocalPreprocessedEntity(Range.getEnd());
168 return std::make_pair(Begin, End);
169}
170
171namespace {
172
173template <SourceLocation (SourceRange::*getRangeLoc)() const>
174struct PPEntityComp {
175 const SourceManager &SM;
176
177 explicit PPEntityComp(const SourceManager &SM) : SM(SM) { }
178
Benjamin Kramer2e9d9cf2011-09-21 16:58:20 +0000179 bool operator()(PreprocessedEntity *L, PreprocessedEntity *R) const {
180 SourceLocation LHS = getLoc(L);
181 SourceLocation RHS = getLoc(R);
182 return SM.isBeforeInTranslationUnit(LHS, RHS);
183 }
184
185 bool operator()(PreprocessedEntity *L, SourceLocation RHS) const {
Argyrios Kyrtzidis64f63812011-09-19 20:40:25 +0000186 SourceLocation LHS = getLoc(L);
187 return SM.isBeforeInTranslationUnit(LHS, RHS);
188 }
189
Benjamin Kramer2e9d9cf2011-09-21 16:58:20 +0000190 bool operator()(SourceLocation LHS, PreprocessedEntity *R) const {
Argyrios Kyrtzidis64f63812011-09-19 20:40:25 +0000191 SourceLocation RHS = getLoc(R);
192 return SM.isBeforeInTranslationUnit(LHS, RHS);
193 }
194
195 SourceLocation getLoc(PreprocessedEntity *PPE) const {
Argyrios Kyrtzidisa35c4442011-09-19 22:02:08 +0000196 SourceRange Range = PPE->getSourceRange();
197 return (Range.*getRangeLoc)();
Argyrios Kyrtzidis64f63812011-09-19 20:40:25 +0000198 }
199};
200
201}
202
203unsigned PreprocessingRecord::findBeginLocalPreprocessedEntity(
204 SourceLocation Loc) const {
205 if (SourceMgr.isLoadedSourceLocation(Loc))
206 return 0;
207
Argyrios Kyrtzidise523e382011-09-22 21:17:02 +0000208 size_t Count = PreprocessedEntities.size();
209 size_t Half;
Argyrios Kyrtzidis64f63812011-09-19 20:40:25 +0000210 std::vector<PreprocessedEntity *>::const_iterator
Argyrios Kyrtzidise523e382011-09-22 21:17:02 +0000211 First = PreprocessedEntities.begin();
212 std::vector<PreprocessedEntity *>::const_iterator I;
213
214 // Do a binary search manually instead of using std::lower_bound because
215 // The end locations of entities may be unordered (when a macro expansion
216 // is inside another macro argument), but for this case it is not important
217 // whether we get the first macro expansion or its containing macro.
218 while (Count > 0) {
219 Half = Count/2;
220 I = First;
221 std::advance(I, Half);
222 if (SourceMgr.isBeforeInTranslationUnit((*I)->getSourceRange().getEnd(),
223 Loc)){
224 First = I;
225 ++First;
226 Count = Count - Half - 1;
227 } else
228 Count = Half;
229 }
230
231 return First - PreprocessedEntities.begin();
Argyrios Kyrtzidis64f63812011-09-19 20:40:25 +0000232}
233
234unsigned PreprocessingRecord::findEndLocalPreprocessedEntity(
235 SourceLocation Loc) const {
236 if (SourceMgr.isLoadedSourceLocation(Loc))
237 return 0;
238
239 std::vector<PreprocessedEntity *>::const_iterator
240 I = std::upper_bound(PreprocessedEntities.begin(),
241 PreprocessedEntities.end(),
242 Loc,
243 PPEntityComp<&SourceRange::getBegin>(SourceMgr));
244 return I - PreprocessedEntities.begin();
245}
246
Douglas Gregor065f8d12010-03-18 17:52:52 +0000247void PreprocessingRecord::addPreprocessedEntity(PreprocessedEntity *Entity) {
Argyrios Kyrtzidis45e8cf52011-09-20 23:27:33 +0000248 assert(Entity);
Argyrios Kyrtzidisf37d0a62011-10-12 17:36:33 +0000249 SourceLocation BeginLoc = Entity->getSourceRange().getBegin();
250
251 // Check normal case, this entity begin location is after the previous one.
252 if (PreprocessedEntities.empty() ||
253 !SourceMgr.isBeforeInTranslationUnit(BeginLoc,
254 PreprocessedEntities.back()->getSourceRange().getBegin())) {
255 PreprocessedEntities.push_back(Entity);
256 return;
257 }
258
259 // The entity's location is not after the previous one; this can happen rarely
260 // e.g. with "#include MACRO".
261 // Iterate the entities vector in reverse until we find the right place to
262 // insert the new entity.
263 for (std::vector<PreprocessedEntity *>::iterator
264 RI = PreprocessedEntities.end(), Begin = PreprocessedEntities.begin();
265 RI != Begin; --RI) {
266 std::vector<PreprocessedEntity *>::iterator I = RI;
267 --I;
268 if (!SourceMgr.isBeforeInTranslationUnit(BeginLoc,
269 (*I)->getSourceRange().getBegin())) {
270 PreprocessedEntities.insert(RI, Entity);
271 return;
272 }
273 }
Douglas Gregor065f8d12010-03-18 17:52:52 +0000274}
275
Douglas Gregoraae92242010-03-19 21:51:54 +0000276void PreprocessingRecord::SetExternalSource(
Douglas Gregor4a9c39a2011-07-21 00:47:40 +0000277 ExternalPreprocessingRecordSource &Source) {
Douglas Gregoraae92242010-03-19 21:51:54 +0000278 assert(!ExternalSource &&
279 "Preprocessing record already has an external source");
280 ExternalSource = &Source;
Douglas Gregoraae92242010-03-19 21:51:54 +0000281}
282
Douglas Gregor4a9c39a2011-07-21 00:47:40 +0000283unsigned PreprocessingRecord::allocateLoadedEntities(unsigned NumEntities) {
284 unsigned Result = LoadedPreprocessedEntities.size();
285 LoadedPreprocessedEntities.resize(LoadedPreprocessedEntities.size()
286 + NumEntities);
287 return Result;
288}
289
Argyrios Kyrtzidis03c40c52011-09-15 18:02:56 +0000290void PreprocessingRecord::RegisterMacroDefinition(MacroInfo *Macro,
291 PPEntityID PPID) {
292 MacroDefinitions[Macro] = PPID;
Douglas Gregoraae92242010-03-19 21:51:54 +0000293}
294
Argyrios Kyrtzidis03c40c52011-09-15 18:02:56 +0000295/// \brief Retrieve the preprocessed entity at the given ID.
296PreprocessedEntity *PreprocessingRecord::getPreprocessedEntity(PPEntityID PPID){
297 if (PPID < 0) {
298 assert(unsigned(-PPID-1) < LoadedPreprocessedEntities.size() &&
299 "Out-of bounds loaded preprocessed entity");
300 return getLoadedPreprocessedEntity(LoadedPreprocessedEntities.size()+PPID);
301 }
302 assert(unsigned(PPID) < PreprocessedEntities.size() &&
303 "Out-of bounds local preprocessed entity");
304 return PreprocessedEntities[PPID];
305}
306
307/// \brief Retrieve the loaded preprocessed entity at the given index.
308PreprocessedEntity *
309PreprocessingRecord::getLoadedPreprocessedEntity(unsigned Index) {
310 assert(Index < LoadedPreprocessedEntities.size() &&
311 "Out-of bounds loaded preprocessed entity");
312 assert(ExternalSource && "No external source to load from");
313 PreprocessedEntity *&Entity = LoadedPreprocessedEntities[Index];
314 if (!Entity) {
315 Entity = ExternalSource->ReadPreprocessedEntity(Index);
316 if (!Entity) // Failed to load.
317 Entity = new (*this)
318 PreprocessedEntity(PreprocessedEntity::InvalidKind, SourceRange());
319 }
320 return Entity;
Douglas Gregoraae92242010-03-19 21:51:54 +0000321}
322
Douglas Gregor8aaca672010-03-19 21:58:23 +0000323MacroDefinition *PreprocessingRecord::findMacroDefinition(const MacroInfo *MI) {
Argyrios Kyrtzidis03c40c52011-09-15 18:02:56 +0000324 llvm::DenseMap<const MacroInfo *, PPEntityID>::iterator Pos
Douglas Gregor7dc87222010-03-19 17:12:43 +0000325 = MacroDefinitions.find(MI);
326 if (Pos == MacroDefinitions.end())
327 return 0;
328
Argyrios Kyrtzidis03c40c52011-09-15 18:02:56 +0000329 PreprocessedEntity *Entity = getPreprocessedEntity(Pos->second);
330 if (Entity->isInvalid())
331 return 0;
332 return cast<MacroDefinition>(Entity);
Douglas Gregor7dc87222010-03-19 17:12:43 +0000333}
334
Argyrios Kyrtzidis85a14bb2011-08-18 01:05:45 +0000335void PreprocessingRecord::MacroExpands(const Token &Id, const MacroInfo* MI,
336 SourceRange Range) {
Argyrios Kyrtzidis335c5a42012-02-25 02:41:16 +0000337 // We don't record nested macro expansions.
338 if (Id.getLocation().isMacroID())
Douglas Gregor998caea2011-05-06 16:33:08 +0000339 return;
340
Argyrios Kyrtzidis80f78b92011-09-08 17:18:41 +0000341 if (MI->isBuiltinMacro())
Argyrios Kyrtzidis64f63812011-09-19 20:40:25 +0000342 addPreprocessedEntity(
Argyrios Kyrtzidis80f78b92011-09-08 17:18:41 +0000343 new (*this) MacroExpansion(Id.getIdentifierInfo(),Range));
344 else if (MacroDefinition *Def = findMacroDefinition(MI))
Argyrios Kyrtzidis64f63812011-09-19 20:40:25 +0000345 addPreprocessedEntity(
Argyrios Kyrtzidis80f78b92011-09-08 17:18:41 +0000346 new (*this) MacroExpansion(Def, Range));
Douglas Gregor7dc87222010-03-19 17:12:43 +0000347}
348
Craig Silverstein1a9ca212010-11-19 21:33:15 +0000349void PreprocessingRecord::MacroDefined(const Token &Id,
Douglas Gregor7dc87222010-03-19 17:12:43 +0000350 const MacroInfo *MI) {
351 SourceRange R(MI->getDefinitionLoc(), MI->getDefinitionEndLoc());
352 MacroDefinition *Def
Argyrios Kyrtzidis0d48fb82011-09-20 22:14:48 +0000353 = new (*this) MacroDefinition(Id.getIdentifierInfo(), R);
Argyrios Kyrtzidis64f63812011-09-19 20:40:25 +0000354 addPreprocessedEntity(Def);
Argyrios Kyrtzidis03c40c52011-09-15 18:02:56 +0000355 MacroDefinitions[MI] = getPPEntityID(PreprocessedEntities.size()-1,
356 /*isLoaded=*/false);
Douglas Gregor7dc87222010-03-19 17:12:43 +0000357}
Douglas Gregoraae92242010-03-19 21:51:54 +0000358
Craig Silverstein1a9ca212010-11-19 21:33:15 +0000359void PreprocessingRecord::MacroUndefined(const Token &Id,
Douglas Gregor8aaca672010-03-19 21:58:23 +0000360 const MacroInfo *MI) {
Benjamin Kramere894e092012-03-24 18:22:12 +0000361 MacroDefinitions.erase(MI);
Douglas Gregor8aaca672010-03-19 21:58:23 +0000362}
363
Chandler Carruth3cc331a2011-03-16 18:34:36 +0000364void PreprocessingRecord::InclusionDirective(
365 SourceLocation HashLoc,
366 const clang::Token &IncludeTok,
Chris Lattner0e62c1c2011-07-23 10:55:15 +0000367 StringRef FileName,
Chandler Carruth3cc331a2011-03-16 18:34:36 +0000368 bool IsAngled,
369 const FileEntry *File,
370 clang::SourceLocation EndLoc,
Chris Lattner0e62c1c2011-07-23 10:55:15 +0000371 StringRef SearchPath,
372 StringRef RelativePath) {
Douglas Gregor796d76a2010-10-20 22:00:55 +0000373 InclusionDirective::InclusionKind Kind = InclusionDirective::Include;
374
375 switch (IncludeTok.getIdentifierInfo()->getPPKeywordID()) {
376 case tok::pp_include:
377 Kind = InclusionDirective::Include;
378 break;
379
380 case tok::pp_import:
381 Kind = InclusionDirective::Import;
382 break;
383
384 case tok::pp_include_next:
385 Kind = InclusionDirective::IncludeNext;
386 break;
387
388 case tok::pp___include_macros:
389 Kind = InclusionDirective::IncludeMacros;
390 break;
391
392 default:
393 llvm_unreachable("Unknown include directive kind");
Douglas Gregor796d76a2010-10-20 22:00:55 +0000394 }
395
396 clang::InclusionDirective *ID
Douglas Gregorf09b6c92010-11-01 15:03:47 +0000397 = new (*this) clang::InclusionDirective(*this, Kind, FileName, !IsAngled,
398 File, SourceRange(HashLoc, EndLoc));
Argyrios Kyrtzidis64f63812011-09-19 20:40:25 +0000399 addPreprocessedEntity(ID);
Douglas Gregor796d76a2010-10-20 22:00:55 +0000400}
Ted Kremenek182543a2011-07-26 21:17:24 +0000401
Argyrios Kyrtzidis647dcd82012-03-05 05:48:17 +0000402bool PreprocessingRecord::rangeIntersectsConditionalDirective(
403 SourceRange Range) const {
404 if (Range.isInvalid())
405 return false;
406
407 CondDirectiveLocsTy::const_iterator
408 low = std::lower_bound(CondDirectiveLocs.begin(), CondDirectiveLocs.end(),
409 Range.getBegin(), CondDirectiveLoc::Comp(SourceMgr));
410 if (low == CondDirectiveLocs.end())
411 return false;
412
413 if (SourceMgr.isBeforeInTranslationUnit(Range.getEnd(), low->getLoc()))
414 return false;
415
416 CondDirectiveLocsTy::const_iterator
417 upp = std::upper_bound(low, CondDirectiveLocs.end(),
418 Range.getEnd(), CondDirectiveLoc::Comp(SourceMgr));
419 unsigned uppIdx;
420 if (upp != CondDirectiveLocs.end())
421 uppIdx = upp->getIdx();
422 else
423 uppIdx = 0;
424
425 return low->getIdx() != uppIdx;
426}
427
428unsigned PreprocessingRecord::findCondDirectiveIdx(SourceLocation Loc) const {
429 if (Loc.isInvalid())
430 return 0;
431
432 CondDirectiveLocsTy::const_iterator
433 low = std::lower_bound(CondDirectiveLocs.begin(), CondDirectiveLocs.end(),
434 Loc, CondDirectiveLoc::Comp(SourceMgr));
435 if (low == CondDirectiveLocs.end())
436 return 0;
437 return low->getIdx();
438}
439
440void PreprocessingRecord::addCondDirectiveLoc(CondDirectiveLoc DirLoc) {
441 // Ignore directives in system headers.
442 if (SourceMgr.isInSystemHeader(DirLoc.getLoc()))
443 return;
444
445 assert(CondDirectiveLocs.empty() ||
446 SourceMgr.isBeforeInTranslationUnit(CondDirectiveLocs.back().getLoc(),
447 DirLoc.getLoc()));
448 CondDirectiveLocs.push_back(DirLoc);
449}
450
451void PreprocessingRecord::If(SourceLocation Loc, SourceRange ConditionRange) {
452 if (RecordCondDirectives) {
453 addCondDirectiveLoc(CondDirectiveLoc(Loc, CondDirectiveStack.back()));
454 CondDirectiveStack.push_back(CondDirectiveNextIdx++);
455 }
456}
457
458void PreprocessingRecord::Ifdef(SourceLocation Loc, const Token &MacroNameTok) {
459 if (RecordCondDirectives) {
460 addCondDirectiveLoc(CondDirectiveLoc(Loc, CondDirectiveStack.back()));
461 CondDirectiveStack.push_back(CondDirectiveNextIdx++);
462 }
463}
464
465void PreprocessingRecord::Ifndef(SourceLocation Loc,const Token &MacroNameTok) {
466 if (RecordCondDirectives) {
467 addCondDirectiveLoc(CondDirectiveLoc(Loc, CondDirectiveStack.back()));
468 CondDirectiveStack.push_back(CondDirectiveNextIdx++);
469 }
470}
471
472void PreprocessingRecord::Elif(SourceLocation Loc, SourceRange ConditionRange,
473 SourceLocation IfLoc) {
474 if (RecordCondDirectives)
475 addCondDirectiveLoc(CondDirectiveLoc(Loc, CondDirectiveStack.back()));
476}
477
478void PreprocessingRecord::Else(SourceLocation Loc, SourceLocation IfLoc) {
479 if (RecordCondDirectives)
480 addCondDirectiveLoc(CondDirectiveLoc(Loc, CondDirectiveStack.back()));
481}
482
483void PreprocessingRecord::Endif(SourceLocation Loc, SourceLocation IfLoc) {
484 if (RecordCondDirectives) {
485 addCondDirectiveLoc(CondDirectiveLoc(Loc, CondDirectiveStack.back()));
486 assert(!CondDirectiveStack.empty());
487 CondDirectiveStack.pop_back();
488 }
489}
490
Ted Kremenek182543a2011-07-26 21:17:24 +0000491size_t PreprocessingRecord::getTotalMemory() const {
492 return BumpAlloc.getTotalMemory()
Ted Kremenekf1c38812011-07-27 18:41:20 +0000493 + llvm::capacity_in_bytes(MacroDefinitions)
494 + llvm::capacity_in_bytes(PreprocessedEntities)
495 + llvm::capacity_in_bytes(LoadedPreprocessedEntities);
Ted Kremenek182543a2011-07-26 21:17:24 +0000496}