xref: /src/contrib/llvm-project/clang/lib/Lex/PreprocessingRecord.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1461a67faSDimitry Andric //===- PreprocessingRecord.cpp - Record of Preprocessing ------------------===//
2c0c7bca4SRoman Divacky //
322989816SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
422989816SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
522989816SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6c0c7bca4SRoman Divacky //
7c0c7bca4SRoman Divacky //===----------------------------------------------------------------------===//
8c0c7bca4SRoman Divacky //
9c0c7bca4SRoman Divacky //  This file implements the PreprocessingRecord class, which maintains a record
10c0c7bca4SRoman Divacky //  of what occurred during preprocessing, and its helpers.
11c0c7bca4SRoman Divacky //
12c0c7bca4SRoman Divacky //===----------------------------------------------------------------------===//
13461a67faSDimitry Andric 
14c0c7bca4SRoman Divacky #include "clang/Lex/PreprocessingRecord.h"
15461a67faSDimitry Andric #include "clang/Basic/IdentifierTable.h"
16461a67faSDimitry Andric #include "clang/Basic/LLVM.h"
17461a67faSDimitry Andric #include "clang/Basic/SourceLocation.h"
18461a67faSDimitry Andric #include "clang/Basic/SourceManager.h"
19461a67faSDimitry Andric #include "clang/Basic/TokenKinds.h"
20c0c7bca4SRoman Divacky #include "clang/Lex/MacroInfo.h"
21c0c7bca4SRoman Divacky #include "clang/Lex/Token.h"
22461a67faSDimitry Andric #include "llvm/ADT/DenseMap.h"
23461a67faSDimitry Andric #include "llvm/ADT/StringRef.h"
24461a67faSDimitry Andric #include "llvm/ADT/iterator_range.h"
2536981b17SDimitry Andric #include "llvm/Support/Capacity.h"
26461a67faSDimitry Andric #include "llvm/Support/Casting.h"
27809500fcSDimitry Andric #include "llvm/Support/ErrorHandling.h"
28461a67faSDimitry Andric #include <algorithm>
29461a67faSDimitry Andric #include <cassert>
30461a67faSDimitry Andric #include <cstddef>
31461a67faSDimitry Andric #include <cstring>
32461a67faSDimitry Andric #include <iterator>
33e3b55780SDimitry Andric #include <optional>
34461a67faSDimitry Andric #include <utility>
35461a67faSDimitry Andric #include <vector>
36c0c7bca4SRoman Divacky 
37c0c7bca4SRoman Divacky using namespace clang;
38c0c7bca4SRoman Divacky 
39461a67faSDimitry Andric ExternalPreprocessingRecordSource::~ExternalPreprocessingRecordSource() =
40461a67faSDimitry Andric     default;
41c0c7bca4SRoman Divacky 
InclusionDirective(PreprocessingRecord & PPRec,InclusionKind Kind,StringRef FileName,bool InQuotes,bool ImportedModule,OptionalFileEntryRef File,SourceRange Range)42bca07a45SDimitry Andric InclusionDirective::InclusionDirective(PreprocessingRecord &PPRec,
43bab175ecSDimitry Andric                                        InclusionKind Kind, StringRef FileName,
4413cc256eSDimitry Andric                                        bool InQuotes, bool ImportedModule,
45e3b55780SDimitry Andric                                        OptionalFileEntryRef File,
46145449b1SDimitry Andric                                        SourceRange Range)
47bab175ecSDimitry Andric     : PreprocessingDirective(InclusionDirectiveKind, Range), InQuotes(InQuotes),
48bab175ecSDimitry Andric       Kind(Kind), ImportedModule(ImportedModule), File(File) {
49bab175ecSDimitry Andric   char *Memory = (char *)PPRec.Allocate(FileName.size() + 1, alignof(char));
50bca07a45SDimitry Andric   memcpy(Memory, FileName.data(), FileName.size());
51bca07a45SDimitry Andric   Memory[FileName.size()] = 0;
5236981b17SDimitry Andric   this->FileName = StringRef(Memory, FileName.size());
53bca07a45SDimitry Andric }
54bca07a45SDimitry Andric 
PreprocessingRecord(SourceManager & SM)55461a67faSDimitry Andric PreprocessingRecord::PreprocessingRecord(SourceManager &SM) : SourceMgr(SM) {}
56c0c7bca4SRoman Divacky 
5748675466SDimitry Andric /// Returns a pair of [Begin, End) iterators of preprocessed entities
5856d91b49SDimitry Andric /// that source range \p Range encompasses.
595e20cdd8SDimitry Andric llvm::iterator_range<PreprocessingRecord::iterator>
getPreprocessedEntitiesInRange(SourceRange Range)6036981b17SDimitry Andric PreprocessingRecord::getPreprocessedEntitiesInRange(SourceRange Range) {
6136981b17SDimitry Andric   if (Range.isInvalid())
625e20cdd8SDimitry Andric     return llvm::make_range(iterator(), iterator());
63dbe13110SDimitry Andric 
64dbe13110SDimitry Andric   if (CachedRangeQuery.Range == Range) {
655e20cdd8SDimitry Andric     return llvm::make_range(iterator(this, CachedRangeQuery.Result.first),
66dbe13110SDimitry Andric                             iterator(this, CachedRangeQuery.Result.second));
67dbe13110SDimitry Andric   }
68dbe13110SDimitry Andric 
6913cc256eSDimitry Andric   std::pair<int, int> Res = getPreprocessedEntitiesInRangeSlow(Range);
70dbe13110SDimitry Andric 
71dbe13110SDimitry Andric   CachedRangeQuery.Range = Range;
72dbe13110SDimitry Andric   CachedRangeQuery.Result = Res;
73dbe13110SDimitry Andric 
745e20cdd8SDimitry Andric   return llvm::make_range(iterator(this, Res.first),
755e20cdd8SDimitry Andric                           iterator(this, Res.second));
76dbe13110SDimitry Andric }
77dbe13110SDimitry Andric 
isPreprocessedEntityIfInFileID(PreprocessedEntity * PPE,FileID FID,SourceManager & SM)78dbe13110SDimitry Andric static bool isPreprocessedEntityIfInFileID(PreprocessedEntity *PPE, FileID FID,
79dbe13110SDimitry Andric                                            SourceManager &SM) {
8045b53394SDimitry Andric   assert(FID.isValid());
81dbe13110SDimitry Andric   if (!PPE)
82dbe13110SDimitry Andric     return false;
83dbe13110SDimitry Andric 
84dbe13110SDimitry Andric   SourceLocation Loc = PPE->getSourceRange().getBegin();
85dbe13110SDimitry Andric   if (Loc.isInvalid())
86dbe13110SDimitry Andric     return false;
87dbe13110SDimitry Andric 
885e20cdd8SDimitry Andric   return SM.isInFileID(SM.getFileLoc(Loc), FID);
89dbe13110SDimitry Andric }
90dbe13110SDimitry Andric 
9148675466SDimitry Andric /// Returns true if the preprocessed entity that \arg PPEI iterator
92dbe13110SDimitry Andric /// points to is coming from the file \arg FID.
93dbe13110SDimitry Andric ///
94dbe13110SDimitry Andric /// Can be used to avoid implicit deserializations of preallocated
95dbe13110SDimitry Andric /// preprocessed entities if we only care about entities of a specific file
9656d91b49SDimitry Andric /// and not from files \#included in the range given at
97dbe13110SDimitry Andric /// \see getPreprocessedEntitiesInRange.
isEntityInFileID(iterator PPEI,FileID FID)98dbe13110SDimitry Andric bool PreprocessingRecord::isEntityInFileID(iterator PPEI, FileID FID) {
99dbe13110SDimitry Andric   if (FID.isInvalid())
100dbe13110SDimitry Andric     return false;
101dbe13110SDimitry Andric 
1025e20cdd8SDimitry Andric   int Pos = std::distance(iterator(this, 0), PPEI);
10313cc256eSDimitry Andric   if (Pos < 0) {
104809500fcSDimitry Andric     if (unsigned(-Pos-1) >= LoadedPreprocessedEntities.size()) {
105809500fcSDimitry Andric       assert(0 && "Out-of bounds loaded preprocessed entity");
106809500fcSDimitry Andric       return false;
107809500fcSDimitry Andric     }
108dbe13110SDimitry Andric     assert(ExternalSource && "No external source to load from");
10913cc256eSDimitry Andric     unsigned LoadedIndex = LoadedPreprocessedEntities.size()+Pos;
110dbe13110SDimitry Andric     if (PreprocessedEntity *PPE = LoadedPreprocessedEntities[LoadedIndex])
111dbe13110SDimitry Andric       return isPreprocessedEntityIfInFileID(PPE, FID, SourceMgr);
112dbe13110SDimitry Andric 
113dbe13110SDimitry Andric     // See if the external source can see if the entity is in the file without
114dbe13110SDimitry Andric     // deserializing it.
115e3b55780SDimitry Andric     if (std::optional<bool> IsInFile =
116e3b55780SDimitry Andric             ExternalSource->isPreprocessedEntityInFileID(LoadedIndex, FID))
117e3b55780SDimitry Andric       return *IsInFile;
118dbe13110SDimitry Andric 
119dbe13110SDimitry Andric     // The external source did not provide a definite answer, go and deserialize
120dbe13110SDimitry Andric     // the entity to check it.
121dbe13110SDimitry Andric     return isPreprocessedEntityIfInFileID(
122dbe13110SDimitry Andric                                        getLoadedPreprocessedEntity(LoadedIndex),
123dbe13110SDimitry Andric                                           FID, SourceMgr);
124dbe13110SDimitry Andric   }
125dbe13110SDimitry Andric 
126809500fcSDimitry Andric   if (unsigned(Pos) >= PreprocessedEntities.size()) {
127809500fcSDimitry Andric     assert(0 && "Out-of bounds local preprocessed entity");
128809500fcSDimitry Andric     return false;
129809500fcSDimitry Andric   }
13013cc256eSDimitry Andric   return isPreprocessedEntityIfInFileID(PreprocessedEntities[Pos],
131dbe13110SDimitry Andric                                         FID, SourceMgr);
132dbe13110SDimitry Andric }
133dbe13110SDimitry Andric 
13448675466SDimitry Andric /// Returns a pair of [Begin, End) iterators of preprocessed entities
135dbe13110SDimitry Andric /// that source range \arg R encompasses.
13613cc256eSDimitry Andric std::pair<int, int>
getPreprocessedEntitiesInRangeSlow(SourceRange Range)137dbe13110SDimitry Andric PreprocessingRecord::getPreprocessedEntitiesInRangeSlow(SourceRange Range) {
138dbe13110SDimitry Andric   assert(Range.isValid());
13936981b17SDimitry Andric   assert(!SourceMgr.isBeforeInTranslationUnit(Range.getEnd(),Range.getBegin()));
140c0c7bca4SRoman Divacky 
14136981b17SDimitry Andric   std::pair<unsigned, unsigned>
14236981b17SDimitry Andric     Local = findLocalPreprocessedEntitiesInRange(Range);
14336981b17SDimitry Andric 
14436981b17SDimitry Andric   // Check if range spans local entities.
14536981b17SDimitry Andric   if (!ExternalSource || SourceMgr.isLocalSourceLocation(Range.getBegin()))
146dbe13110SDimitry Andric     return std::make_pair(Local.first, Local.second);
14736981b17SDimitry Andric 
14836981b17SDimitry Andric   std::pair<unsigned, unsigned>
14936981b17SDimitry Andric     Loaded = ExternalSource->findPreprocessedEntitiesInRange(Range);
15036981b17SDimitry Andric 
15136981b17SDimitry Andric   // Check if range spans local entities.
15236981b17SDimitry Andric   if (Loaded.first == Loaded.second)
153dbe13110SDimitry Andric     return std::make_pair(Local.first, Local.second);
15436981b17SDimitry Andric 
15536981b17SDimitry Andric   unsigned TotalLoaded = LoadedPreprocessedEntities.size();
15636981b17SDimitry Andric 
15736981b17SDimitry Andric   // Check if range spans loaded entities.
15836981b17SDimitry Andric   if (Local.first == Local.second)
159dbe13110SDimitry Andric     return std::make_pair(int(Loaded.first)-TotalLoaded,
160dbe13110SDimitry Andric                           int(Loaded.second)-TotalLoaded);
16136981b17SDimitry Andric 
16236981b17SDimitry Andric   // Range spands loaded and local entities.
163dbe13110SDimitry Andric   return std::make_pair(int(Loaded.first)-TotalLoaded, Local.second);
164c0c7bca4SRoman Divacky }
165c0c7bca4SRoman Divacky 
16636981b17SDimitry Andric std::pair<unsigned, unsigned>
findLocalPreprocessedEntitiesInRange(SourceRange Range) const16736981b17SDimitry Andric PreprocessingRecord::findLocalPreprocessedEntitiesInRange(
16836981b17SDimitry Andric                                                       SourceRange Range) const {
16936981b17SDimitry Andric   if (Range.isInvalid())
17036981b17SDimitry Andric     return std::make_pair(0,0);
17136981b17SDimitry Andric   assert(!SourceMgr.isBeforeInTranslationUnit(Range.getEnd(),Range.getBegin()));
172c0c7bca4SRoman Divacky 
17336981b17SDimitry Andric   unsigned Begin = findBeginLocalPreprocessedEntity(Range.getBegin());
17436981b17SDimitry Andric   unsigned End = findEndLocalPreprocessedEntity(Range.getEnd());
17536981b17SDimitry Andric   return std::make_pair(Begin, End);
176c0c7bca4SRoman Divacky }
177c0c7bca4SRoman Divacky 
17836981b17SDimitry Andric namespace {
179c0c7bca4SRoman Divacky 
18036981b17SDimitry Andric template <SourceLocation (SourceRange::*getRangeLoc)() const>
18136981b17SDimitry Andric struct PPEntityComp {
18236981b17SDimitry Andric   const SourceManager &SM;
18336981b17SDimitry Andric 
PPEntityComp__anon41257eea0111::PPEntityComp18436981b17SDimitry Andric   explicit PPEntityComp(const SourceManager &SM) : SM(SM) {}
18536981b17SDimitry Andric 
operator ()__anon41257eea0111::PPEntityComp18636981b17SDimitry Andric   bool operator()(PreprocessedEntity *L, PreprocessedEntity *R) const {
18736981b17SDimitry Andric     SourceLocation LHS = getLoc(L);
18836981b17SDimitry Andric     SourceLocation RHS = getLoc(R);
18936981b17SDimitry Andric     return SM.isBeforeInTranslationUnit(LHS, RHS);
190c0c7bca4SRoman Divacky   }
191c0c7bca4SRoman Divacky 
operator ()__anon41257eea0111::PPEntityComp19236981b17SDimitry Andric   bool operator()(PreprocessedEntity *L, SourceLocation RHS) const {
19336981b17SDimitry Andric     SourceLocation LHS = getLoc(L);
19436981b17SDimitry Andric     return SM.isBeforeInTranslationUnit(LHS, RHS);
19536981b17SDimitry Andric   }
196c0c7bca4SRoman Divacky 
operator ()__anon41257eea0111::PPEntityComp19736981b17SDimitry Andric   bool operator()(SourceLocation LHS, PreprocessedEntity *R) const {
19836981b17SDimitry Andric     SourceLocation RHS = getLoc(R);
19936981b17SDimitry Andric     return SM.isBeforeInTranslationUnit(LHS, RHS);
20036981b17SDimitry Andric   }
20136981b17SDimitry Andric 
getLoc__anon41257eea0111::PPEntityComp20236981b17SDimitry Andric   SourceLocation getLoc(PreprocessedEntity *PPE) const {
20336981b17SDimitry Andric     SourceRange Range = PPE->getSourceRange();
20436981b17SDimitry Andric     return (Range.*getRangeLoc)();
20536981b17SDimitry Andric   }
20636981b17SDimitry Andric };
20736981b17SDimitry Andric 
208461a67faSDimitry Andric } // namespace
20936981b17SDimitry Andric 
findBeginLocalPreprocessedEntity(SourceLocation Loc) const21036981b17SDimitry Andric unsigned PreprocessingRecord::findBeginLocalPreprocessedEntity(
21136981b17SDimitry Andric                                                      SourceLocation Loc) const {
21236981b17SDimitry Andric   if (SourceMgr.isLoadedSourceLocation(Loc))
21336981b17SDimitry Andric     return 0;
21436981b17SDimitry Andric 
21536981b17SDimitry Andric   size_t Count = PreprocessedEntities.size();
21636981b17SDimitry Andric   size_t Half;
21736981b17SDimitry Andric   std::vector<PreprocessedEntity *>::const_iterator
21836981b17SDimitry Andric     First = PreprocessedEntities.begin();
21936981b17SDimitry Andric   std::vector<PreprocessedEntity *>::const_iterator I;
22036981b17SDimitry Andric 
22136981b17SDimitry Andric   // Do a binary search manually instead of using std::lower_bound because
22236981b17SDimitry Andric   // The end locations of entities may be unordered (when a macro expansion
22336981b17SDimitry Andric   // is inside another macro argument), but for this case it is not important
22436981b17SDimitry Andric   // whether we get the first macro expansion or its containing macro.
22536981b17SDimitry Andric   while (Count > 0) {
22636981b17SDimitry Andric     Half = Count/2;
22736981b17SDimitry Andric     I = First;
22836981b17SDimitry Andric     std::advance(I, Half);
22936981b17SDimitry Andric     if (SourceMgr.isBeforeInTranslationUnit((*I)->getSourceRange().getEnd(),
23036981b17SDimitry Andric                                             Loc)){
23136981b17SDimitry Andric       First = I;
23236981b17SDimitry Andric       ++First;
23336981b17SDimitry Andric       Count = Count - Half - 1;
23436981b17SDimitry Andric     } else
23536981b17SDimitry Andric       Count = Half;
23636981b17SDimitry Andric   }
23736981b17SDimitry Andric 
23836981b17SDimitry Andric   return First - PreprocessedEntities.begin();
23936981b17SDimitry Andric }
24036981b17SDimitry Andric 
24122989816SDimitry Andric unsigned
findEndLocalPreprocessedEntity(SourceLocation Loc) const24222989816SDimitry Andric PreprocessingRecord::findEndLocalPreprocessedEntity(SourceLocation Loc) const {
24336981b17SDimitry Andric   if (SourceMgr.isLoadedSourceLocation(Loc))
24436981b17SDimitry Andric     return 0;
24536981b17SDimitry Andric 
24622989816SDimitry Andric   auto I = llvm::upper_bound(PreprocessedEntities, Loc,
24736981b17SDimitry Andric                              PPEntityComp<&SourceRange::getBegin>(SourceMgr));
24836981b17SDimitry Andric   return I - PreprocessedEntities.begin();
249c0c7bca4SRoman Divacky }
250c0c7bca4SRoman Divacky 
251dbe13110SDimitry Andric PreprocessingRecord::PPEntityID
addPreprocessedEntity(PreprocessedEntity * Entity)252dbe13110SDimitry Andric PreprocessingRecord::addPreprocessedEntity(PreprocessedEntity *Entity) {
25336981b17SDimitry Andric   assert(Entity);
25436981b17SDimitry Andric   SourceLocation BeginLoc = Entity->getSourceRange().getBegin();
25536981b17SDimitry Andric 
2565e20cdd8SDimitry Andric   if (isa<MacroDefinitionRecord>(Entity)) {
257dbe13110SDimitry Andric     assert((PreprocessedEntities.empty() ||
2585e20cdd8SDimitry Andric             !SourceMgr.isBeforeInTranslationUnit(
2595e20cdd8SDimitry Andric                 BeginLoc,
260dbe13110SDimitry Andric                 PreprocessedEntities.back()->getSourceRange().getBegin())) &&
261809500fcSDimitry Andric            "a macro definition was encountered out-of-order");
262dbe13110SDimitry Andric     PreprocessedEntities.push_back(Entity);
263dbe13110SDimitry Andric     return getPPEntityID(PreprocessedEntities.size()-1, /*isLoaded=*/false);
264dbe13110SDimitry Andric   }
265dbe13110SDimitry Andric 
26636981b17SDimitry Andric   // Check normal case, this entity begin location is after the previous one.
26736981b17SDimitry Andric   if (PreprocessedEntities.empty() ||
26836981b17SDimitry Andric       !SourceMgr.isBeforeInTranslationUnit(BeginLoc,
26936981b17SDimitry Andric                    PreprocessedEntities.back()->getSourceRange().getBegin())) {
270c0c7bca4SRoman Divacky     PreprocessedEntities.push_back(Entity);
271dbe13110SDimitry Andric     return getPPEntityID(PreprocessedEntities.size()-1, /*isLoaded=*/false);
27236981b17SDimitry Andric   }
27336981b17SDimitry Andric 
274dbe13110SDimitry Andric   // The entity's location is not after the previous one; this can happen with
275dbe13110SDimitry Andric   // include directives that form the filename using macros, e.g:
276809500fcSDimitry Andric   // "#include MACRO(STUFF)"
277809500fcSDimitry Andric   // or with macro expansions inside macro arguments where the arguments are
278809500fcSDimitry Andric   // not expanded in the same order as listed, e.g:
279809500fcSDimitry Andric   // \code
280809500fcSDimitry Andric   //  #define M1 1
281809500fcSDimitry Andric   //  #define M2 2
282809500fcSDimitry Andric   //  #define FM(x,y) y x
283809500fcSDimitry Andric   //  FM(M1, M2)
284809500fcSDimitry Andric   // \endcode
285dbe13110SDimitry Andric 
286461a67faSDimitry Andric   using pp_iter = std::vector<PreprocessedEntity *>::iterator;
287dbe13110SDimitry Andric 
288dbe13110SDimitry Andric   // Usually there are few macro expansions when defining the filename, do a
289dbe13110SDimitry Andric   // linear search for a few entities.
290dbe13110SDimitry Andric   unsigned count = 0;
291dbe13110SDimitry Andric   for (pp_iter RI    = PreprocessedEntities.end(),
292dbe13110SDimitry Andric                Begin = PreprocessedEntities.begin();
293dbe13110SDimitry Andric        RI != Begin && count < 4; --RI, ++count) {
294dbe13110SDimitry Andric     pp_iter I = RI;
29536981b17SDimitry Andric     --I;
29636981b17SDimitry Andric     if (!SourceMgr.isBeforeInTranslationUnit(BeginLoc,
29736981b17SDimitry Andric                                            (*I)->getSourceRange().getBegin())) {
298dbe13110SDimitry Andric       pp_iter insertI = PreprocessedEntities.insert(RI, Entity);
299dbe13110SDimitry Andric       return getPPEntityID(insertI - PreprocessedEntities.begin(),
300dbe13110SDimitry Andric                            /*isLoaded=*/false);
30136981b17SDimitry Andric     }
30236981b17SDimitry Andric   }
303dbe13110SDimitry Andric 
304dbe13110SDimitry Andric   // Linear search unsuccessful. Do a binary search.
30522989816SDimitry Andric   pp_iter I =
30622989816SDimitry Andric       llvm::upper_bound(PreprocessedEntities, BeginLoc,
307dbe13110SDimitry Andric                         PPEntityComp<&SourceRange::getBegin>(SourceMgr));
308dbe13110SDimitry Andric   pp_iter insertI = PreprocessedEntities.insert(I, Entity);
309dbe13110SDimitry Andric   return getPPEntityID(insertI - PreprocessedEntities.begin(),
310dbe13110SDimitry Andric                        /*isLoaded=*/false);
311c0c7bca4SRoman Divacky }
312c0c7bca4SRoman Divacky 
SetExternalSource(ExternalPreprocessingRecordSource & Source)313c0c7bca4SRoman Divacky void PreprocessingRecord::SetExternalSource(
31436981b17SDimitry Andric                                     ExternalPreprocessingRecordSource &Source) {
315c0c7bca4SRoman Divacky   assert(!ExternalSource &&
316c0c7bca4SRoman Divacky          "Preprocessing record already has an external source");
317c0c7bca4SRoman Divacky   ExternalSource = &Source;
318c0c7bca4SRoman Divacky }
319c0c7bca4SRoman Divacky 
allocateLoadedEntities(unsigned NumEntities)32036981b17SDimitry Andric unsigned PreprocessingRecord::allocateLoadedEntities(unsigned NumEntities) {
32136981b17SDimitry Andric   unsigned Result = LoadedPreprocessedEntities.size();
32236981b17SDimitry Andric   LoadedPreprocessedEntities.resize(LoadedPreprocessedEntities.size()
32336981b17SDimitry Andric                                     + NumEntities);
32436981b17SDimitry Andric   return Result;
325c0c7bca4SRoman Divacky }
326c0c7bca4SRoman Divacky 
allocateSkippedRanges(unsigned NumRanges)32748675466SDimitry Andric unsigned PreprocessingRecord::allocateSkippedRanges(unsigned NumRanges) {
32848675466SDimitry Andric   unsigned Result = SkippedRanges.size();
32948675466SDimitry Andric   SkippedRanges.resize(SkippedRanges.size() + NumRanges);
33048675466SDimitry Andric   SkippedRangesAllLoaded = false;
33148675466SDimitry Andric   return Result;
33248675466SDimitry Andric }
33348675466SDimitry Andric 
ensureSkippedRangesLoaded()33448675466SDimitry Andric void PreprocessingRecord::ensureSkippedRangesLoaded() {
33548675466SDimitry Andric   if (SkippedRangesAllLoaded || !ExternalSource)
33648675466SDimitry Andric     return;
33748675466SDimitry Andric   for (unsigned Index = 0; Index != SkippedRanges.size(); ++Index) {
33848675466SDimitry Andric     if (SkippedRanges[Index].isInvalid())
33948675466SDimitry Andric       SkippedRanges[Index] = ExternalSource->ReadSkippedRange(Index);
34048675466SDimitry Andric   }
34148675466SDimitry Andric   SkippedRangesAllLoaded = true;
34248675466SDimitry Andric }
34348675466SDimitry Andric 
RegisterMacroDefinition(MacroInfo * Macro,MacroDefinitionRecord * Def)344c0c7bca4SRoman Divacky void PreprocessingRecord::RegisterMacroDefinition(MacroInfo *Macro,
3455e20cdd8SDimitry Andric                                                   MacroDefinitionRecord *Def) {
346809500fcSDimitry Andric   MacroDefinitions[Macro] = Def;
34736981b17SDimitry Andric }
34836981b17SDimitry Andric 
34948675466SDimitry Andric /// Retrieve the preprocessed entity at the given ID.
getPreprocessedEntity(PPEntityID PPID)35036981b17SDimitry Andric PreprocessedEntity *PreprocessingRecord::getPreprocessedEntity(PPEntityID PPID){
35113cc256eSDimitry Andric   if (PPID.ID < 0) {
35213cc256eSDimitry Andric     unsigned Index = -PPID.ID - 1;
35313cc256eSDimitry Andric     assert(Index < LoadedPreprocessedEntities.size() &&
35436981b17SDimitry Andric            "Out-of bounds loaded preprocessed entity");
35513cc256eSDimitry Andric     return getLoadedPreprocessedEntity(Index);
35636981b17SDimitry Andric   }
35713cc256eSDimitry Andric 
35813cc256eSDimitry Andric   if (PPID.ID == 0)
3599f4dbff6SDimitry Andric     return nullptr;
36013cc256eSDimitry Andric   unsigned Index = PPID.ID - 1;
36113cc256eSDimitry Andric   assert(Index < PreprocessedEntities.size() &&
36236981b17SDimitry Andric          "Out-of bounds local preprocessed entity");
36313cc256eSDimitry Andric   return PreprocessedEntities[Index];
36436981b17SDimitry Andric }
36536981b17SDimitry Andric 
36648675466SDimitry Andric /// Retrieve the loaded preprocessed entity at the given index.
36736981b17SDimitry Andric PreprocessedEntity *
getLoadedPreprocessedEntity(unsigned Index)36836981b17SDimitry Andric PreprocessingRecord::getLoadedPreprocessedEntity(unsigned Index) {
36936981b17SDimitry Andric   assert(Index < LoadedPreprocessedEntities.size() &&
37036981b17SDimitry Andric          "Out-of bounds loaded preprocessed entity");
37136981b17SDimitry Andric   assert(ExternalSource && "No external source to load from");
37236981b17SDimitry Andric   PreprocessedEntity *&Entity = LoadedPreprocessedEntities[Index];
37336981b17SDimitry Andric   if (!Entity) {
37436981b17SDimitry Andric     Entity = ExternalSource->ReadPreprocessedEntity(Index);
37536981b17SDimitry Andric     if (!Entity) // Failed to load.
37636981b17SDimitry Andric       Entity = new (*this)
37736981b17SDimitry Andric          PreprocessedEntity(PreprocessedEntity::InvalidKind, SourceRange());
37836981b17SDimitry Andric   }
37936981b17SDimitry Andric   return Entity;
380c0c7bca4SRoman Divacky }
381c0c7bca4SRoman Divacky 
3825e20cdd8SDimitry Andric MacroDefinitionRecord *
findMacroDefinition(const MacroInfo * MI)3835e20cdd8SDimitry Andric PreprocessingRecord::findMacroDefinition(const MacroInfo *MI) {
3847fa27ce4SDimitry Andric   return MacroDefinitions.lookup(MI);
385c0c7bca4SRoman Divacky }
386c0c7bca4SRoman Divacky 
addMacroExpansion(const Token & Id,const MacroInfo * MI,SourceRange Range)387809500fcSDimitry Andric void PreprocessingRecord::addMacroExpansion(const Token &Id,
388809500fcSDimitry Andric                                             const MacroInfo *MI,
38936981b17SDimitry Andric                                             SourceRange Range) {
390dbe13110SDimitry Andric   // We don't record nested macro expansions.
391dbe13110SDimitry Andric   if (Id.getLocation().isMacroID())
39229cafa66SDimitry Andric     return;
39329cafa66SDimitry Andric 
39436981b17SDimitry Andric   if (MI->isBuiltinMacro())
3955e20cdd8SDimitry Andric     addPreprocessedEntity(new (*this)
3965e20cdd8SDimitry Andric                               MacroExpansion(Id.getIdentifierInfo(), Range));
3975e20cdd8SDimitry Andric   else if (MacroDefinitionRecord *Def = findMacroDefinition(MI))
3985e20cdd8SDimitry Andric     addPreprocessedEntity(new (*this) MacroExpansion(Def, Range));
399c0c7bca4SRoman Divacky }
400c0c7bca4SRoman Divacky 
Ifdef(SourceLocation Loc,const Token & MacroNameTok,const MacroDefinition & MD)401809500fcSDimitry Andric void PreprocessingRecord::Ifdef(SourceLocation Loc, const Token &MacroNameTok,
4025e20cdd8SDimitry Andric                                 const MacroDefinition &MD) {
403809500fcSDimitry Andric   // This is not actually a macro expansion but record it as a macro reference.
404809500fcSDimitry Andric   if (MD)
4055e20cdd8SDimitry Andric     addMacroExpansion(MacroNameTok, MD.getMacroInfo(),
406809500fcSDimitry Andric                       MacroNameTok.getLocation());
407809500fcSDimitry Andric }
408809500fcSDimitry Andric 
Elifdef(SourceLocation Loc,const Token & MacroNameTok,const MacroDefinition & MD)409344a3780SDimitry Andric void PreprocessingRecord::Elifdef(SourceLocation Loc, const Token &MacroNameTok,
410344a3780SDimitry Andric                                   const MacroDefinition &MD) {
411344a3780SDimitry Andric   // This is not actually a macro expansion but record it as a macro reference.
412344a3780SDimitry Andric   if (MD)
413344a3780SDimitry Andric     addMacroExpansion(MacroNameTok, MD.getMacroInfo(),
414344a3780SDimitry Andric                       MacroNameTok.getLocation());
415344a3780SDimitry Andric }
416344a3780SDimitry Andric 
Ifndef(SourceLocation Loc,const Token & MacroNameTok,const MacroDefinition & MD)417809500fcSDimitry Andric void PreprocessingRecord::Ifndef(SourceLocation Loc, const Token &MacroNameTok,
4185e20cdd8SDimitry Andric                                  const MacroDefinition &MD) {
419809500fcSDimitry Andric   // This is not actually a macro expansion but record it as a macro reference.
420809500fcSDimitry Andric   if (MD)
4215e20cdd8SDimitry Andric     addMacroExpansion(MacroNameTok, MD.getMacroInfo(),
422809500fcSDimitry Andric                       MacroNameTok.getLocation());
423809500fcSDimitry Andric }
424809500fcSDimitry Andric 
Elifndef(SourceLocation Loc,const Token & MacroNameTok,const MacroDefinition & MD)425344a3780SDimitry Andric void PreprocessingRecord::Elifndef(SourceLocation Loc,
426344a3780SDimitry Andric                                    const Token &MacroNameTok,
427344a3780SDimitry Andric                                    const MacroDefinition &MD) {
428344a3780SDimitry Andric   // This is not actually a macro expansion but record it as a macro reference.
429344a3780SDimitry Andric   if (MD)
430344a3780SDimitry Andric     addMacroExpansion(MacroNameTok, MD.getMacroInfo(),
431344a3780SDimitry Andric                       MacroNameTok.getLocation());
432344a3780SDimitry Andric }
433344a3780SDimitry Andric 
Defined(const Token & MacroNameTok,const MacroDefinition & MD,SourceRange Range)434809500fcSDimitry Andric void PreprocessingRecord::Defined(const Token &MacroNameTok,
4355e20cdd8SDimitry Andric                                   const MacroDefinition &MD,
436bfef3995SDimitry Andric                                   SourceRange Range) {
437809500fcSDimitry Andric   // This is not actually a macro expansion but record it as a macro reference.
438809500fcSDimitry Andric   if (MD)
4395e20cdd8SDimitry Andric     addMacroExpansion(MacroNameTok, MD.getMacroInfo(),
440809500fcSDimitry Andric                       MacroNameTok.getLocation());
441809500fcSDimitry Andric }
442809500fcSDimitry Andric 
SourceRangeSkipped(SourceRange Range,SourceLocation EndifLoc)443461a67faSDimitry Andric void PreprocessingRecord::SourceRangeSkipped(SourceRange Range,
444461a67faSDimitry Andric                                              SourceLocation EndifLoc) {
44548675466SDimitry Andric   assert(Range.isValid());
446461a67faSDimitry Andric   SkippedRanges.emplace_back(Range.getBegin(), EndifLoc);
4479f4dbff6SDimitry Andric }
4489f4dbff6SDimitry Andric 
MacroExpands(const Token & Id,const MacroDefinition & MD,SourceRange Range,const MacroArgs * Args)4495e20cdd8SDimitry Andric void PreprocessingRecord::MacroExpands(const Token &Id,
4505e20cdd8SDimitry Andric                                        const MacroDefinition &MD,
4516a037251SDimitry Andric                                        SourceRange Range,
4526a037251SDimitry Andric                                        const MacroArgs *Args) {
4535e20cdd8SDimitry Andric   addMacroExpansion(Id, MD.getMacroInfo(), Range);
454809500fcSDimitry Andric }
455809500fcSDimitry Andric 
MacroDefined(const Token & Id,const MacroDirective * MD)456bca07a45SDimitry Andric void PreprocessingRecord::MacroDefined(const Token &Id,
457809500fcSDimitry Andric                                        const MacroDirective *MD) {
458809500fcSDimitry Andric   const MacroInfo *MI = MD->getMacroInfo();
459c0c7bca4SRoman Divacky   SourceRange R(MI->getDefinitionLoc(), MI->getDefinitionEndLoc());
4605e20cdd8SDimitry Andric   MacroDefinitionRecord *Def =
4615e20cdd8SDimitry Andric       new (*this) MacroDefinitionRecord(Id.getIdentifierInfo(), R);
462809500fcSDimitry Andric   addPreprocessedEntity(Def);
463809500fcSDimitry Andric   MacroDefinitions[MI] = Def;
464c0c7bca4SRoman Divacky }
465c0c7bca4SRoman Divacky 
MacroUndefined(const Token & Id,const MacroDefinition & MD,const MacroDirective * Undef)466bca07a45SDimitry Andric void PreprocessingRecord::MacroUndefined(const Token &Id,
46757091882SDimitry Andric                                          const MacroDefinition &MD,
46857091882SDimitry Andric                                          const MacroDirective *Undef) {
4695e20cdd8SDimitry Andric   MD.forAllDefinitions([&](MacroInfo *MI) { MacroDefinitions.erase(MI); });
470c0c7bca4SRoman Divacky }
471c0c7bca4SRoman Divacky 
InclusionDirective(SourceLocation HashLoc,const Token & IncludeTok,StringRef FileName,bool IsAngled,CharSourceRange FilenameRange,OptionalFileEntryRef File,StringRef SearchPath,StringRef RelativePath,const Module * SuggestedModule,bool ModuleImported,SrcMgr::CharacteristicKind FileType)47201af97d3SDimitry Andric void PreprocessingRecord::InclusionDirective(
473e3b55780SDimitry Andric     SourceLocation HashLoc, const Token &IncludeTok, StringRef FileName,
474e3b55780SDimitry Andric     bool IsAngled, CharSourceRange FilenameRange, OptionalFileEntryRef File,
475ac9a064cSDimitry Andric     StringRef SearchPath, StringRef RelativePath, const Module *SuggestedModule,
476ac9a064cSDimitry Andric     bool ModuleImported, SrcMgr::CharacteristicKind FileType) {
477bca07a45SDimitry Andric   InclusionDirective::InclusionKind Kind = InclusionDirective::Include;
478bca07a45SDimitry Andric 
479bca07a45SDimitry Andric   switch (IncludeTok.getIdentifierInfo()->getPPKeywordID()) {
480bca07a45SDimitry Andric   case tok::pp_include:
481bca07a45SDimitry Andric     Kind = InclusionDirective::Include;
482bca07a45SDimitry Andric     break;
483bca07a45SDimitry Andric 
484bca07a45SDimitry Andric   case tok::pp_import:
485bca07a45SDimitry Andric     Kind = InclusionDirective::Import;
486bca07a45SDimitry Andric     break;
487bca07a45SDimitry Andric 
488bca07a45SDimitry Andric   case tok::pp_include_next:
489bca07a45SDimitry Andric     Kind = InclusionDirective::IncludeNext;
490bca07a45SDimitry Andric     break;
491bca07a45SDimitry Andric 
492bca07a45SDimitry Andric   case tok::pp___include_macros:
493bca07a45SDimitry Andric     Kind = InclusionDirective::IncludeMacros;
494bca07a45SDimitry Andric     break;
495bca07a45SDimitry Andric 
496bca07a45SDimitry Andric   default:
497bca07a45SDimitry Andric     llvm_unreachable("Unknown include directive kind");
498bca07a45SDimitry Andric   }
499bca07a45SDimitry Andric 
50013cc256eSDimitry Andric   SourceLocation EndLoc;
50113cc256eSDimitry Andric   if (!IsAngled) {
50213cc256eSDimitry Andric     EndLoc = FilenameRange.getBegin();
50313cc256eSDimitry Andric   } else {
50413cc256eSDimitry Andric     EndLoc = FilenameRange.getEnd();
50513cc256eSDimitry Andric     if (FilenameRange.isCharRange())
50613cc256eSDimitry Andric       EndLoc = EndLoc.getLocWithOffset(-1); // the InclusionDirective expects
50713cc256eSDimitry Andric                                             // a token range.
50813cc256eSDimitry Andric   }
509ac9a064cSDimitry Andric   clang::InclusionDirective *ID = new (*this) clang::InclusionDirective(
510ac9a064cSDimitry Andric       *this, Kind, FileName, !IsAngled, ModuleImported, File,
511461a67faSDimitry Andric       SourceRange(HashLoc, EndLoc));
51236981b17SDimitry Andric   addPreprocessedEntity(ID);
51336981b17SDimitry Andric }
51436981b17SDimitry Andric 
getTotalMemory() const51536981b17SDimitry Andric size_t PreprocessingRecord::getTotalMemory() const {
51636981b17SDimitry Andric   return BumpAlloc.getTotalMemory()
51736981b17SDimitry Andric     + llvm::capacity_in_bytes(MacroDefinitions)
51836981b17SDimitry Andric     + llvm::capacity_in_bytes(PreprocessedEntities)
51948675466SDimitry Andric     + llvm::capacity_in_bytes(LoadedPreprocessedEntities)
52048675466SDimitry Andric     + llvm::capacity_in_bytes(SkippedRanges);
521bca07a45SDimitry Andric }
522