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