blob: 0376e449ae46c4ac4b8eca38d4344ae1fff816ff [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,
Argyrios Kyrtzidisf590e092012-10-02 16:10:46 +000028 bool InQuotes, bool ImportedModule,
29 const FileEntry *File,
Douglas Gregorf09b6c92010-11-01 15:03:47 +000030 SourceRange Range)
31 : PreprocessingDirective(InclusionDirectiveKind, Range),
Argyrios Kyrtzidisf590e092012-10-02 16:10:46 +000032 InQuotes(InQuotes), Kind(Kind), ImportedModule(ImportedModule), File(File)
Douglas Gregorf09b6c92010-11-01 15:03:47 +000033{
34 char *Memory
35 = (char*)PPRec.Allocate(FileName.size() + 1, llvm::alignOf<char>());
36 memcpy(Memory, FileName.data(), FileName.size());
37 Memory[FileName.size()] = 0;
Chris Lattner0e62c1c2011-07-23 10:55:15 +000038 this->FileName = StringRef(Memory, FileName.size());
Douglas Gregorf09b6c92010-11-01 15:03:47 +000039}
40
Argyrios Kyrtzidis647dcd82012-03-05 05:48:17 +000041PreprocessingRecord::PreprocessingRecord(SourceManager &SM,
42 bool RecordConditionalDirectives)
43 : SourceMgr(SM),
Argyrios Kyrtzidisd1c9031c2012-12-04 07:26:53 +000044 RecordCondDirectives(RecordConditionalDirectives),
Argyrios Kyrtzidis647dcd82012-03-05 05:48:17 +000045 ExternalSource(0)
Douglas Gregoraae92242010-03-19 21:51:54 +000046{
Argyrios Kyrtzidis647dcd82012-03-05 05:48:17 +000047 if (RecordCondDirectives)
Argyrios Kyrtzidisd1c9031c2012-12-04 07:26:53 +000048 CondDirectiveStack.push_back(SourceLocation());
Douglas Gregoraae92242010-03-19 21:51:54 +000049}
50
Argyrios Kyrtzidis64f63812011-09-19 20:40:25 +000051/// \brief Returns a pair of [Begin, End) iterators of preprocessed entities
James Dennett303d8d42012-06-22 05:37:13 +000052/// that source range \p Range encompasses.
Argyrios Kyrtzidis64f63812011-09-19 20:40:25 +000053std::pair<PreprocessingRecord::iterator, PreprocessingRecord::iterator>
54PreprocessingRecord::getPreprocessedEntitiesInRange(SourceRange Range) {
55 if (Range.isInvalid())
Argyrios Kyrtzidis429ec022011-10-25 00:29:50 +000056 return std::make_pair(iterator(), iterator());
Argyrios Kyrtzidis64f63812011-09-19 20:40:25 +000057
Argyrios Kyrtzidis429ec022011-10-25 00:29:50 +000058 if (CachedRangeQuery.Range == Range) {
59 return std::make_pair(iterator(this, CachedRangeQuery.Result.first),
60 iterator(this, CachedRangeQuery.Result.second));
61 }
62
Argyrios Kyrtzidisabc721a2012-10-05 00:22:28 +000063 std::pair<int, int> Res = getPreprocessedEntitiesInRangeSlow(Range);
Argyrios Kyrtzidis429ec022011-10-25 00:29:50 +000064
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
James Dennett303d8d42012-06-22 05:37:13 +000092/// and not from files \#included in the range given at
Argyrios Kyrtzidis429ec022011-10-25 00:29:50 +000093/// \see getPreprocessedEntitiesInRange.
94bool PreprocessingRecord::isEntityInFileID(iterator PPEI, FileID FID) {
95 if (FID.isInvalid())
96 return false;
97
Argyrios Kyrtzidisabc721a2012-10-05 00:22:28 +000098 int Pos = PPEI.Position;
99 if (Pos < 0) {
100 assert(unsigned(-Pos-1) < LoadedPreprocessedEntities.size() &&
Argyrios Kyrtzidis429ec022011-10-25 00:29:50 +0000101 "Out-of bounds loaded preprocessed entity");
102 assert(ExternalSource && "No external source to load from");
Argyrios Kyrtzidisabc721a2012-10-05 00:22:28 +0000103 unsigned LoadedIndex = LoadedPreprocessedEntities.size()+Pos;
Argyrios Kyrtzidis429ec022011-10-25 00:29:50 +0000104 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
Argyrios Kyrtzidisabc721a2012-10-05 00:22:28 +0000121 assert(unsigned(Pos) < PreprocessedEntities.size() &&
Argyrios Kyrtzidis429ec022011-10-25 00:29:50 +0000122 "Out-of bounds local preprocessed entity");
Argyrios Kyrtzidisabc721a2012-10-05 00:22:28 +0000123 return isPreprocessedEntityIfInFileID(PreprocessedEntities[Pos],
Argyrios Kyrtzidis429ec022011-10-25 00:29:50 +0000124 FID, SourceMgr);
125}
126
127/// \brief Returns a pair of [Begin, End) iterators of preprocessed entities
128/// that source range \arg R encompasses.
Argyrios Kyrtzidisabc721a2012-10-05 00:22:28 +0000129std::pair<int, int>
Argyrios Kyrtzidis429ec022011-10-25 00:29:50 +0000130PreprocessingRecord::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
Argyrios Kyrtzidisa9564502012-03-27 18:47:48 +0000247PreprocessingRecord::PPEntityID
248PreprocessingRecord::addPreprocessedEntity(PreprocessedEntity *Entity) {
Argyrios Kyrtzidis45e8cf52011-09-20 23:27:33 +0000249 assert(Entity);
Argyrios Kyrtzidisf37d0a62011-10-12 17:36:33 +0000250 SourceLocation BeginLoc = Entity->getSourceRange().getBegin();
Argyrios Kyrtzidisa9564502012-03-27 18:47:48 +0000251
252 if (!isa<class InclusionDirective>(Entity)) {
253 assert((PreprocessedEntities.empty() ||
254 !SourceMgr.isBeforeInTranslationUnit(BeginLoc,
255 PreprocessedEntities.back()->getSourceRange().getBegin())) &&
256 "a macro directive was encountered out-of-order");
257 PreprocessedEntities.push_back(Entity);
258 return getPPEntityID(PreprocessedEntities.size()-1, /*isLoaded=*/false);
259 }
260
Argyrios Kyrtzidisf37d0a62011-10-12 17:36:33 +0000261 // Check normal case, this entity begin location is after the previous one.
262 if (PreprocessedEntities.empty() ||
263 !SourceMgr.isBeforeInTranslationUnit(BeginLoc,
264 PreprocessedEntities.back()->getSourceRange().getBegin())) {
265 PreprocessedEntities.push_back(Entity);
Argyrios Kyrtzidisa9564502012-03-27 18:47:48 +0000266 return getPPEntityID(PreprocessedEntities.size()-1, /*isLoaded=*/false);
Argyrios Kyrtzidisf37d0a62011-10-12 17:36:33 +0000267 }
268
Argyrios Kyrtzidisa9564502012-03-27 18:47:48 +0000269 // The entity's location is not after the previous one; this can happen with
270 // include directives that form the filename using macros, e.g:
271 // "#include MACRO(STUFF)".
272
273 typedef std::vector<PreprocessedEntity *>::iterator pp_iter;
274
275 // Usually there are few macro expansions when defining the filename, do a
276 // linear search for a few entities.
277 unsigned count = 0;
278 for (pp_iter RI = PreprocessedEntities.end(),
279 Begin = PreprocessedEntities.begin();
280 RI != Begin && count < 4; --RI, ++count) {
281 pp_iter I = RI;
Argyrios Kyrtzidisf37d0a62011-10-12 17:36:33 +0000282 --I;
283 if (!SourceMgr.isBeforeInTranslationUnit(BeginLoc,
284 (*I)->getSourceRange().getBegin())) {
Argyrios Kyrtzidisa9564502012-03-27 18:47:48 +0000285 pp_iter insertI = PreprocessedEntities.insert(RI, Entity);
286 return getPPEntityID(insertI - PreprocessedEntities.begin(),
287 /*isLoaded=*/false);
Argyrios Kyrtzidisf37d0a62011-10-12 17:36:33 +0000288 }
289 }
Argyrios Kyrtzidisa9564502012-03-27 18:47:48 +0000290
291 // Linear search unsuccessful. Do a binary search.
292 pp_iter I = std::upper_bound(PreprocessedEntities.begin(),
293 PreprocessedEntities.end(),
294 BeginLoc,
295 PPEntityComp<&SourceRange::getBegin>(SourceMgr));
296 pp_iter insertI = PreprocessedEntities.insert(I, Entity);
297 return getPPEntityID(insertI - PreprocessedEntities.begin(),
298 /*isLoaded=*/false);
Douglas Gregor065f8d12010-03-18 17:52:52 +0000299}
300
Douglas Gregoraae92242010-03-19 21:51:54 +0000301void PreprocessingRecord::SetExternalSource(
Douglas Gregor4a9c39a2011-07-21 00:47:40 +0000302 ExternalPreprocessingRecordSource &Source) {
Douglas Gregoraae92242010-03-19 21:51:54 +0000303 assert(!ExternalSource &&
304 "Preprocessing record already has an external source");
305 ExternalSource = &Source;
Douglas Gregoraae92242010-03-19 21:51:54 +0000306}
307
Douglas Gregor4a9c39a2011-07-21 00:47:40 +0000308unsigned PreprocessingRecord::allocateLoadedEntities(unsigned NumEntities) {
309 unsigned Result = LoadedPreprocessedEntities.size();
310 LoadedPreprocessedEntities.resize(LoadedPreprocessedEntities.size()
311 + NumEntities);
312 return Result;
313}
314
Argyrios Kyrtzidis03c40c52011-09-15 18:02:56 +0000315void PreprocessingRecord::RegisterMacroDefinition(MacroInfo *Macro,
316 PPEntityID PPID) {
317 MacroDefinitions[Macro] = PPID;
Douglas Gregoraae92242010-03-19 21:51:54 +0000318}
319
Argyrios Kyrtzidis03c40c52011-09-15 18:02:56 +0000320/// \brief Retrieve the preprocessed entity at the given ID.
321PreprocessedEntity *PreprocessingRecord::getPreprocessedEntity(PPEntityID PPID){
Argyrios Kyrtzidisabc721a2012-10-05 00:22:28 +0000322 if (PPID.ID < 0) {
323 unsigned Index = -PPID.ID - 1;
324 assert(Index < LoadedPreprocessedEntities.size() &&
Argyrios Kyrtzidis03c40c52011-09-15 18:02:56 +0000325 "Out-of bounds loaded preprocessed entity");
Argyrios Kyrtzidisabc721a2012-10-05 00:22:28 +0000326 return getLoadedPreprocessedEntity(Index);
Argyrios Kyrtzidis03c40c52011-09-15 18:02:56 +0000327 }
Argyrios Kyrtzidisabc721a2012-10-05 00:22:28 +0000328
329 if (PPID.ID == 0)
330 return 0;
331 unsigned Index = PPID.ID - 1;
332 assert(Index < PreprocessedEntities.size() &&
Argyrios Kyrtzidis03c40c52011-09-15 18:02:56 +0000333 "Out-of bounds local preprocessed entity");
Argyrios Kyrtzidisabc721a2012-10-05 00:22:28 +0000334 return PreprocessedEntities[Index];
Argyrios Kyrtzidis03c40c52011-09-15 18:02:56 +0000335}
336
337/// \brief Retrieve the loaded preprocessed entity at the given index.
338PreprocessedEntity *
339PreprocessingRecord::getLoadedPreprocessedEntity(unsigned Index) {
340 assert(Index < LoadedPreprocessedEntities.size() &&
341 "Out-of bounds loaded preprocessed entity");
342 assert(ExternalSource && "No external source to load from");
343 PreprocessedEntity *&Entity = LoadedPreprocessedEntities[Index];
344 if (!Entity) {
345 Entity = ExternalSource->ReadPreprocessedEntity(Index);
346 if (!Entity) // Failed to load.
347 Entity = new (*this)
348 PreprocessedEntity(PreprocessedEntity::InvalidKind, SourceRange());
349 }
350 return Entity;
Douglas Gregoraae92242010-03-19 21:51:54 +0000351}
352
Douglas Gregor8aaca672010-03-19 21:58:23 +0000353MacroDefinition *PreprocessingRecord::findMacroDefinition(const MacroInfo *MI) {
Argyrios Kyrtzidis03c40c52011-09-15 18:02:56 +0000354 llvm::DenseMap<const MacroInfo *, PPEntityID>::iterator Pos
Douglas Gregor7dc87222010-03-19 17:12:43 +0000355 = MacroDefinitions.find(MI);
356 if (Pos == MacroDefinitions.end())
357 return 0;
358
Argyrios Kyrtzidis03c40c52011-09-15 18:02:56 +0000359 PreprocessedEntity *Entity = getPreprocessedEntity(Pos->second);
360 if (Entity->isInvalid())
361 return 0;
362 return cast<MacroDefinition>(Entity);
Douglas Gregor7dc87222010-03-19 17:12:43 +0000363}
364
Argyrios Kyrtzidis85a14bb2011-08-18 01:05:45 +0000365void PreprocessingRecord::MacroExpands(const Token &Id, const MacroInfo* MI,
366 SourceRange Range) {
Argyrios Kyrtzidis335c5a42012-02-25 02:41:16 +0000367 // We don't record nested macro expansions.
368 if (Id.getLocation().isMacroID())
Douglas Gregor998caea2011-05-06 16:33:08 +0000369 return;
370
Argyrios Kyrtzidis80f78b92011-09-08 17:18:41 +0000371 if (MI->isBuiltinMacro())
Argyrios Kyrtzidis64f63812011-09-19 20:40:25 +0000372 addPreprocessedEntity(
Argyrios Kyrtzidis80f78b92011-09-08 17:18:41 +0000373 new (*this) MacroExpansion(Id.getIdentifierInfo(),Range));
374 else if (MacroDefinition *Def = findMacroDefinition(MI))
Argyrios Kyrtzidis64f63812011-09-19 20:40:25 +0000375 addPreprocessedEntity(
Argyrios Kyrtzidis80f78b92011-09-08 17:18:41 +0000376 new (*this) MacroExpansion(Def, Range));
Douglas Gregor7dc87222010-03-19 17:12:43 +0000377}
378
Craig Silverstein1a9ca212010-11-19 21:33:15 +0000379void PreprocessingRecord::MacroDefined(const Token &Id,
Douglas Gregor7dc87222010-03-19 17:12:43 +0000380 const MacroInfo *MI) {
381 SourceRange R(MI->getDefinitionLoc(), MI->getDefinitionEndLoc());
382 MacroDefinition *Def
Argyrios Kyrtzidis0d48fb82011-09-20 22:14:48 +0000383 = new (*this) MacroDefinition(Id.getIdentifierInfo(), R);
Argyrios Kyrtzidisa9564502012-03-27 18:47:48 +0000384 MacroDefinitions[MI] = addPreprocessedEntity(Def);
Douglas Gregor7dc87222010-03-19 17:12:43 +0000385}
Douglas Gregoraae92242010-03-19 21:51:54 +0000386
Craig Silverstein1a9ca212010-11-19 21:33:15 +0000387void PreprocessingRecord::MacroUndefined(const Token &Id,
Douglas Gregor8aaca672010-03-19 21:58:23 +0000388 const MacroInfo *MI) {
Benjamin Kramere894e092012-03-24 18:22:12 +0000389 MacroDefinitions.erase(MI);
Douglas Gregor8aaca672010-03-19 21:58:23 +0000390}
391
Chandler Carruth3cc331a2011-03-16 18:34:36 +0000392void PreprocessingRecord::InclusionDirective(
393 SourceLocation HashLoc,
394 const clang::Token &IncludeTok,
Chris Lattner0e62c1c2011-07-23 10:55:15 +0000395 StringRef FileName,
Chandler Carruth3cc331a2011-03-16 18:34:36 +0000396 bool IsAngled,
Argyrios Kyrtzidis4fcd2882012-09-27 01:42:07 +0000397 CharSourceRange FilenameRange,
Chandler Carruth3cc331a2011-03-16 18:34:36 +0000398 const FileEntry *File,
Chris Lattner0e62c1c2011-07-23 10:55:15 +0000399 StringRef SearchPath,
Argyrios Kyrtzidis19d78b72012-09-29 01:06:10 +0000400 StringRef RelativePath,
401 const Module *Imported) {
Douglas Gregor796d76a2010-10-20 22:00:55 +0000402 InclusionDirective::InclusionKind Kind = InclusionDirective::Include;
403
404 switch (IncludeTok.getIdentifierInfo()->getPPKeywordID()) {
405 case tok::pp_include:
406 Kind = InclusionDirective::Include;
407 break;
408
409 case tok::pp_import:
410 Kind = InclusionDirective::Import;
411 break;
412
413 case tok::pp_include_next:
414 Kind = InclusionDirective::IncludeNext;
415 break;
416
417 case tok::pp___include_macros:
418 Kind = InclusionDirective::IncludeMacros;
419 break;
420
421 default:
422 llvm_unreachable("Unknown include directive kind");
Douglas Gregor796d76a2010-10-20 22:00:55 +0000423 }
Argyrios Kyrtzidis4fcd2882012-09-27 01:42:07 +0000424
425 SourceLocation EndLoc;
426 if (!IsAngled) {
427 EndLoc = FilenameRange.getBegin();
428 } else {
429 EndLoc = FilenameRange.getEnd();
430 if (FilenameRange.isCharRange())
431 EndLoc = EndLoc.getLocWithOffset(-1); // the InclusionDirective expects
432 // a token range.
433 }
Douglas Gregor796d76a2010-10-20 22:00:55 +0000434 clang::InclusionDirective *ID
Argyrios Kyrtzidisf590e092012-10-02 16:10:46 +0000435 = new (*this) clang::InclusionDirective(*this, Kind, FileName, !IsAngled,
436 (bool)Imported,
Douglas Gregorf09b6c92010-11-01 15:03:47 +0000437 File, SourceRange(HashLoc, EndLoc));
Argyrios Kyrtzidis64f63812011-09-19 20:40:25 +0000438 addPreprocessedEntity(ID);
Douglas Gregor796d76a2010-10-20 22:00:55 +0000439}
Ted Kremenek182543a2011-07-26 21:17:24 +0000440
Argyrios Kyrtzidis647dcd82012-03-05 05:48:17 +0000441bool PreprocessingRecord::rangeIntersectsConditionalDirective(
442 SourceRange Range) const {
443 if (Range.isInvalid())
444 return false;
445
446 CondDirectiveLocsTy::const_iterator
447 low = std::lower_bound(CondDirectiveLocs.begin(), CondDirectiveLocs.end(),
448 Range.getBegin(), CondDirectiveLoc::Comp(SourceMgr));
449 if (low == CondDirectiveLocs.end())
450 return false;
451
452 if (SourceMgr.isBeforeInTranslationUnit(Range.getEnd(), low->getLoc()))
453 return false;
454
455 CondDirectiveLocsTy::const_iterator
456 upp = std::upper_bound(low, CondDirectiveLocs.end(),
457 Range.getEnd(), CondDirectiveLoc::Comp(SourceMgr));
Argyrios Kyrtzidisd1c9031c2012-12-04 07:26:53 +0000458 SourceLocation uppRegion;
Argyrios Kyrtzidis647dcd82012-03-05 05:48:17 +0000459 if (upp != CondDirectiveLocs.end())
Argyrios Kyrtzidisd1c9031c2012-12-04 07:26:53 +0000460 uppRegion = upp->getRegionLoc();
Argyrios Kyrtzidis647dcd82012-03-05 05:48:17 +0000461
Argyrios Kyrtzidisd1c9031c2012-12-04 07:26:53 +0000462 return low->getRegionLoc() != uppRegion;
Argyrios Kyrtzidis647dcd82012-03-05 05:48:17 +0000463}
464
Argyrios Kyrtzidisd1c9031c2012-12-04 07:26:53 +0000465SourceLocation
466PreprocessingRecord::findCondDirectiveRegionLoc(SourceLocation Loc) const {
Argyrios Kyrtzidis647dcd82012-03-05 05:48:17 +0000467 if (Loc.isInvalid())
Argyrios Kyrtzidisd1c9031c2012-12-04 07:26:53 +0000468 return SourceLocation();
Argyrios Kyrtzidis647dcd82012-03-05 05:48:17 +0000469
470 CondDirectiveLocsTy::const_iterator
471 low = std::lower_bound(CondDirectiveLocs.begin(), CondDirectiveLocs.end(),
472 Loc, CondDirectiveLoc::Comp(SourceMgr));
473 if (low == CondDirectiveLocs.end())
Argyrios Kyrtzidisd1c9031c2012-12-04 07:26:53 +0000474 return SourceLocation();
475 return low->getRegionLoc();
Argyrios Kyrtzidis647dcd82012-03-05 05:48:17 +0000476}
477
478void PreprocessingRecord::addCondDirectiveLoc(CondDirectiveLoc DirLoc) {
479 // Ignore directives in system headers.
480 if (SourceMgr.isInSystemHeader(DirLoc.getLoc()))
481 return;
482
483 assert(CondDirectiveLocs.empty() ||
484 SourceMgr.isBeforeInTranslationUnit(CondDirectiveLocs.back().getLoc(),
485 DirLoc.getLoc()));
486 CondDirectiveLocs.push_back(DirLoc);
487}
488
489void PreprocessingRecord::If(SourceLocation Loc, SourceRange ConditionRange) {
490 if (RecordCondDirectives) {
491 addCondDirectiveLoc(CondDirectiveLoc(Loc, CondDirectiveStack.back()));
Argyrios Kyrtzidisd1c9031c2012-12-04 07:26:53 +0000492 CondDirectiveStack.push_back(Loc);
Argyrios Kyrtzidis647dcd82012-03-05 05:48:17 +0000493 }
494}
495
496void PreprocessingRecord::Ifdef(SourceLocation Loc, const Token &MacroNameTok) {
497 if (RecordCondDirectives) {
498 addCondDirectiveLoc(CondDirectiveLoc(Loc, CondDirectiveStack.back()));
Argyrios Kyrtzidisd1c9031c2012-12-04 07:26:53 +0000499 CondDirectiveStack.push_back(Loc);
Argyrios Kyrtzidis647dcd82012-03-05 05:48:17 +0000500 }
501}
502
503void PreprocessingRecord::Ifndef(SourceLocation Loc,const Token &MacroNameTok) {
504 if (RecordCondDirectives) {
505 addCondDirectiveLoc(CondDirectiveLoc(Loc, CondDirectiveStack.back()));
Argyrios Kyrtzidisd1c9031c2012-12-04 07:26:53 +0000506 CondDirectiveStack.push_back(Loc);
Argyrios Kyrtzidis647dcd82012-03-05 05:48:17 +0000507 }
508}
509
510void PreprocessingRecord::Elif(SourceLocation Loc, SourceRange ConditionRange,
511 SourceLocation IfLoc) {
Argyrios Kyrtzidisd1c9031c2012-12-04 07:26:53 +0000512 if (RecordCondDirectives) {
Argyrios Kyrtzidis647dcd82012-03-05 05:48:17 +0000513 addCondDirectiveLoc(CondDirectiveLoc(Loc, CondDirectiveStack.back()));
Argyrios Kyrtzidisd1c9031c2012-12-04 07:26:53 +0000514 CondDirectiveStack.back() = Loc;
515 }
Argyrios Kyrtzidis647dcd82012-03-05 05:48:17 +0000516}
517
518void PreprocessingRecord::Else(SourceLocation Loc, SourceLocation IfLoc) {
Argyrios Kyrtzidisd1c9031c2012-12-04 07:26:53 +0000519 if (RecordCondDirectives) {
Argyrios Kyrtzidis647dcd82012-03-05 05:48:17 +0000520 addCondDirectiveLoc(CondDirectiveLoc(Loc, CondDirectiveStack.back()));
Argyrios Kyrtzidisd1c9031c2012-12-04 07:26:53 +0000521 CondDirectiveStack.back() = Loc;
522 }
Argyrios Kyrtzidis647dcd82012-03-05 05:48:17 +0000523}
524
525void PreprocessingRecord::Endif(SourceLocation Loc, SourceLocation IfLoc) {
526 if (RecordCondDirectives) {
527 addCondDirectiveLoc(CondDirectiveLoc(Loc, CondDirectiveStack.back()));
528 assert(!CondDirectiveStack.empty());
529 CondDirectiveStack.pop_back();
530 }
531}
532
Ted Kremenek182543a2011-07-26 21:17:24 +0000533size_t PreprocessingRecord::getTotalMemory() const {
534 return BumpAlloc.getTotalMemory()
Ted Kremenekf1c38812011-07-27 18:41:20 +0000535 + llvm::capacity_in_bytes(MacroDefinitions)
536 + llvm::capacity_in_bytes(PreprocessedEntities)
537 + llvm::capacity_in_bytes(LoadedPreprocessedEntities);
Ted Kremenek182543a2011-07-26 21:17:24 +0000538}