blob: b372b2df509ee83130d624e06b456a424bd31967 [file] [log] [blame]
Eugene Zelenkocb96ac62017-12-08 22:39:26 +00001//===- PreprocessingRecord.cpp - Record of Preprocessing ------------------===//
Douglas Gregor065f8d12010-03-18 17:52:52 +00002//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// 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
Douglas Gregor065f8d12010-03-18 17:52:52 +00006//
7//===----------------------------------------------------------------------===//
8//
9// This file implements the PreprocessingRecord class, which maintains a record
10// of what occurred during preprocessing, and its helpers.
11//
12//===----------------------------------------------------------------------===//
Eugene Zelenkocb96ac62017-12-08 22:39:26 +000013
Douglas Gregor065f8d12010-03-18 17:52:52 +000014#include "clang/Lex/PreprocessingRecord.h"
Eugene Zelenkocb96ac62017-12-08 22:39:26 +000015#include "clang/Basic/IdentifierTable.h"
16#include "clang/Basic/LLVM.h"
17#include "clang/Basic/SourceLocation.h"
18#include "clang/Basic/SourceManager.h"
19#include "clang/Basic/TokenKinds.h"
Douglas Gregor065f8d12010-03-18 17:52:52 +000020#include "clang/Lex/MacroInfo.h"
21#include "clang/Lex/Token.h"
Eugene Zelenkocb96ac62017-12-08 22:39:26 +000022#include "llvm/ADT/DenseMap.h"
23#include "llvm/ADT/Optional.h"
24#include "llvm/ADT/StringRef.h"
25#include "llvm/ADT/iterator_range.h"
Ted Kremenekf1c38812011-07-27 18:41:20 +000026#include "llvm/Support/Capacity.h"
Eugene Zelenkocb96ac62017-12-08 22:39:26 +000027#include "llvm/Support/Casting.h"
Chandler Carruth3a022472012-12-04 09:13:33 +000028#include "llvm/Support/ErrorHandling.h"
Eugene Zelenkocb96ac62017-12-08 22:39:26 +000029#include <algorithm>
30#include <cassert>
31#include <cstddef>
32#include <cstring>
33#include <iterator>
34#include <utility>
35#include <vector>
Douglas Gregor065f8d12010-03-18 17:52:52 +000036
37using namespace clang;
38
Eugene Zelenkocb96ac62017-12-08 22:39:26 +000039ExternalPreprocessingRecordSource::~ExternalPreprocessingRecordSource() =
40 default;
Douglas Gregoraae92242010-03-19 21:51:54 +000041
Douglas Gregorf09b6c92010-11-01 15:03:47 +000042InclusionDirective::InclusionDirective(PreprocessingRecord &PPRec,
Benjamin Kramerc3f89252016-10-20 14:27:22 +000043 InclusionKind Kind, StringRef FileName,
Argyrios Kyrtzidisf590e092012-10-02 16:10:46 +000044 bool InQuotes, bool ImportedModule,
Benjamin Kramerc3f89252016-10-20 14:27:22 +000045 const FileEntry *File, SourceRange Range)
46 : PreprocessingDirective(InclusionDirectiveKind, Range), InQuotes(InQuotes),
47 Kind(Kind), ImportedModule(ImportedModule), File(File) {
48 char *Memory = (char *)PPRec.Allocate(FileName.size() + 1, alignof(char));
Douglas Gregorf09b6c92010-11-01 15:03:47 +000049 memcpy(Memory, FileName.data(), FileName.size());
50 Memory[FileName.size()] = 0;
Chris Lattner0e62c1c2011-07-23 10:55:15 +000051 this->FileName = StringRef(Memory, FileName.size());
Douglas Gregorf09b6c92010-11-01 15:03:47 +000052}
53
Eugene Zelenkocb96ac62017-12-08 22:39:26 +000054PreprocessingRecord::PreprocessingRecord(SourceManager &SM) : SourceMgr(SM) {}
Douglas Gregoraae92242010-03-19 21:51:54 +000055
Adrian Prantl9fc8faf2018-05-09 01:00:01 +000056/// Returns a pair of [Begin, End) iterators of preprocessed entities
James Dennett303d8d42012-06-22 05:37:13 +000057/// that source range \p Range encompasses.
Benjamin Kramerb4ef6682015-02-06 17:25:10 +000058llvm::iterator_range<PreprocessingRecord::iterator>
Argyrios Kyrtzidis64f63812011-09-19 20:40:25 +000059PreprocessingRecord::getPreprocessedEntitiesInRange(SourceRange Range) {
60 if (Range.isInvalid())
Benjamin Kramerb4ef6682015-02-06 17:25:10 +000061 return llvm::make_range(iterator(), iterator());
Argyrios Kyrtzidis64f63812011-09-19 20:40:25 +000062
Argyrios Kyrtzidis429ec022011-10-25 00:29:50 +000063 if (CachedRangeQuery.Range == Range) {
Benjamin Kramerb4ef6682015-02-06 17:25:10 +000064 return llvm::make_range(iterator(this, CachedRangeQuery.Result.first),
65 iterator(this, CachedRangeQuery.Result.second));
Argyrios Kyrtzidis429ec022011-10-25 00:29:50 +000066 }
67
Argyrios Kyrtzidisabc721a2012-10-05 00:22:28 +000068 std::pair<int, int> Res = getPreprocessedEntitiesInRangeSlow(Range);
Fangrui Song6907ce22018-07-30 19:24:48 +000069
Argyrios Kyrtzidis429ec022011-10-25 00:29:50 +000070 CachedRangeQuery.Range = Range;
71 CachedRangeQuery.Result = Res;
Benjamin Kramerb4ef6682015-02-06 17:25:10 +000072
73 return llvm::make_range(iterator(this, Res.first),
74 iterator(this, Res.second));
Argyrios Kyrtzidis429ec022011-10-25 00:29:50 +000075}
76
77static bool isPreprocessedEntityIfInFileID(PreprocessedEntity *PPE, FileID FID,
78 SourceManager &SM) {
Yaron Keren8b563662015-10-03 10:46:20 +000079 assert(FID.isValid());
Argyrios Kyrtzidis429ec022011-10-25 00:29:50 +000080 if (!PPE)
81 return false;
82
83 SourceLocation Loc = PPE->getSourceRange().getBegin();
84 if (Loc.isInvalid())
85 return false;
David Blaikie7a3cbb22015-03-09 02:02:07 +000086
87 return SM.isInFileID(SM.getFileLoc(Loc), FID);
Argyrios Kyrtzidis429ec022011-10-25 00:29:50 +000088}
89
Adrian Prantl9fc8faf2018-05-09 01:00:01 +000090/// Returns true if the preprocessed entity that \arg PPEI iterator
Argyrios Kyrtzidis429ec022011-10-25 00:29:50 +000091/// points to is coming from the file \arg FID.
92///
93/// Can be used to avoid implicit deserializations of preallocated
94/// preprocessed entities if we only care about entities of a specific file
James Dennett303d8d42012-06-22 05:37:13 +000095/// and not from files \#included in the range given at
Argyrios Kyrtzidis429ec022011-10-25 00:29:50 +000096/// \see getPreprocessedEntitiesInRange.
97bool PreprocessingRecord::isEntityInFileID(iterator PPEI, FileID FID) {
98 if (FID.isInvalid())
99 return false;
100
Benjamin Kramer15b97172015-03-15 15:27:19 +0000101 int Pos = std::distance(iterator(this, 0), PPEI);
Argyrios Kyrtzidisabc721a2012-10-05 00:22:28 +0000102 if (Pos < 0) {
Argyrios Kyrtzidis962b2212013-02-12 21:41:23 +0000103 if (unsigned(-Pos-1) >= LoadedPreprocessedEntities.size()) {
104 assert(0 && "Out-of bounds loaded preprocessed entity");
105 return false;
106 }
Argyrios Kyrtzidis429ec022011-10-25 00:29:50 +0000107 assert(ExternalSource && "No external source to load from");
Argyrios Kyrtzidisabc721a2012-10-05 00:22:28 +0000108 unsigned LoadedIndex = LoadedPreprocessedEntities.size()+Pos;
Argyrios Kyrtzidis429ec022011-10-25 00:29:50 +0000109 if (PreprocessedEntity *PPE = LoadedPreprocessedEntities[LoadedIndex])
110 return isPreprocessedEntityIfInFileID(PPE, FID, SourceMgr);
111
112 // See if the external source can see if the entity is in the file without
113 // deserializing it.
David Blaikie05785d12013-02-20 22:23:23 +0000114 Optional<bool> IsInFile =
115 ExternalSource->isPreprocessedEntityInFileID(LoadedIndex, FID);
Argyrios Kyrtzidis429ec022011-10-25 00:29:50 +0000116 if (IsInFile.hasValue())
117 return IsInFile.getValue();
118
119 // The external source did not provide a definite answer, go and deserialize
120 // the entity to check it.
121 return isPreprocessedEntityIfInFileID(
122 getLoadedPreprocessedEntity(LoadedIndex),
123 FID, SourceMgr);
124 }
125
Argyrios Kyrtzidis962b2212013-02-12 21:41:23 +0000126 if (unsigned(Pos) >= PreprocessedEntities.size()) {
127 assert(0 && "Out-of bounds local preprocessed entity");
128 return false;
129 }
Argyrios Kyrtzidisabc721a2012-10-05 00:22:28 +0000130 return isPreprocessedEntityIfInFileID(PreprocessedEntities[Pos],
Argyrios Kyrtzidis429ec022011-10-25 00:29:50 +0000131 FID, SourceMgr);
132}
133
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000134/// Returns a pair of [Begin, End) iterators of preprocessed entities
Argyrios Kyrtzidis429ec022011-10-25 00:29:50 +0000135/// that source range \arg R encompasses.
Argyrios Kyrtzidisabc721a2012-10-05 00:22:28 +0000136std::pair<int, int>
Argyrios Kyrtzidis429ec022011-10-25 00:29:50 +0000137PreprocessingRecord::getPreprocessedEntitiesInRangeSlow(SourceRange Range) {
138 assert(Range.isValid());
139 assert(!SourceMgr.isBeforeInTranslationUnit(Range.getEnd(),Range.getBegin()));
Fangrui Song6907ce22018-07-30 19:24:48 +0000140
Argyrios Kyrtzidis64f63812011-09-19 20:40:25 +0000141 std::pair<unsigned, unsigned>
142 Local = findLocalPreprocessedEntitiesInRange(Range);
Fangrui Song6907ce22018-07-30 19:24:48 +0000143
Argyrios Kyrtzidis64f63812011-09-19 20:40:25 +0000144 // Check if range spans local entities.
145 if (!ExternalSource || SourceMgr.isLocalSourceLocation(Range.getBegin()))
Argyrios Kyrtzidis429ec022011-10-25 00:29:50 +0000146 return std::make_pair(Local.first, Local.second);
Fangrui Song6907ce22018-07-30 19:24:48 +0000147
Argyrios Kyrtzidis64f63812011-09-19 20:40:25 +0000148 std::pair<unsigned, unsigned>
149 Loaded = ExternalSource->findPreprocessedEntitiesInRange(Range);
Fangrui Song6907ce22018-07-30 19:24:48 +0000150
Argyrios Kyrtzidis64f63812011-09-19 20:40:25 +0000151 // Check if range spans local entities.
152 if (Loaded.first == Loaded.second)
Argyrios Kyrtzidis429ec022011-10-25 00:29:50 +0000153 return std::make_pair(Local.first, Local.second);
Fangrui Song6907ce22018-07-30 19:24:48 +0000154
Argyrios Kyrtzidis64f63812011-09-19 20:40:25 +0000155 unsigned TotalLoaded = LoadedPreprocessedEntities.size();
Fangrui Song6907ce22018-07-30 19:24:48 +0000156
Argyrios Kyrtzidis64f63812011-09-19 20:40:25 +0000157 // Check if range spans loaded entities.
158 if (Local.first == Local.second)
Argyrios Kyrtzidis429ec022011-10-25 00:29:50 +0000159 return std::make_pair(int(Loaded.first)-TotalLoaded,
160 int(Loaded.second)-TotalLoaded);
Fangrui Song6907ce22018-07-30 19:24:48 +0000161
Argyrios Kyrtzidis64f63812011-09-19 20:40:25 +0000162 // Range spands loaded and local entities.
Argyrios Kyrtzidis429ec022011-10-25 00:29:50 +0000163 return std::make_pair(int(Loaded.first)-TotalLoaded, Local.second);
Argyrios Kyrtzidis64f63812011-09-19 20:40:25 +0000164}
165
166std::pair<unsigned, unsigned>
167PreprocessingRecord::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
178namespace {
179
180template <SourceLocation (SourceRange::*getRangeLoc)() const>
181struct PPEntityComp {
182 const SourceManager &SM;
183
Eugene Zelenkocb96ac62017-12-08 22:39:26 +0000184 explicit PPEntityComp(const SourceManager &SM) : SM(SM) {}
Argyrios Kyrtzidis64f63812011-09-19 20:40:25 +0000185
Benjamin Kramer2e9d9cf2011-09-21 16:58:20 +0000186 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 {
Argyrios Kyrtzidis64f63812011-09-19 20:40:25 +0000193 SourceLocation LHS = getLoc(L);
194 return SM.isBeforeInTranslationUnit(LHS, RHS);
195 }
196
Benjamin Kramer2e9d9cf2011-09-21 16:58:20 +0000197 bool operator()(SourceLocation LHS, PreprocessedEntity *R) const {
Argyrios Kyrtzidis64f63812011-09-19 20:40:25 +0000198 SourceLocation RHS = getLoc(R);
199 return SM.isBeforeInTranslationUnit(LHS, RHS);
200 }
201
202 SourceLocation getLoc(PreprocessedEntity *PPE) const {
Argyrios Kyrtzidisa35c4442011-09-19 22:02:08 +0000203 SourceRange Range = PPE->getSourceRange();
204 return (Range.*getRangeLoc)();
Argyrios Kyrtzidis64f63812011-09-19 20:40:25 +0000205 }
206};
207
Eugene Zelenkocb96ac62017-12-08 22:39:26 +0000208} // namespace
Argyrios Kyrtzidis64f63812011-09-19 20:40:25 +0000209
210unsigned PreprocessingRecord::findBeginLocalPreprocessedEntity(
211 SourceLocation Loc) const {
212 if (SourceMgr.isLoadedSourceLocation(Loc))
213 return 0;
214
Argyrios Kyrtzidise523e382011-09-22 21:17:02 +0000215 size_t Count = PreprocessedEntities.size();
216 size_t Half;
Argyrios Kyrtzidis64f63812011-09-19 20:40:25 +0000217 std::vector<PreprocessedEntity *>::const_iterator
Argyrios Kyrtzidise523e382011-09-22 21:17:02 +0000218 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();
Argyrios Kyrtzidis64f63812011-09-19 20:40:25 +0000239}
240
241unsigned PreprocessingRecord::findEndLocalPreprocessedEntity(
242 SourceLocation Loc) const {
243 if (SourceMgr.isLoadedSourceLocation(Loc))
244 return 0;
245
246 std::vector<PreprocessedEntity *>::const_iterator
247 I = std::upper_bound(PreprocessedEntities.begin(),
248 PreprocessedEntities.end(),
249 Loc,
250 PPEntityComp<&SourceRange::getBegin>(SourceMgr));
251 return I - PreprocessedEntities.begin();
252}
253
Argyrios Kyrtzidisa9564502012-03-27 18:47:48 +0000254PreprocessingRecord::PPEntityID
255PreprocessingRecord::addPreprocessedEntity(PreprocessedEntity *Entity) {
Argyrios Kyrtzidis45e8cf52011-09-20 23:27:33 +0000256 assert(Entity);
Argyrios Kyrtzidisf37d0a62011-10-12 17:36:33 +0000257 SourceLocation BeginLoc = Entity->getSourceRange().getBegin();
Argyrios Kyrtzidisa9564502012-03-27 18:47:48 +0000258
Richard Smith66a81862015-05-04 02:25:31 +0000259 if (isa<MacroDefinitionRecord>(Entity)) {
Argyrios Kyrtzidisa9564502012-03-27 18:47:48 +0000260 assert((PreprocessedEntities.empty() ||
Richard Smith66a81862015-05-04 02:25:31 +0000261 !SourceMgr.isBeforeInTranslationUnit(
262 BeginLoc,
263 PreprocessedEntities.back()->getSourceRange().getBegin())) &&
Argyrios Kyrtzidiseb994f42013-01-09 23:22:20 +0000264 "a macro definition was encountered out-of-order");
Argyrios Kyrtzidisa9564502012-03-27 18:47:48 +0000265 PreprocessedEntities.push_back(Entity);
266 return getPPEntityID(PreprocessedEntities.size()-1, /*isLoaded=*/false);
267 }
268
Argyrios Kyrtzidisf37d0a62011-10-12 17:36:33 +0000269 // Check normal case, this entity begin location is after the previous one.
270 if (PreprocessedEntities.empty() ||
271 !SourceMgr.isBeforeInTranslationUnit(BeginLoc,
272 PreprocessedEntities.back()->getSourceRange().getBegin())) {
273 PreprocessedEntities.push_back(Entity);
Argyrios Kyrtzidisa9564502012-03-27 18:47:48 +0000274 return getPPEntityID(PreprocessedEntities.size()-1, /*isLoaded=*/false);
Argyrios Kyrtzidisf37d0a62011-10-12 17:36:33 +0000275 }
276
Argyrios Kyrtzidisa9564502012-03-27 18:47:48 +0000277 // The entity's location is not after the previous one; this can happen with
278 // include directives that form the filename using macros, e.g:
Argyrios Kyrtzidiseb994f42013-01-09 23:22:20 +0000279 // "#include MACRO(STUFF)"
280 // or with macro expansions inside macro arguments where the arguments are
281 // not expanded in the same order as listed, e.g:
282 // \code
283 // #define M1 1
284 // #define M2 2
285 // #define FM(x,y) y x
286 // FM(M1, M2)
287 // \endcode
Argyrios Kyrtzidisa9564502012-03-27 18:47:48 +0000288
Eugene Zelenkocb96ac62017-12-08 22:39:26 +0000289 using pp_iter = std::vector<PreprocessedEntity *>::iterator;
Argyrios Kyrtzidisa9564502012-03-27 18:47:48 +0000290
291 // Usually there are few macro expansions when defining the filename, do a
292 // linear search for a few entities.
293 unsigned count = 0;
294 for (pp_iter RI = PreprocessedEntities.end(),
295 Begin = PreprocessedEntities.begin();
296 RI != Begin && count < 4; --RI, ++count) {
297 pp_iter I = RI;
Argyrios Kyrtzidisf37d0a62011-10-12 17:36:33 +0000298 --I;
299 if (!SourceMgr.isBeforeInTranslationUnit(BeginLoc,
300 (*I)->getSourceRange().getBegin())) {
Argyrios Kyrtzidisa9564502012-03-27 18:47:48 +0000301 pp_iter insertI = PreprocessedEntities.insert(RI, Entity);
302 return getPPEntityID(insertI - PreprocessedEntities.begin(),
303 /*isLoaded=*/false);
Argyrios Kyrtzidisf37d0a62011-10-12 17:36:33 +0000304 }
305 }
Argyrios Kyrtzidisa9564502012-03-27 18:47:48 +0000306
307 // Linear search unsuccessful. Do a binary search.
308 pp_iter I = std::upper_bound(PreprocessedEntities.begin(),
309 PreprocessedEntities.end(),
310 BeginLoc,
311 PPEntityComp<&SourceRange::getBegin>(SourceMgr));
312 pp_iter insertI = PreprocessedEntities.insert(I, Entity);
313 return getPPEntityID(insertI - PreprocessedEntities.begin(),
314 /*isLoaded=*/false);
Douglas Gregor065f8d12010-03-18 17:52:52 +0000315}
316
Douglas Gregoraae92242010-03-19 21:51:54 +0000317void PreprocessingRecord::SetExternalSource(
Douglas Gregor4a9c39a2011-07-21 00:47:40 +0000318 ExternalPreprocessingRecordSource &Source) {
Douglas Gregoraae92242010-03-19 21:51:54 +0000319 assert(!ExternalSource &&
320 "Preprocessing record already has an external source");
321 ExternalSource = &Source;
Douglas Gregoraae92242010-03-19 21:51:54 +0000322}
323
Douglas Gregor4a9c39a2011-07-21 00:47:40 +0000324unsigned PreprocessingRecord::allocateLoadedEntities(unsigned NumEntities) {
325 unsigned Result = LoadedPreprocessedEntities.size();
Fangrui Song6907ce22018-07-30 19:24:48 +0000326 LoadedPreprocessedEntities.resize(LoadedPreprocessedEntities.size()
Douglas Gregor4a9c39a2011-07-21 00:47:40 +0000327 + NumEntities);
328 return Result;
329}
330
Cameron Desrochersb60f1b62018-01-15 19:14:16 +0000331unsigned PreprocessingRecord::allocateSkippedRanges(unsigned NumRanges) {
332 unsigned Result = SkippedRanges.size();
333 SkippedRanges.resize(SkippedRanges.size() + NumRanges);
334 SkippedRangesAllLoaded = false;
335 return Result;
336}
337
338void PreprocessingRecord::ensureSkippedRangesLoaded() {
339 if (SkippedRangesAllLoaded || !ExternalSource)
340 return;
341 for (unsigned Index = 0; Index != SkippedRanges.size(); ++Index) {
342 if (SkippedRanges[Index].isInvalid())
343 SkippedRanges[Index] = ExternalSource->ReadSkippedRange(Index);
344 }
345 SkippedRangesAllLoaded = true;
346}
347
Argyrios Kyrtzidis03c40c52011-09-15 18:02:56 +0000348void PreprocessingRecord::RegisterMacroDefinition(MacroInfo *Macro,
Richard Smith66a81862015-05-04 02:25:31 +0000349 MacroDefinitionRecord *Def) {
Argyrios Kyrtzidis832de9f2013-02-22 18:35:59 +0000350 MacroDefinitions[Macro] = Def;
Douglas Gregoraae92242010-03-19 21:51:54 +0000351}
352
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000353/// Retrieve the preprocessed entity at the given ID.
Argyrios Kyrtzidis03c40c52011-09-15 18:02:56 +0000354PreprocessedEntity *PreprocessingRecord::getPreprocessedEntity(PPEntityID PPID){
Argyrios Kyrtzidisabc721a2012-10-05 00:22:28 +0000355 if (PPID.ID < 0) {
356 unsigned Index = -PPID.ID - 1;
357 assert(Index < LoadedPreprocessedEntities.size() &&
Argyrios Kyrtzidis03c40c52011-09-15 18:02:56 +0000358 "Out-of bounds loaded preprocessed entity");
Argyrios Kyrtzidisabc721a2012-10-05 00:22:28 +0000359 return getLoadedPreprocessedEntity(Index);
Argyrios Kyrtzidis03c40c52011-09-15 18:02:56 +0000360 }
Argyrios Kyrtzidisabc721a2012-10-05 00:22:28 +0000361
362 if (PPID.ID == 0)
Craig Topperd2d442c2014-05-17 23:10:59 +0000363 return nullptr;
Argyrios Kyrtzidisabc721a2012-10-05 00:22:28 +0000364 unsigned Index = PPID.ID - 1;
365 assert(Index < PreprocessedEntities.size() &&
Argyrios Kyrtzidis03c40c52011-09-15 18:02:56 +0000366 "Out-of bounds local preprocessed entity");
Argyrios Kyrtzidisabc721a2012-10-05 00:22:28 +0000367 return PreprocessedEntities[Index];
Argyrios Kyrtzidis03c40c52011-09-15 18:02:56 +0000368}
369
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000370/// Retrieve the loaded preprocessed entity at the given index.
Argyrios Kyrtzidis03c40c52011-09-15 18:02:56 +0000371PreprocessedEntity *
372PreprocessingRecord::getLoadedPreprocessedEntity(unsigned Index) {
Fangrui Song6907ce22018-07-30 19:24:48 +0000373 assert(Index < LoadedPreprocessedEntities.size() &&
Argyrios Kyrtzidis03c40c52011-09-15 18:02:56 +0000374 "Out-of bounds loaded preprocessed entity");
375 assert(ExternalSource && "No external source to load from");
376 PreprocessedEntity *&Entity = LoadedPreprocessedEntities[Index];
377 if (!Entity) {
378 Entity = ExternalSource->ReadPreprocessedEntity(Index);
379 if (!Entity) // Failed to load.
380 Entity = new (*this)
381 PreprocessedEntity(PreprocessedEntity::InvalidKind, SourceRange());
382 }
383 return Entity;
Douglas Gregoraae92242010-03-19 21:51:54 +0000384}
385
Richard Smith66a81862015-05-04 02:25:31 +0000386MacroDefinitionRecord *
387PreprocessingRecord::findMacroDefinition(const MacroInfo *MI) {
388 llvm::DenseMap<const MacroInfo *, MacroDefinitionRecord *>::iterator Pos =
389 MacroDefinitions.find(MI);
Douglas Gregor7dc87222010-03-19 17:12:43 +0000390 if (Pos == MacroDefinitions.end())
Craig Topperd2d442c2014-05-17 23:10:59 +0000391 return nullptr;
Argyrios Kyrtzidis832de9f2013-02-22 18:35:59 +0000392
393 return Pos->second;
Douglas Gregor7dc87222010-03-19 17:12:43 +0000394}
395
Argyrios Kyrtzidisf77b0f82012-12-08 02:21:17 +0000396void PreprocessingRecord::addMacroExpansion(const Token &Id,
397 const MacroInfo *MI,
398 SourceRange Range) {
Argyrios Kyrtzidis335c5a42012-02-25 02:41:16 +0000399 // We don't record nested macro expansions.
400 if (Id.getLocation().isMacroID())
Douglas Gregor998caea2011-05-06 16:33:08 +0000401 return;
402
Argyrios Kyrtzidis80f78b92011-09-08 17:18:41 +0000403 if (MI->isBuiltinMacro())
Richard Smith66a81862015-05-04 02:25:31 +0000404 addPreprocessedEntity(new (*this)
405 MacroExpansion(Id.getIdentifierInfo(), Range));
406 else if (MacroDefinitionRecord *Def = findMacroDefinition(MI))
407 addPreprocessedEntity(new (*this) MacroExpansion(Def, Range));
Douglas Gregor7dc87222010-03-19 17:12:43 +0000408}
409
Argyrios Kyrtzidisf77b0f82012-12-08 02:21:17 +0000410void PreprocessingRecord::Ifdef(SourceLocation Loc, const Token &MacroNameTok,
Richard Smith36bd40d2015-05-04 03:15:40 +0000411 const MacroDefinition &MD) {
Argyrios Kyrtzidisf77b0f82012-12-08 02:21:17 +0000412 // This is not actually a macro expansion but record it as a macro reference.
Argyrios Kyrtzidisfead64b2013-02-24 00:05:14 +0000413 if (MD)
Richard Smith36bd40d2015-05-04 03:15:40 +0000414 addMacroExpansion(MacroNameTok, MD.getMacroInfo(),
Argyrios Kyrtzidisb6210df2013-03-26 17:17:01 +0000415 MacroNameTok.getLocation());
Argyrios Kyrtzidisf77b0f82012-12-08 02:21:17 +0000416}
417
418void PreprocessingRecord::Ifndef(SourceLocation Loc, const Token &MacroNameTok,
Richard Smith36bd40d2015-05-04 03:15:40 +0000419 const MacroDefinition &MD) {
Argyrios Kyrtzidisf77b0f82012-12-08 02:21:17 +0000420 // This is not actually a macro expansion but record it as a macro reference.
Argyrios Kyrtzidisfead64b2013-02-24 00:05:14 +0000421 if (MD)
Richard Smith36bd40d2015-05-04 03:15:40 +0000422 addMacroExpansion(MacroNameTok, MD.getMacroInfo(),
Argyrios Kyrtzidisb6210df2013-03-26 17:17:01 +0000423 MacroNameTok.getLocation());
Argyrios Kyrtzidisf77b0f82012-12-08 02:21:17 +0000424}
425
426void PreprocessingRecord::Defined(const Token &MacroNameTok,
Richard Smith36bd40d2015-05-04 03:15:40 +0000427 const MacroDefinition &MD,
John Thompsoncda95fe2013-07-19 18:50:04 +0000428 SourceRange Range) {
Argyrios Kyrtzidisf77b0f82012-12-08 02:21:17 +0000429 // This is not actually a macro expansion but record it as a macro reference.
Argyrios Kyrtzidisfead64b2013-02-24 00:05:14 +0000430 if (MD)
Richard Smith36bd40d2015-05-04 03:15:40 +0000431 addMacroExpansion(MacroNameTok, MD.getMacroInfo(),
Argyrios Kyrtzidisb6210df2013-03-26 17:17:01 +0000432 MacroNameTok.getLocation());
Argyrios Kyrtzidisf77b0f82012-12-08 02:21:17 +0000433}
434
Vedant Kumar3919a502017-09-11 20:47:42 +0000435void PreprocessingRecord::SourceRangeSkipped(SourceRange Range,
436 SourceLocation EndifLoc) {
Cameron Desrochersb60f1b62018-01-15 19:14:16 +0000437 assert(Range.isValid());
Vedant Kumar3919a502017-09-11 20:47:42 +0000438 SkippedRanges.emplace_back(Range.getBegin(), EndifLoc);
Argyrios Kyrtzidis9ef57752013-12-05 08:19:32 +0000439}
440
Richard Smith36bd40d2015-05-04 03:15:40 +0000441void PreprocessingRecord::MacroExpands(const Token &Id,
442 const MacroDefinition &MD,
Argyrios Kyrtzidis37e48ff2013-05-03 22:31:32 +0000443 SourceRange Range,
444 const MacroArgs *Args) {
Richard Smith36bd40d2015-05-04 03:15:40 +0000445 addMacroExpansion(Id, MD.getMacroInfo(), Range);
Argyrios Kyrtzidisf77b0f82012-12-08 02:21:17 +0000446}
447
Craig Silverstein1a9ca212010-11-19 21:33:15 +0000448void PreprocessingRecord::MacroDefined(const Token &Id,
Argyrios Kyrtzidisfead64b2013-02-24 00:05:14 +0000449 const MacroDirective *MD) {
Argyrios Kyrtzidisb6210df2013-03-26 17:17:01 +0000450 const MacroInfo *MI = MD->getMacroInfo();
Douglas Gregor7dc87222010-03-19 17:12:43 +0000451 SourceRange R(MI->getDefinitionLoc(), MI->getDefinitionEndLoc());
Richard Smith66a81862015-05-04 02:25:31 +0000452 MacroDefinitionRecord *Def =
453 new (*this) MacroDefinitionRecord(Id.getIdentifierInfo(), R);
Argyrios Kyrtzidis832de9f2013-02-22 18:35:59 +0000454 addPreprocessedEntity(Def);
455 MacroDefinitions[MI] = Def;
Douglas Gregor7dc87222010-03-19 17:12:43 +0000456}
Douglas Gregoraae92242010-03-19 21:51:54 +0000457
Craig Silverstein1a9ca212010-11-19 21:33:15 +0000458void PreprocessingRecord::MacroUndefined(const Token &Id,
Vedant Kumar349a6242017-04-26 21:05:44 +0000459 const MacroDefinition &MD,
460 const MacroDirective *Undef) {
Richard Smith36bd40d2015-05-04 03:15:40 +0000461 MD.forAllDefinitions([&](MacroInfo *MI) { MacroDefinitions.erase(MI); });
Douglas Gregor8aaca672010-03-19 21:58:23 +0000462}
463
Chandler Carruth3cc331a2011-03-16 18:34:36 +0000464void PreprocessingRecord::InclusionDirective(
465 SourceLocation HashLoc,
Eugene Zelenkocb96ac62017-12-08 22:39:26 +0000466 const Token &IncludeTok,
Chris Lattner0e62c1c2011-07-23 10:55:15 +0000467 StringRef FileName,
Chandler Carruth3cc331a2011-03-16 18:34:36 +0000468 bool IsAngled,
Argyrios Kyrtzidis4fcd2882012-09-27 01:42:07 +0000469 CharSourceRange FilenameRange,
Chandler Carruth3cc331a2011-03-16 18:34:36 +0000470 const FileEntry *File,
Chris Lattner0e62c1c2011-07-23 10:55:15 +0000471 StringRef SearchPath,
Argyrios Kyrtzidis19d78b72012-09-29 01:06:10 +0000472 StringRef RelativePath,
Fangrui Song6907ce22018-07-30 19:24:48 +0000473 const Module *Imported,
Julie Hockett96fbe582018-05-10 19:05:36 +0000474 SrcMgr::CharacteristicKind FileType) {
Douglas Gregor796d76a2010-10-20 22:00:55 +0000475 InclusionDirective::InclusionKind Kind = InclusionDirective::Include;
Fangrui Song6907ce22018-07-30 19:24:48 +0000476
Douglas Gregor796d76a2010-10-20 22:00:55 +0000477 switch (IncludeTok.getIdentifierInfo()->getPPKeywordID()) {
Fangrui Song6907ce22018-07-30 19:24:48 +0000478 case tok::pp_include:
479 Kind = InclusionDirective::Include;
Douglas Gregor796d76a2010-10-20 22:00:55 +0000480 break;
Fangrui Song6907ce22018-07-30 19:24:48 +0000481
482 case tok::pp_import:
483 Kind = InclusionDirective::Import;
Douglas Gregor796d76a2010-10-20 22:00:55 +0000484 break;
Fangrui Song6907ce22018-07-30 19:24:48 +0000485
486 case tok::pp_include_next:
487 Kind = InclusionDirective::IncludeNext;
Douglas Gregor796d76a2010-10-20 22:00:55 +0000488 break;
Fangrui Song6907ce22018-07-30 19:24:48 +0000489
490 case tok::pp___include_macros:
Douglas Gregor796d76a2010-10-20 22:00:55 +0000491 Kind = InclusionDirective::IncludeMacros;
492 break;
Fangrui Song6907ce22018-07-30 19:24:48 +0000493
Douglas Gregor796d76a2010-10-20 22:00:55 +0000494 default:
495 llvm_unreachable("Unknown include directive kind");
Douglas Gregor796d76a2010-10-20 22:00:55 +0000496 }
Argyrios Kyrtzidis4fcd2882012-09-27 01:42:07 +0000497
498 SourceLocation EndLoc;
499 if (!IsAngled) {
500 EndLoc = FilenameRange.getBegin();
501 } else {
502 EndLoc = FilenameRange.getEnd();
503 if (FilenameRange.isCharRange())
504 EndLoc = EndLoc.getLocWithOffset(-1); // the InclusionDirective expects
505 // a token range.
506 }
Eugene Zelenkocb96ac62017-12-08 22:39:26 +0000507 clang::InclusionDirective *ID =
508 new (*this) clang::InclusionDirective(*this, Kind, FileName, !IsAngled,
509 (bool)Imported, File,
510 SourceRange(HashLoc, EndLoc));
Argyrios Kyrtzidis64f63812011-09-19 20:40:25 +0000511 addPreprocessedEntity(ID);
Douglas Gregor796d76a2010-10-20 22:00:55 +0000512}
Ted Kremenek182543a2011-07-26 21:17:24 +0000513
514size_t PreprocessingRecord::getTotalMemory() const {
515 return BumpAlloc.getTotalMemory()
Ted Kremenekf1c38812011-07-27 18:41:20 +0000516 + llvm::capacity_in_bytes(MacroDefinitions)
517 + llvm::capacity_in_bytes(PreprocessedEntities)
Cameron Desrochersb60f1b62018-01-15 19:14:16 +0000518 + llvm::capacity_in_bytes(LoadedPreprocessedEntities)
519 + llvm::capacity_in_bytes(SkippedRanges);
Ted Kremenek182543a2011-07-26 21:17:24 +0000520}