1cb96ac64SEugene Zelenko //===- PreprocessingRecord.cpp - Record of Preprocessing ------------------===//
2065f8d11SDouglas Gregor //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6065f8d11SDouglas Gregor //
7065f8d11SDouglas Gregor //===----------------------------------------------------------------------===//
8065f8d11SDouglas Gregor //
9065f8d11SDouglas Gregor // This file implements the PreprocessingRecord class, which maintains a record
10065f8d11SDouglas Gregor // of what occurred during preprocessing, and its helpers.
11065f8d11SDouglas Gregor //
12065f8d11SDouglas Gregor //===----------------------------------------------------------------------===//
13cb96ac64SEugene Zelenko
14065f8d11SDouglas Gregor #include "clang/Lex/PreprocessingRecord.h"
15cb96ac64SEugene Zelenko #include "clang/Basic/IdentifierTable.h"
16cb96ac64SEugene Zelenko #include "clang/Basic/LLVM.h"
17cb96ac64SEugene Zelenko #include "clang/Basic/SourceLocation.h"
18cb96ac64SEugene Zelenko #include "clang/Basic/SourceManager.h"
19cb96ac64SEugene Zelenko #include "clang/Basic/TokenKinds.h"
20065f8d11SDouglas Gregor #include "clang/Lex/MacroInfo.h"
21065f8d11SDouglas Gregor #include "clang/Lex/Token.h"
22cb96ac64SEugene Zelenko #include "llvm/ADT/DenseMap.h"
23cb96ac64SEugene Zelenko #include "llvm/ADT/Optional.h"
24cb96ac64SEugene Zelenko #include "llvm/ADT/StringRef.h"
25cb96ac64SEugene Zelenko #include "llvm/ADT/iterator_range.h"
26f1c38811STed Kremenek #include "llvm/Support/Capacity.h"
27cb96ac64SEugene Zelenko #include "llvm/Support/Casting.h"
283a02247dSChandler Carruth #include "llvm/Support/ErrorHandling.h"
29cb96ac64SEugene Zelenko #include <algorithm>
30cb96ac64SEugene Zelenko #include <cassert>
31cb96ac64SEugene Zelenko #include <cstddef>
32cb96ac64SEugene Zelenko #include <cstring>
33cb96ac64SEugene Zelenko #include <iterator>
34cb96ac64SEugene Zelenko #include <utility>
35cb96ac64SEugene Zelenko #include <vector>
36065f8d11SDouglas Gregor
37065f8d11SDouglas Gregor using namespace clang;
38065f8d11SDouglas Gregor
39cb96ac64SEugene Zelenko ExternalPreprocessingRecordSource::~ExternalPreprocessingRecordSource() =
40cb96ac64SEugene Zelenko default;
41aae9224eSDouglas Gregor
InclusionDirective(PreprocessingRecord & PPRec,InclusionKind Kind,StringRef FileName,bool InQuotes,bool ImportedModule,Optional<FileEntryRef> File,SourceRange Range)42f09b6c9cSDouglas Gregor InclusionDirective::InclusionDirective(PreprocessingRecord &PPRec,
43c3f89253SBenjamin Kramer InclusionKind Kind, StringRef FileName,
44f590e094SArgyrios Kyrtzidis bool InQuotes, bool ImportedModule,
45d79ad2f1SJan Svoboda Optional<FileEntryRef> File,
46d79ad2f1SJan Svoboda SourceRange Range)
47c3f89253SBenjamin Kramer : PreprocessingDirective(InclusionDirectiveKind, Range), InQuotes(InQuotes),
48c3f89253SBenjamin Kramer Kind(Kind), ImportedModule(ImportedModule), File(File) {
49c3f89253SBenjamin Kramer char *Memory = (char *)PPRec.Allocate(FileName.size() + 1, alignof(char));
50f09b6c9cSDouglas Gregor memcpy(Memory, FileName.data(), FileName.size());
51f09b6c9cSDouglas Gregor Memory[FileName.size()] = 0;
520e62c1ccSChris Lattner this->FileName = StringRef(Memory, FileName.size());
53f09b6c9cSDouglas Gregor }
54f09b6c9cSDouglas Gregor
PreprocessingRecord(SourceManager & SM)55cb96ac64SEugene Zelenko PreprocessingRecord::PreprocessingRecord(SourceManager &SM) : SourceMgr(SM) {}
56aae9224eSDouglas Gregor
579fc8faf9SAdrian Prantl /// Returns a pair of [Begin, End) iterators of preprocessed entities
58303d8d49SJames Dennett /// that source range \p Range encompasses.
59b4ef6683SBenjamin Kramer llvm::iterator_range<PreprocessingRecord::iterator>
getPreprocessedEntitiesInRange(SourceRange Range)6064f63810SArgyrios Kyrtzidis PreprocessingRecord::getPreprocessedEntitiesInRange(SourceRange Range) {
6164f63810SArgyrios Kyrtzidis if (Range.isInvalid())
62b4ef6683SBenjamin Kramer return llvm::make_range(iterator(), iterator());
63429ec024SArgyrios Kyrtzidis
64429ec024SArgyrios Kyrtzidis if (CachedRangeQuery.Range == Range) {
65b4ef6683SBenjamin Kramer return llvm::make_range(iterator(this, CachedRangeQuery.Result.first),
66429ec024SArgyrios Kyrtzidis iterator(this, CachedRangeQuery.Result.second));
67429ec024SArgyrios Kyrtzidis }
68429ec024SArgyrios Kyrtzidis
69abc721abSArgyrios Kyrtzidis std::pair<int, int> Res = getPreprocessedEntitiesInRangeSlow(Range);
70429ec024SArgyrios Kyrtzidis
71429ec024SArgyrios Kyrtzidis CachedRangeQuery.Range = Range;
72429ec024SArgyrios Kyrtzidis CachedRangeQuery.Result = Res;
73429ec024SArgyrios Kyrtzidis
74b4ef6683SBenjamin Kramer return llvm::make_range(iterator(this, Res.first),
75b4ef6683SBenjamin Kramer iterator(this, Res.second));
76429ec024SArgyrios Kyrtzidis }
77429ec024SArgyrios Kyrtzidis
isPreprocessedEntityIfInFileID(PreprocessedEntity * PPE,FileID FID,SourceManager & SM)78429ec024SArgyrios Kyrtzidis static bool isPreprocessedEntityIfInFileID(PreprocessedEntity *PPE, FileID FID,
79429ec024SArgyrios Kyrtzidis SourceManager &SM) {
808b563665SYaron Keren assert(FID.isValid());
81429ec024SArgyrios Kyrtzidis if (!PPE)
82429ec024SArgyrios Kyrtzidis return false;
83429ec024SArgyrios Kyrtzidis
84429ec024SArgyrios Kyrtzidis SourceLocation Loc = PPE->getSourceRange().getBegin();
85429ec024SArgyrios Kyrtzidis if (Loc.isInvalid())
86429ec024SArgyrios Kyrtzidis return false;
87429ec024SArgyrios Kyrtzidis
887a3cbb29SDavid Blaikie return SM.isInFileID(SM.getFileLoc(Loc), FID);
89429ec024SArgyrios Kyrtzidis }
90429ec024SArgyrios Kyrtzidis
919fc8faf9SAdrian Prantl /// Returns true if the preprocessed entity that \arg PPEI iterator
92429ec024SArgyrios Kyrtzidis /// points to is coming from the file \arg FID.
93429ec024SArgyrios Kyrtzidis ///
94429ec024SArgyrios Kyrtzidis /// Can be used to avoid implicit deserializations of preallocated
95429ec024SArgyrios Kyrtzidis /// preprocessed entities if we only care about entities of a specific file
96303d8d49SJames Dennett /// and not from files \#included in the range given at
97429ec024SArgyrios Kyrtzidis /// \see getPreprocessedEntitiesInRange.
isEntityInFileID(iterator PPEI,FileID FID)98429ec024SArgyrios Kyrtzidis bool PreprocessingRecord::isEntityInFileID(iterator PPEI, FileID FID) {
99429ec024SArgyrios Kyrtzidis if (FID.isInvalid())
100429ec024SArgyrios Kyrtzidis return false;
101429ec024SArgyrios Kyrtzidis
10215b97178SBenjamin Kramer int Pos = std::distance(iterator(this, 0), PPEI);
103abc721abSArgyrios Kyrtzidis if (Pos < 0) {
104962b2210SArgyrios Kyrtzidis if (unsigned(-Pos-1) >= LoadedPreprocessedEntities.size()) {
105962b2210SArgyrios Kyrtzidis assert(0 && "Out-of bounds loaded preprocessed entity");
106962b2210SArgyrios Kyrtzidis return false;
107962b2210SArgyrios Kyrtzidis }
108429ec024SArgyrios Kyrtzidis assert(ExternalSource && "No external source to load from");
109abc721abSArgyrios Kyrtzidis unsigned LoadedIndex = LoadedPreprocessedEntities.size()+Pos;
110429ec024SArgyrios Kyrtzidis if (PreprocessedEntity *PPE = LoadedPreprocessedEntities[LoadedIndex])
111429ec024SArgyrios Kyrtzidis return isPreprocessedEntityIfInFileID(PPE, FID, SourceMgr);
112429ec024SArgyrios Kyrtzidis
113429ec024SArgyrios Kyrtzidis // See if the external source can see if the entity is in the file without
114429ec024SArgyrios Kyrtzidis // deserializing it.
11505785d16SDavid Blaikie Optional<bool> IsInFile =
11605785d16SDavid Blaikie ExternalSource->isPreprocessedEntityInFileID(LoadedIndex, FID);
11797afce08SKazu Hirata if (IsInFile)
118*cb2c8f69SKazu Hirata return IsInFile.value();
119429ec024SArgyrios Kyrtzidis
120429ec024SArgyrios Kyrtzidis // The external source did not provide a definite answer, go and deserialize
121429ec024SArgyrios Kyrtzidis // the entity to check it.
122429ec024SArgyrios Kyrtzidis return isPreprocessedEntityIfInFileID(
123429ec024SArgyrios Kyrtzidis getLoadedPreprocessedEntity(LoadedIndex),
124429ec024SArgyrios Kyrtzidis FID, SourceMgr);
125429ec024SArgyrios Kyrtzidis }
126429ec024SArgyrios Kyrtzidis
127962b2210SArgyrios Kyrtzidis if (unsigned(Pos) >= PreprocessedEntities.size()) {
128962b2210SArgyrios Kyrtzidis assert(0 && "Out-of bounds local preprocessed entity");
129962b2210SArgyrios Kyrtzidis return false;
130962b2210SArgyrios Kyrtzidis }
131abc721abSArgyrios Kyrtzidis return isPreprocessedEntityIfInFileID(PreprocessedEntities[Pos],
132429ec024SArgyrios Kyrtzidis FID, SourceMgr);
133429ec024SArgyrios Kyrtzidis }
134429ec024SArgyrios Kyrtzidis
1359fc8faf9SAdrian Prantl /// Returns a pair of [Begin, End) iterators of preprocessed entities
136429ec024SArgyrios Kyrtzidis /// that source range \arg R encompasses.
137abc721abSArgyrios Kyrtzidis std::pair<int, int>
getPreprocessedEntitiesInRangeSlow(SourceRange Range)138429ec024SArgyrios Kyrtzidis PreprocessingRecord::getPreprocessedEntitiesInRangeSlow(SourceRange Range) {
139429ec024SArgyrios Kyrtzidis assert(Range.isValid());
14064f63810SArgyrios Kyrtzidis assert(!SourceMgr.isBeforeInTranslationUnit(Range.getEnd(),Range.getBegin()));
14164f63810SArgyrios Kyrtzidis
14264f63810SArgyrios Kyrtzidis std::pair<unsigned, unsigned>
14364f63810SArgyrios Kyrtzidis Local = findLocalPreprocessedEntitiesInRange(Range);
14464f63810SArgyrios Kyrtzidis
14564f63810SArgyrios Kyrtzidis // Check if range spans local entities.
14664f63810SArgyrios Kyrtzidis if (!ExternalSource || SourceMgr.isLocalSourceLocation(Range.getBegin()))
147429ec024SArgyrios Kyrtzidis return std::make_pair(Local.first, Local.second);
14864f63810SArgyrios Kyrtzidis
14964f63810SArgyrios Kyrtzidis std::pair<unsigned, unsigned>
15064f63810SArgyrios Kyrtzidis Loaded = ExternalSource->findPreprocessedEntitiesInRange(Range);
15164f63810SArgyrios Kyrtzidis
15264f63810SArgyrios Kyrtzidis // Check if range spans local entities.
15364f63810SArgyrios Kyrtzidis if (Loaded.first == Loaded.second)
154429ec024SArgyrios Kyrtzidis return std::make_pair(Local.first, Local.second);
15564f63810SArgyrios Kyrtzidis
15664f63810SArgyrios Kyrtzidis unsigned TotalLoaded = LoadedPreprocessedEntities.size();
15764f63810SArgyrios Kyrtzidis
15864f63810SArgyrios Kyrtzidis // Check if range spans loaded entities.
15964f63810SArgyrios Kyrtzidis if (Local.first == Local.second)
160429ec024SArgyrios Kyrtzidis return std::make_pair(int(Loaded.first)-TotalLoaded,
161429ec024SArgyrios Kyrtzidis int(Loaded.second)-TotalLoaded);
16264f63810SArgyrios Kyrtzidis
16364f63810SArgyrios Kyrtzidis // Range spands loaded and local entities.
164429ec024SArgyrios Kyrtzidis return std::make_pair(int(Loaded.first)-TotalLoaded, Local.second);
16564f63810SArgyrios Kyrtzidis }
16664f63810SArgyrios Kyrtzidis
16764f63810SArgyrios Kyrtzidis std::pair<unsigned, unsigned>
findLocalPreprocessedEntitiesInRange(SourceRange Range) const16864f63810SArgyrios Kyrtzidis PreprocessingRecord::findLocalPreprocessedEntitiesInRange(
16964f63810SArgyrios Kyrtzidis SourceRange Range) const {
17064f63810SArgyrios Kyrtzidis if (Range.isInvalid())
17164f63810SArgyrios Kyrtzidis return std::make_pair(0,0);
17264f63810SArgyrios Kyrtzidis assert(!SourceMgr.isBeforeInTranslationUnit(Range.getEnd(),Range.getBegin()));
17364f63810SArgyrios Kyrtzidis
17464f63810SArgyrios Kyrtzidis unsigned Begin = findBeginLocalPreprocessedEntity(Range.getBegin());
17564f63810SArgyrios Kyrtzidis unsigned End = findEndLocalPreprocessedEntity(Range.getEnd());
17664f63810SArgyrios Kyrtzidis return std::make_pair(Begin, End);
17764f63810SArgyrios Kyrtzidis }
17864f63810SArgyrios Kyrtzidis
17964f63810SArgyrios Kyrtzidis namespace {
18064f63810SArgyrios Kyrtzidis
18164f63810SArgyrios Kyrtzidis template <SourceLocation (SourceRange::*getRangeLoc)() const>
18264f63810SArgyrios Kyrtzidis struct PPEntityComp {
18364f63810SArgyrios Kyrtzidis const SourceManager &SM;
18464f63810SArgyrios Kyrtzidis
PPEntityComp__anone92e62850111::PPEntityComp18564f63810SArgyrios Kyrtzidis explicit PPEntityComp(const SourceManager &SM) : SM(SM) {}
18664f63810SArgyrios Kyrtzidis
operator ()__anone92e62850111::PPEntityComp1872e9d9cfcSBenjamin Kramer bool operator()(PreprocessedEntity *L, PreprocessedEntity *R) const {
1882e9d9cfcSBenjamin Kramer SourceLocation LHS = getLoc(L);
1892e9d9cfcSBenjamin Kramer SourceLocation RHS = getLoc(R);
1902e9d9cfcSBenjamin Kramer return SM.isBeforeInTranslationUnit(LHS, RHS);
1912e9d9cfcSBenjamin Kramer }
1922e9d9cfcSBenjamin Kramer
operator ()__anone92e62850111::PPEntityComp1932e9d9cfcSBenjamin Kramer bool operator()(PreprocessedEntity *L, SourceLocation RHS) const {
19464f63810SArgyrios Kyrtzidis SourceLocation LHS = getLoc(L);
19564f63810SArgyrios Kyrtzidis return SM.isBeforeInTranslationUnit(LHS, RHS);
19664f63810SArgyrios Kyrtzidis }
19764f63810SArgyrios Kyrtzidis
operator ()__anone92e62850111::PPEntityComp1982e9d9cfcSBenjamin Kramer bool operator()(SourceLocation LHS, PreprocessedEntity *R) const {
19964f63810SArgyrios Kyrtzidis SourceLocation RHS = getLoc(R);
20064f63810SArgyrios Kyrtzidis return SM.isBeforeInTranslationUnit(LHS, RHS);
20164f63810SArgyrios Kyrtzidis }
20264f63810SArgyrios Kyrtzidis
getLoc__anone92e62850111::PPEntityComp20364f63810SArgyrios Kyrtzidis SourceLocation getLoc(PreprocessedEntity *PPE) const {
204a35c4441SArgyrios Kyrtzidis SourceRange Range = PPE->getSourceRange();
205a35c4441SArgyrios Kyrtzidis return (Range.*getRangeLoc)();
20664f63810SArgyrios Kyrtzidis }
20764f63810SArgyrios Kyrtzidis };
20864f63810SArgyrios Kyrtzidis
209cb96ac64SEugene Zelenko } // namespace
21064f63810SArgyrios Kyrtzidis
findBeginLocalPreprocessedEntity(SourceLocation Loc) const21164f63810SArgyrios Kyrtzidis unsigned PreprocessingRecord::findBeginLocalPreprocessedEntity(
21264f63810SArgyrios Kyrtzidis SourceLocation Loc) const {
21364f63810SArgyrios Kyrtzidis if (SourceMgr.isLoadedSourceLocation(Loc))
21464f63810SArgyrios Kyrtzidis return 0;
21564f63810SArgyrios Kyrtzidis
216e523e389SArgyrios Kyrtzidis size_t Count = PreprocessedEntities.size();
217e523e389SArgyrios Kyrtzidis size_t Half;
21864f63810SArgyrios Kyrtzidis std::vector<PreprocessedEntity *>::const_iterator
219e523e389SArgyrios Kyrtzidis First = PreprocessedEntities.begin();
220e523e389SArgyrios Kyrtzidis std::vector<PreprocessedEntity *>::const_iterator I;
221e523e389SArgyrios Kyrtzidis
222e523e389SArgyrios Kyrtzidis // Do a binary search manually instead of using std::lower_bound because
223e523e389SArgyrios Kyrtzidis // The end locations of entities may be unordered (when a macro expansion
224e523e389SArgyrios Kyrtzidis // is inside another macro argument), but for this case it is not important
225e523e389SArgyrios Kyrtzidis // whether we get the first macro expansion or its containing macro.
226e523e389SArgyrios Kyrtzidis while (Count > 0) {
227e523e389SArgyrios Kyrtzidis Half = Count/2;
228e523e389SArgyrios Kyrtzidis I = First;
229e523e389SArgyrios Kyrtzidis std::advance(I, Half);
230e523e389SArgyrios Kyrtzidis if (SourceMgr.isBeforeInTranslationUnit((*I)->getSourceRange().getEnd(),
231e523e389SArgyrios Kyrtzidis Loc)){
232e523e389SArgyrios Kyrtzidis First = I;
233e523e389SArgyrios Kyrtzidis ++First;
234e523e389SArgyrios Kyrtzidis Count = Count - Half - 1;
235e523e389SArgyrios Kyrtzidis } else
236e523e389SArgyrios Kyrtzidis Count = Half;
237e523e389SArgyrios Kyrtzidis }
238e523e389SArgyrios Kyrtzidis
239e523e389SArgyrios Kyrtzidis return First - PreprocessedEntities.begin();
24064f63810SArgyrios Kyrtzidis }
24164f63810SArgyrios Kyrtzidis
2427264a474SFangrui Song unsigned
findEndLocalPreprocessedEntity(SourceLocation Loc) const2437264a474SFangrui Song PreprocessingRecord::findEndLocalPreprocessedEntity(SourceLocation Loc) const {
24464f63810SArgyrios Kyrtzidis if (SourceMgr.isLoadedSourceLocation(Loc))
24564f63810SArgyrios Kyrtzidis return 0;
24664f63810SArgyrios Kyrtzidis
2477264a474SFangrui Song auto I = llvm::upper_bound(PreprocessedEntities, Loc,
24864f63810SArgyrios Kyrtzidis PPEntityComp<&SourceRange::getBegin>(SourceMgr));
24964f63810SArgyrios Kyrtzidis return I - PreprocessedEntities.begin();
25064f63810SArgyrios Kyrtzidis }
25164f63810SArgyrios Kyrtzidis
252a956450eSArgyrios Kyrtzidis PreprocessingRecord::PPEntityID
addPreprocessedEntity(PreprocessedEntity * Entity)253a956450eSArgyrios Kyrtzidis PreprocessingRecord::addPreprocessedEntity(PreprocessedEntity *Entity) {
25445e8cf57SArgyrios Kyrtzidis assert(Entity);
255f37d0a61SArgyrios Kyrtzidis SourceLocation BeginLoc = Entity->getSourceRange().getBegin();
256f37d0a61SArgyrios Kyrtzidis
25766a8186eSRichard Smith if (isa<MacroDefinitionRecord>(Entity)) {
258a956450eSArgyrios Kyrtzidis assert((PreprocessedEntities.empty() ||
25966a8186eSRichard Smith !SourceMgr.isBeforeInTranslationUnit(
26066a8186eSRichard Smith BeginLoc,
261a956450eSArgyrios Kyrtzidis PreprocessedEntities.back()->getSourceRange().getBegin())) &&
262eb994f40SArgyrios Kyrtzidis "a macro definition was encountered out-of-order");
263a956450eSArgyrios Kyrtzidis PreprocessedEntities.push_back(Entity);
264a956450eSArgyrios Kyrtzidis return getPPEntityID(PreprocessedEntities.size()-1, /*isLoaded=*/false);
265a956450eSArgyrios Kyrtzidis }
266a956450eSArgyrios Kyrtzidis
267f37d0a61SArgyrios Kyrtzidis // Check normal case, this entity begin location is after the previous one.
268f37d0a61SArgyrios Kyrtzidis if (PreprocessedEntities.empty() ||
269f37d0a61SArgyrios Kyrtzidis !SourceMgr.isBeforeInTranslationUnit(BeginLoc,
270f37d0a61SArgyrios Kyrtzidis PreprocessedEntities.back()->getSourceRange().getBegin())) {
271065f8d11SDouglas Gregor PreprocessedEntities.push_back(Entity);
272a956450eSArgyrios Kyrtzidis return getPPEntityID(PreprocessedEntities.size()-1, /*isLoaded=*/false);
273f37d0a61SArgyrios Kyrtzidis }
274f37d0a61SArgyrios Kyrtzidis
275a956450eSArgyrios Kyrtzidis // The entity's location is not after the previous one; this can happen with
276a956450eSArgyrios Kyrtzidis // include directives that form the filename using macros, e.g:
277eb994f40SArgyrios Kyrtzidis // "#include MACRO(STUFF)"
278eb994f40SArgyrios Kyrtzidis // or with macro expansions inside macro arguments where the arguments are
279eb994f40SArgyrios Kyrtzidis // not expanded in the same order as listed, e.g:
280eb994f40SArgyrios Kyrtzidis // \code
281eb994f40SArgyrios Kyrtzidis // #define M1 1
282eb994f40SArgyrios Kyrtzidis // #define M2 2
283eb994f40SArgyrios Kyrtzidis // #define FM(x,y) y x
284eb994f40SArgyrios Kyrtzidis // FM(M1, M2)
285eb994f40SArgyrios Kyrtzidis // \endcode
286a956450eSArgyrios Kyrtzidis
287cb96ac64SEugene Zelenko using pp_iter = std::vector<PreprocessedEntity *>::iterator;
288a956450eSArgyrios Kyrtzidis
289a956450eSArgyrios Kyrtzidis // Usually there are few macro expansions when defining the filename, do a
290a956450eSArgyrios Kyrtzidis // linear search for a few entities.
291a956450eSArgyrios Kyrtzidis unsigned count = 0;
292a956450eSArgyrios Kyrtzidis for (pp_iter RI = PreprocessedEntities.end(),
293a956450eSArgyrios Kyrtzidis Begin = PreprocessedEntities.begin();
294a956450eSArgyrios Kyrtzidis RI != Begin && count < 4; --RI, ++count) {
295a956450eSArgyrios Kyrtzidis pp_iter I = RI;
296f37d0a61SArgyrios Kyrtzidis --I;
297f37d0a61SArgyrios Kyrtzidis if (!SourceMgr.isBeforeInTranslationUnit(BeginLoc,
298f37d0a61SArgyrios Kyrtzidis (*I)->getSourceRange().getBegin())) {
299a956450eSArgyrios Kyrtzidis pp_iter insertI = PreprocessedEntities.insert(RI, Entity);
300a956450eSArgyrios Kyrtzidis return getPPEntityID(insertI - PreprocessedEntities.begin(),
301a956450eSArgyrios Kyrtzidis /*isLoaded=*/false);
302f37d0a61SArgyrios Kyrtzidis }
303f37d0a61SArgyrios Kyrtzidis }
304a956450eSArgyrios Kyrtzidis
305a956450eSArgyrios Kyrtzidis // Linear search unsuccessful. Do a binary search.
3067264a474SFangrui Song pp_iter I =
3077264a474SFangrui Song llvm::upper_bound(PreprocessedEntities, BeginLoc,
308a956450eSArgyrios Kyrtzidis PPEntityComp<&SourceRange::getBegin>(SourceMgr));
309a956450eSArgyrios Kyrtzidis pp_iter insertI = PreprocessedEntities.insert(I, Entity);
310a956450eSArgyrios Kyrtzidis return getPPEntityID(insertI - PreprocessedEntities.begin(),
311a956450eSArgyrios Kyrtzidis /*isLoaded=*/false);
312065f8d11SDouglas Gregor }
313065f8d11SDouglas Gregor
SetExternalSource(ExternalPreprocessingRecordSource & Source)314aae9224eSDouglas Gregor void PreprocessingRecord::SetExternalSource(
3154a9c39a2SDouglas Gregor ExternalPreprocessingRecordSource &Source) {
316aae9224eSDouglas Gregor assert(!ExternalSource &&
317aae9224eSDouglas Gregor "Preprocessing record already has an external source");
318aae9224eSDouglas Gregor ExternalSource = &Source;
319aae9224eSDouglas Gregor }
320aae9224eSDouglas Gregor
allocateLoadedEntities(unsigned NumEntities)3214a9c39a2SDouglas Gregor unsigned PreprocessingRecord::allocateLoadedEntities(unsigned NumEntities) {
3224a9c39a2SDouglas Gregor unsigned Result = LoadedPreprocessedEntities.size();
3234a9c39a2SDouglas Gregor LoadedPreprocessedEntities.resize(LoadedPreprocessedEntities.size()
3244a9c39a2SDouglas Gregor + NumEntities);
3254a9c39a2SDouglas Gregor return Result;
3264a9c39a2SDouglas Gregor }
3274a9c39a2SDouglas Gregor
allocateSkippedRanges(unsigned NumRanges)328b60f1b6dSCameron Desrochers unsigned PreprocessingRecord::allocateSkippedRanges(unsigned NumRanges) {
329b60f1b6dSCameron Desrochers unsigned Result = SkippedRanges.size();
330b60f1b6dSCameron Desrochers SkippedRanges.resize(SkippedRanges.size() + NumRanges);
331b60f1b6dSCameron Desrochers SkippedRangesAllLoaded = false;
332b60f1b6dSCameron Desrochers return Result;
333b60f1b6dSCameron Desrochers }
334b60f1b6dSCameron Desrochers
ensureSkippedRangesLoaded()335b60f1b6dSCameron Desrochers void PreprocessingRecord::ensureSkippedRangesLoaded() {
336b60f1b6dSCameron Desrochers if (SkippedRangesAllLoaded || !ExternalSource)
337b60f1b6dSCameron Desrochers return;
338b60f1b6dSCameron Desrochers for (unsigned Index = 0; Index != SkippedRanges.size(); ++Index) {
339b60f1b6dSCameron Desrochers if (SkippedRanges[Index].isInvalid())
340b60f1b6dSCameron Desrochers SkippedRanges[Index] = ExternalSource->ReadSkippedRange(Index);
341b60f1b6dSCameron Desrochers }
342b60f1b6dSCameron Desrochers SkippedRangesAllLoaded = true;
343b60f1b6dSCameron Desrochers }
344b60f1b6dSCameron Desrochers
RegisterMacroDefinition(MacroInfo * Macro,MacroDefinitionRecord * Def)34503c40c51SArgyrios Kyrtzidis void PreprocessingRecord::RegisterMacroDefinition(MacroInfo *Macro,
34666a8186eSRichard Smith MacroDefinitionRecord *Def) {
347832de9fcSArgyrios Kyrtzidis MacroDefinitions[Macro] = Def;
348aae9224eSDouglas Gregor }
349aae9224eSDouglas Gregor
3509fc8faf9SAdrian Prantl /// Retrieve the preprocessed entity at the given ID.
getPreprocessedEntity(PPEntityID PPID)35103c40c51SArgyrios Kyrtzidis PreprocessedEntity *PreprocessingRecord::getPreprocessedEntity(PPEntityID PPID){
352abc721abSArgyrios Kyrtzidis if (PPID.ID < 0) {
353abc721abSArgyrios Kyrtzidis unsigned Index = -PPID.ID - 1;
354abc721abSArgyrios Kyrtzidis assert(Index < LoadedPreprocessedEntities.size() &&
35503c40c51SArgyrios Kyrtzidis "Out-of bounds loaded preprocessed entity");
356abc721abSArgyrios Kyrtzidis return getLoadedPreprocessedEntity(Index);
35703c40c51SArgyrios Kyrtzidis }
358abc721abSArgyrios Kyrtzidis
359abc721abSArgyrios Kyrtzidis if (PPID.ID == 0)
360d2d442caSCraig Topper return nullptr;
361abc721abSArgyrios Kyrtzidis unsigned Index = PPID.ID - 1;
362abc721abSArgyrios Kyrtzidis assert(Index < PreprocessedEntities.size() &&
36303c40c51SArgyrios Kyrtzidis "Out-of bounds local preprocessed entity");
364abc721abSArgyrios Kyrtzidis return PreprocessedEntities[Index];
36503c40c51SArgyrios Kyrtzidis }
36603c40c51SArgyrios Kyrtzidis
3679fc8faf9SAdrian Prantl /// Retrieve the loaded preprocessed entity at the given index.
36803c40c51SArgyrios Kyrtzidis PreprocessedEntity *
getLoadedPreprocessedEntity(unsigned Index)36903c40c51SArgyrios Kyrtzidis PreprocessingRecord::getLoadedPreprocessedEntity(unsigned Index) {
37003c40c51SArgyrios Kyrtzidis assert(Index < LoadedPreprocessedEntities.size() &&
37103c40c51SArgyrios Kyrtzidis "Out-of bounds loaded preprocessed entity");
37203c40c51SArgyrios Kyrtzidis assert(ExternalSource && "No external source to load from");
37303c40c51SArgyrios Kyrtzidis PreprocessedEntity *&Entity = LoadedPreprocessedEntities[Index];
37403c40c51SArgyrios Kyrtzidis if (!Entity) {
37503c40c51SArgyrios Kyrtzidis Entity = ExternalSource->ReadPreprocessedEntity(Index);
37603c40c51SArgyrios Kyrtzidis if (!Entity) // Failed to load.
37703c40c51SArgyrios Kyrtzidis Entity = new (*this)
37803c40c51SArgyrios Kyrtzidis PreprocessedEntity(PreprocessedEntity::InvalidKind, SourceRange());
37903c40c51SArgyrios Kyrtzidis }
38003c40c51SArgyrios Kyrtzidis return Entity;
381aae9224eSDouglas Gregor }
382aae9224eSDouglas Gregor
38366a8186eSRichard Smith MacroDefinitionRecord *
findMacroDefinition(const MacroInfo * MI)38466a8186eSRichard Smith PreprocessingRecord::findMacroDefinition(const MacroInfo *MI) {
38566a8186eSRichard Smith llvm::DenseMap<const MacroInfo *, MacroDefinitionRecord *>::iterator Pos =
38666a8186eSRichard Smith MacroDefinitions.find(MI);
3877dc8722bSDouglas Gregor if (Pos == MacroDefinitions.end())
388d2d442caSCraig Topper return nullptr;
3897dc8722bSDouglas Gregor
390832de9fcSArgyrios Kyrtzidis return Pos->second;
3917dc8722bSDouglas Gregor }
3927dc8722bSDouglas Gregor
addMacroExpansion(const Token & Id,const MacroInfo * MI,SourceRange Range)393f77b0f88SArgyrios Kyrtzidis void PreprocessingRecord::addMacroExpansion(const Token &Id,
394f77b0f88SArgyrios Kyrtzidis const MacroInfo *MI,
39585a14bbdSArgyrios Kyrtzidis SourceRange Range) {
396335c5a42SArgyrios Kyrtzidis // We don't record nested macro expansions.
397335c5a42SArgyrios Kyrtzidis if (Id.getLocation().isMacroID())
398998caeadSDouglas Gregor return;
399998caeadSDouglas Gregor
40080f78b96SArgyrios Kyrtzidis if (MI->isBuiltinMacro())
40166a8186eSRichard Smith addPreprocessedEntity(new (*this)
40266a8186eSRichard Smith MacroExpansion(Id.getIdentifierInfo(), Range));
40366a8186eSRichard Smith else if (MacroDefinitionRecord *Def = findMacroDefinition(MI))
40466a8186eSRichard Smith addPreprocessedEntity(new (*this) MacroExpansion(Def, Range));
4057dc8722bSDouglas Gregor }
4067dc8722bSDouglas Gregor
Ifdef(SourceLocation Loc,const Token & MacroNameTok,const MacroDefinition & MD)407f77b0f88SArgyrios Kyrtzidis void PreprocessingRecord::Ifdef(SourceLocation Loc, const Token &MacroNameTok,
40836bd40dfSRichard Smith const MacroDefinition &MD) {
409f77b0f88SArgyrios Kyrtzidis // This is not actually a macro expansion but record it as a macro reference.
410fead64beSArgyrios Kyrtzidis if (MD)
41136bd40dfSRichard Smith addMacroExpansion(MacroNameTok, MD.getMacroInfo(),
412b6210dffSArgyrios Kyrtzidis MacroNameTok.getLocation());
413f77b0f88SArgyrios Kyrtzidis }
414f77b0f88SArgyrios Kyrtzidis
Elifdef(SourceLocation Loc,const Token & MacroNameTok,const MacroDefinition & MD)4158edd3464SAaron Ballman void PreprocessingRecord::Elifdef(SourceLocation Loc, const Token &MacroNameTok,
4168edd3464SAaron Ballman const MacroDefinition &MD) {
4178edd3464SAaron Ballman // This is not actually a macro expansion but record it as a macro reference.
4188edd3464SAaron Ballman if (MD)
4198edd3464SAaron Ballman addMacroExpansion(MacroNameTok, MD.getMacroInfo(),
4208edd3464SAaron Ballman MacroNameTok.getLocation());
4218edd3464SAaron Ballman }
4228edd3464SAaron Ballman
Ifndef(SourceLocation Loc,const Token & MacroNameTok,const MacroDefinition & MD)423f77b0f88SArgyrios Kyrtzidis void PreprocessingRecord::Ifndef(SourceLocation Loc, const Token &MacroNameTok,
42436bd40dfSRichard Smith const MacroDefinition &MD) {
425f77b0f88SArgyrios Kyrtzidis // This is not actually a macro expansion but record it as a macro reference.
426fead64beSArgyrios Kyrtzidis if (MD)
42736bd40dfSRichard Smith addMacroExpansion(MacroNameTok, MD.getMacroInfo(),
428b6210dffSArgyrios Kyrtzidis MacroNameTok.getLocation());
429f77b0f88SArgyrios Kyrtzidis }
430f77b0f88SArgyrios Kyrtzidis
Elifndef(SourceLocation Loc,const Token & MacroNameTok,const MacroDefinition & MD)4318edd3464SAaron Ballman void PreprocessingRecord::Elifndef(SourceLocation Loc,
4328edd3464SAaron Ballman const Token &MacroNameTok,
4338edd3464SAaron Ballman const MacroDefinition &MD) {
4348edd3464SAaron Ballman // This is not actually a macro expansion but record it as a macro reference.
4358edd3464SAaron Ballman if (MD)
4368edd3464SAaron Ballman addMacroExpansion(MacroNameTok, MD.getMacroInfo(),
4378edd3464SAaron Ballman MacroNameTok.getLocation());
4388edd3464SAaron Ballman }
4398edd3464SAaron Ballman
Defined(const Token & MacroNameTok,const MacroDefinition & MD,SourceRange Range)440f77b0f88SArgyrios Kyrtzidis void PreprocessingRecord::Defined(const Token &MacroNameTok,
44136bd40dfSRichard Smith const MacroDefinition &MD,
442cda95fe7SJohn Thompson SourceRange Range) {
443f77b0f88SArgyrios Kyrtzidis // This is not actually a macro expansion but record it as a macro reference.
444fead64beSArgyrios Kyrtzidis if (MD)
44536bd40dfSRichard Smith addMacroExpansion(MacroNameTok, MD.getMacroInfo(),
446b6210dffSArgyrios Kyrtzidis MacroNameTok.getLocation());
447f77b0f88SArgyrios Kyrtzidis }
448f77b0f88SArgyrios Kyrtzidis
SourceRangeSkipped(SourceRange Range,SourceLocation EndifLoc)4493919a501SVedant Kumar void PreprocessingRecord::SourceRangeSkipped(SourceRange Range,
4503919a501SVedant Kumar SourceLocation EndifLoc) {
451b60f1b6dSCameron Desrochers assert(Range.isValid());
4523919a501SVedant Kumar SkippedRanges.emplace_back(Range.getBegin(), EndifLoc);
4539ef5775aSArgyrios Kyrtzidis }
4549ef5775aSArgyrios Kyrtzidis
MacroExpands(const Token & Id,const MacroDefinition & MD,SourceRange Range,const MacroArgs * Args)45536bd40dfSRichard Smith void PreprocessingRecord::MacroExpands(const Token &Id,
45636bd40dfSRichard Smith const MacroDefinition &MD,
45737e48ff5SArgyrios Kyrtzidis SourceRange Range,
45837e48ff5SArgyrios Kyrtzidis const MacroArgs *Args) {
45936bd40dfSRichard Smith addMacroExpansion(Id, MD.getMacroInfo(), Range);
460f77b0f88SArgyrios Kyrtzidis }
461f77b0f88SArgyrios Kyrtzidis
MacroDefined(const Token & Id,const MacroDirective * MD)4621a9ca218SCraig Silverstein void PreprocessingRecord::MacroDefined(const Token &Id,
463fead64beSArgyrios Kyrtzidis const MacroDirective *MD) {
464b6210dffSArgyrios Kyrtzidis const MacroInfo *MI = MD->getMacroInfo();
4657dc8722bSDouglas Gregor SourceRange R(MI->getDefinitionLoc(), MI->getDefinitionEndLoc());
46666a8186eSRichard Smith MacroDefinitionRecord *Def =
46766a8186eSRichard Smith new (*this) MacroDefinitionRecord(Id.getIdentifierInfo(), R);
468832de9fcSArgyrios Kyrtzidis addPreprocessedEntity(Def);
469832de9fcSArgyrios Kyrtzidis MacroDefinitions[MI] = Def;
4707dc8722bSDouglas Gregor }
471aae9224eSDouglas Gregor
MacroUndefined(const Token & Id,const MacroDefinition & MD,const MacroDirective * Undef)4721a9ca218SCraig Silverstein void PreprocessingRecord::MacroUndefined(const Token &Id,
473349a624aSVedant Kumar const MacroDefinition &MD,
474349a624aSVedant Kumar const MacroDirective *Undef) {
47536bd40dfSRichard Smith MD.forAllDefinitions([&](MacroInfo *MI) { MacroDefinitions.erase(MI); });
4768aaca67bSDouglas Gregor }
4778aaca67bSDouglas Gregor
InclusionDirective(SourceLocation HashLoc,const Token & IncludeTok,StringRef FileName,bool IsAngled,CharSourceRange FilenameRange,Optional<FileEntryRef> File,StringRef SearchPath,StringRef RelativePath,const Module * Imported,SrcMgr::CharacteristicKind FileType)4783cc331a1SChandler Carruth void PreprocessingRecord::InclusionDirective(
4793cc331a1SChandler Carruth SourceLocation HashLoc,
480cb96ac64SEugene Zelenko const Token &IncludeTok,
4810e62c1ccSChris Lattner StringRef FileName,
482796d76a6SDouglas Gregor bool IsAngled,
4834fcd2885SArgyrios Kyrtzidis CharSourceRange FilenameRange,
484d79ad2f1SJan Svoboda Optional<FileEntryRef> File,
4850e62c1ccSChris Lattner StringRef SearchPath,
48619d78b74SArgyrios Kyrtzidis StringRef RelativePath,
48796fbe58bSJulie Hockett const Module *Imported,
48896fbe58bSJulie Hockett SrcMgr::CharacteristicKind FileType) {
489796d76a6SDouglas Gregor InclusionDirective::InclusionKind Kind = InclusionDirective::Include;
490796d76a6SDouglas Gregor
491796d76a6SDouglas Gregor switch (IncludeTok.getIdentifierInfo()->getPPKeywordID()) {
492796d76a6SDouglas Gregor case tok::pp_include:
493796d76a6SDouglas Gregor Kind = InclusionDirective::Include;
494796d76a6SDouglas Gregor break;
495796d76a6SDouglas Gregor
496796d76a6SDouglas Gregor case tok::pp_import:
497796d76a6SDouglas Gregor Kind = InclusionDirective::Import;
498796d76a6SDouglas Gregor break;
499796d76a6SDouglas Gregor
500796d76a6SDouglas Gregor case tok::pp_include_next:
501796d76a6SDouglas Gregor Kind = InclusionDirective::IncludeNext;
502796d76a6SDouglas Gregor break;
503796d76a6SDouglas Gregor
504796d76a6SDouglas Gregor case tok::pp___include_macros:
505796d76a6SDouglas Gregor Kind = InclusionDirective::IncludeMacros;
506796d76a6SDouglas Gregor break;
507796d76a6SDouglas Gregor
508796d76a6SDouglas Gregor default:
509796d76a6SDouglas Gregor llvm_unreachable("Unknown include directive kind");
510796d76a6SDouglas Gregor }
511796d76a6SDouglas Gregor
5124fcd2885SArgyrios Kyrtzidis SourceLocation EndLoc;
5134fcd2885SArgyrios Kyrtzidis if (!IsAngled) {
5144fcd2885SArgyrios Kyrtzidis EndLoc = FilenameRange.getBegin();
5154fcd2885SArgyrios Kyrtzidis } else {
5164fcd2885SArgyrios Kyrtzidis EndLoc = FilenameRange.getEnd();
5174fcd2885SArgyrios Kyrtzidis if (FilenameRange.isCharRange())
5184fcd2885SArgyrios Kyrtzidis EndLoc = EndLoc.getLocWithOffset(-1); // the InclusionDirective expects
5194fcd2885SArgyrios Kyrtzidis // a token range.
5204fcd2885SArgyrios Kyrtzidis }
521cb96ac64SEugene Zelenko clang::InclusionDirective *ID =
522cb96ac64SEugene Zelenko new (*this) clang::InclusionDirective(*this, Kind, FileName, !IsAngled,
523cb96ac64SEugene Zelenko (bool)Imported, File,
524cb96ac64SEugene Zelenko SourceRange(HashLoc, EndLoc));
52564f63810SArgyrios Kyrtzidis addPreprocessedEntity(ID);
526796d76a6SDouglas Gregor }
527182543abSTed Kremenek
getTotalMemory() const528182543abSTed Kremenek size_t PreprocessingRecord::getTotalMemory() const {
529182543abSTed Kremenek return BumpAlloc.getTotalMemory()
530f1c38811STed Kremenek + llvm::capacity_in_bytes(MacroDefinitions)
531f1c38811STed Kremenek + llvm::capacity_in_bytes(PreprocessedEntities)
532b60f1b6dSCameron Desrochers + llvm::capacity_in_bytes(LoadedPreprocessedEntities)
533b60f1b6dSCameron Desrochers + llvm::capacity_in_bytes(SkippedRanges);
534182543abSTed Kremenek }
535