10b57cec5SDimitry Andric //===- PreprocessingRecord.cpp - Record of Preprocessing ------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric //  This file implements the PreprocessingRecord class, which maintains a record
100b57cec5SDimitry Andric //  of what occurred during preprocessing, and its helpers.
110b57cec5SDimitry Andric //
120b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric 
140b57cec5SDimitry Andric #include "clang/Lex/PreprocessingRecord.h"
150b57cec5SDimitry Andric #include "clang/Basic/IdentifierTable.h"
160b57cec5SDimitry Andric #include "clang/Basic/LLVM.h"
170b57cec5SDimitry Andric #include "clang/Basic/SourceLocation.h"
180b57cec5SDimitry Andric #include "clang/Basic/SourceManager.h"
190b57cec5SDimitry Andric #include "clang/Basic/TokenKinds.h"
200b57cec5SDimitry Andric #include "clang/Lex/MacroInfo.h"
210b57cec5SDimitry Andric #include "clang/Lex/Token.h"
220b57cec5SDimitry Andric #include "llvm/ADT/DenseMap.h"
230b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h"
240b57cec5SDimitry Andric #include "llvm/ADT/iterator_range.h"
250b57cec5SDimitry Andric #include "llvm/Support/Capacity.h"
260b57cec5SDimitry Andric #include "llvm/Support/Casting.h"
270b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
280b57cec5SDimitry Andric #include <algorithm>
290b57cec5SDimitry Andric #include <cassert>
300b57cec5SDimitry Andric #include <cstddef>
310b57cec5SDimitry Andric #include <cstring>
320b57cec5SDimitry Andric #include <iterator>
33bdd1243dSDimitry Andric #include <optional>
340b57cec5SDimitry Andric #include <utility>
350b57cec5SDimitry Andric #include <vector>
360b57cec5SDimitry Andric 
370b57cec5SDimitry Andric using namespace clang;
380b57cec5SDimitry Andric 
390b57cec5SDimitry Andric ExternalPreprocessingRecordSource::~ExternalPreprocessingRecordSource() =
400b57cec5SDimitry Andric     default;
410b57cec5SDimitry Andric 
InclusionDirective(PreprocessingRecord & PPRec,InclusionKind Kind,StringRef FileName,bool InQuotes,bool ImportedModule,OptionalFileEntryRef File,SourceRange Range)420b57cec5SDimitry Andric InclusionDirective::InclusionDirective(PreprocessingRecord &PPRec,
430b57cec5SDimitry Andric                                        InclusionKind Kind, StringRef FileName,
440b57cec5SDimitry Andric                                        bool InQuotes, bool ImportedModule,
45bdd1243dSDimitry Andric                                        OptionalFileEntryRef File,
4681ad6265SDimitry Andric                                        SourceRange Range)
470b57cec5SDimitry Andric     : PreprocessingDirective(InclusionDirectiveKind, Range), InQuotes(InQuotes),
480b57cec5SDimitry Andric       Kind(Kind), ImportedModule(ImportedModule), File(File) {
490b57cec5SDimitry Andric   char *Memory = (char *)PPRec.Allocate(FileName.size() + 1, alignof(char));
500b57cec5SDimitry Andric   memcpy(Memory, FileName.data(), FileName.size());
510b57cec5SDimitry Andric   Memory[FileName.size()] = 0;
520b57cec5SDimitry Andric   this->FileName = StringRef(Memory, FileName.size());
530b57cec5SDimitry Andric }
540b57cec5SDimitry Andric 
PreprocessingRecord(SourceManager & SM)550b57cec5SDimitry Andric PreprocessingRecord::PreprocessingRecord(SourceManager &SM) : SourceMgr(SM) {}
560b57cec5SDimitry Andric 
570b57cec5SDimitry Andric /// Returns a pair of [Begin, End) iterators of preprocessed entities
580b57cec5SDimitry Andric /// that source range \p Range encompasses.
590b57cec5SDimitry Andric llvm::iterator_range<PreprocessingRecord::iterator>
getPreprocessedEntitiesInRange(SourceRange Range)600b57cec5SDimitry Andric PreprocessingRecord::getPreprocessedEntitiesInRange(SourceRange Range) {
610b57cec5SDimitry Andric   if (Range.isInvalid())
620b57cec5SDimitry Andric     return llvm::make_range(iterator(), iterator());
630b57cec5SDimitry Andric 
640b57cec5SDimitry Andric   if (CachedRangeQuery.Range == Range) {
650b57cec5SDimitry Andric     return llvm::make_range(iterator(this, CachedRangeQuery.Result.first),
660b57cec5SDimitry Andric                             iterator(this, CachedRangeQuery.Result.second));
670b57cec5SDimitry Andric   }
680b57cec5SDimitry Andric 
690b57cec5SDimitry Andric   std::pair<int, int> Res = getPreprocessedEntitiesInRangeSlow(Range);
700b57cec5SDimitry Andric 
710b57cec5SDimitry Andric   CachedRangeQuery.Range = Range;
720b57cec5SDimitry Andric   CachedRangeQuery.Result = Res;
730b57cec5SDimitry Andric 
740b57cec5SDimitry Andric   return llvm::make_range(iterator(this, Res.first),
750b57cec5SDimitry Andric                           iterator(this, Res.second));
760b57cec5SDimitry Andric }
770b57cec5SDimitry Andric 
isPreprocessedEntityIfInFileID(PreprocessedEntity * PPE,FileID FID,SourceManager & SM)780b57cec5SDimitry Andric static bool isPreprocessedEntityIfInFileID(PreprocessedEntity *PPE, FileID FID,
790b57cec5SDimitry Andric                                            SourceManager &SM) {
800b57cec5SDimitry Andric   assert(FID.isValid());
810b57cec5SDimitry Andric   if (!PPE)
820b57cec5SDimitry Andric     return false;
830b57cec5SDimitry Andric 
840b57cec5SDimitry Andric   SourceLocation Loc = PPE->getSourceRange().getBegin();
850b57cec5SDimitry Andric   if (Loc.isInvalid())
860b57cec5SDimitry Andric     return false;
870b57cec5SDimitry Andric 
880b57cec5SDimitry Andric   return SM.isInFileID(SM.getFileLoc(Loc), FID);
890b57cec5SDimitry Andric }
900b57cec5SDimitry Andric 
910b57cec5SDimitry Andric /// Returns true if the preprocessed entity that \arg PPEI iterator
920b57cec5SDimitry Andric /// points to is coming from the file \arg FID.
930b57cec5SDimitry Andric ///
940b57cec5SDimitry Andric /// Can be used to avoid implicit deserializations of preallocated
950b57cec5SDimitry Andric /// preprocessed entities if we only care about entities of a specific file
960b57cec5SDimitry Andric /// and not from files \#included in the range given at
970b57cec5SDimitry Andric /// \see getPreprocessedEntitiesInRange.
isEntityInFileID(iterator PPEI,FileID FID)980b57cec5SDimitry Andric bool PreprocessingRecord::isEntityInFileID(iterator PPEI, FileID FID) {
990b57cec5SDimitry Andric   if (FID.isInvalid())
1000b57cec5SDimitry Andric     return false;
1010b57cec5SDimitry Andric 
1020b57cec5SDimitry Andric   int Pos = std::distance(iterator(this, 0), PPEI);
1030b57cec5SDimitry Andric   if (Pos < 0) {
1040b57cec5SDimitry Andric     if (unsigned(-Pos-1) >= LoadedPreprocessedEntities.size()) {
1050b57cec5SDimitry Andric       assert(0 && "Out-of bounds loaded preprocessed entity");
1060b57cec5SDimitry Andric       return false;
1070b57cec5SDimitry Andric     }
1080b57cec5SDimitry Andric     assert(ExternalSource && "No external source to load from");
1090b57cec5SDimitry Andric     unsigned LoadedIndex = LoadedPreprocessedEntities.size()+Pos;
1100b57cec5SDimitry Andric     if (PreprocessedEntity *PPE = LoadedPreprocessedEntities[LoadedIndex])
1110b57cec5SDimitry Andric       return isPreprocessedEntityIfInFileID(PPE, FID, SourceMgr);
1120b57cec5SDimitry Andric 
1130b57cec5SDimitry Andric     // See if the external source can see if the entity is in the file without
1140b57cec5SDimitry Andric     // deserializing it.
115bdd1243dSDimitry Andric     if (std::optional<bool> IsInFile =
116bdd1243dSDimitry Andric             ExternalSource->isPreprocessedEntityInFileID(LoadedIndex, FID))
117bdd1243dSDimitry Andric       return *IsInFile;
1180b57cec5SDimitry Andric 
1190b57cec5SDimitry Andric     // The external source did not provide a definite answer, go and deserialize
1200b57cec5SDimitry Andric     // the entity to check it.
1210b57cec5SDimitry Andric     return isPreprocessedEntityIfInFileID(
1220b57cec5SDimitry Andric                                        getLoadedPreprocessedEntity(LoadedIndex),
1230b57cec5SDimitry Andric                                           FID, SourceMgr);
1240b57cec5SDimitry Andric   }
1250b57cec5SDimitry Andric 
1260b57cec5SDimitry Andric   if (unsigned(Pos) >= PreprocessedEntities.size()) {
1270b57cec5SDimitry Andric     assert(0 && "Out-of bounds local preprocessed entity");
1280b57cec5SDimitry Andric     return false;
1290b57cec5SDimitry Andric   }
1300b57cec5SDimitry Andric   return isPreprocessedEntityIfInFileID(PreprocessedEntities[Pos],
1310b57cec5SDimitry Andric                                         FID, SourceMgr);
1320b57cec5SDimitry Andric }
1330b57cec5SDimitry Andric 
1340b57cec5SDimitry Andric /// Returns a pair of [Begin, End) iterators of preprocessed entities
1350b57cec5SDimitry Andric /// that source range \arg R encompasses.
1360b57cec5SDimitry Andric std::pair<int, int>
getPreprocessedEntitiesInRangeSlow(SourceRange Range)1370b57cec5SDimitry Andric PreprocessingRecord::getPreprocessedEntitiesInRangeSlow(SourceRange Range) {
1380b57cec5SDimitry Andric   assert(Range.isValid());
1390b57cec5SDimitry Andric   assert(!SourceMgr.isBeforeInTranslationUnit(Range.getEnd(),Range.getBegin()));
1400b57cec5SDimitry Andric 
1410b57cec5SDimitry Andric   std::pair<unsigned, unsigned>
1420b57cec5SDimitry Andric     Local = findLocalPreprocessedEntitiesInRange(Range);
1430b57cec5SDimitry Andric 
1440b57cec5SDimitry Andric   // Check if range spans local entities.
1450b57cec5SDimitry Andric   if (!ExternalSource || SourceMgr.isLocalSourceLocation(Range.getBegin()))
1460b57cec5SDimitry Andric     return std::make_pair(Local.first, Local.second);
1470b57cec5SDimitry Andric 
1480b57cec5SDimitry Andric   std::pair<unsigned, unsigned>
1490b57cec5SDimitry Andric     Loaded = ExternalSource->findPreprocessedEntitiesInRange(Range);
1500b57cec5SDimitry Andric 
1510b57cec5SDimitry Andric   // Check if range spans local entities.
1520b57cec5SDimitry Andric   if (Loaded.first == Loaded.second)
1530b57cec5SDimitry Andric     return std::make_pair(Local.first, Local.second);
1540b57cec5SDimitry Andric 
1550b57cec5SDimitry Andric   unsigned TotalLoaded = LoadedPreprocessedEntities.size();
1560b57cec5SDimitry Andric 
1570b57cec5SDimitry Andric   // Check if range spans loaded entities.
1580b57cec5SDimitry Andric   if (Local.first == Local.second)
1590b57cec5SDimitry Andric     return std::make_pair(int(Loaded.first)-TotalLoaded,
1600b57cec5SDimitry Andric                           int(Loaded.second)-TotalLoaded);
1610b57cec5SDimitry Andric 
1620b57cec5SDimitry Andric   // Range spands loaded and local entities.
1630b57cec5SDimitry Andric   return std::make_pair(int(Loaded.first)-TotalLoaded, Local.second);
1640b57cec5SDimitry Andric }
1650b57cec5SDimitry Andric 
1660b57cec5SDimitry Andric std::pair<unsigned, unsigned>
findLocalPreprocessedEntitiesInRange(SourceRange Range) const1670b57cec5SDimitry Andric PreprocessingRecord::findLocalPreprocessedEntitiesInRange(
1680b57cec5SDimitry Andric                                                       SourceRange Range) const {
1690b57cec5SDimitry Andric   if (Range.isInvalid())
1700b57cec5SDimitry Andric     return std::make_pair(0,0);
1710b57cec5SDimitry Andric   assert(!SourceMgr.isBeforeInTranslationUnit(Range.getEnd(),Range.getBegin()));
1720b57cec5SDimitry Andric 
1730b57cec5SDimitry Andric   unsigned Begin = findBeginLocalPreprocessedEntity(Range.getBegin());
1740b57cec5SDimitry Andric   unsigned End = findEndLocalPreprocessedEntity(Range.getEnd());
1750b57cec5SDimitry Andric   return std::make_pair(Begin, End);
1760b57cec5SDimitry Andric }
1770b57cec5SDimitry Andric 
1780b57cec5SDimitry Andric namespace {
1790b57cec5SDimitry Andric 
1800b57cec5SDimitry Andric template <SourceLocation (SourceRange::*getRangeLoc)() const>
1810b57cec5SDimitry Andric struct PPEntityComp {
1820b57cec5SDimitry Andric   const SourceManager &SM;
1830b57cec5SDimitry Andric 
PPEntityComp__anondd72c81d0111::PPEntityComp1840b57cec5SDimitry Andric   explicit PPEntityComp(const SourceManager &SM) : SM(SM) {}
1850b57cec5SDimitry Andric 
operator ()__anondd72c81d0111::PPEntityComp1860b57cec5SDimitry Andric   bool operator()(PreprocessedEntity *L, PreprocessedEntity *R) const {
1870b57cec5SDimitry Andric     SourceLocation LHS = getLoc(L);
1880b57cec5SDimitry Andric     SourceLocation RHS = getLoc(R);
1890b57cec5SDimitry Andric     return SM.isBeforeInTranslationUnit(LHS, RHS);
1900b57cec5SDimitry Andric   }
1910b57cec5SDimitry Andric 
operator ()__anondd72c81d0111::PPEntityComp1920b57cec5SDimitry Andric   bool operator()(PreprocessedEntity *L, SourceLocation RHS) const {
1930b57cec5SDimitry Andric     SourceLocation LHS = getLoc(L);
1940b57cec5SDimitry Andric     return SM.isBeforeInTranslationUnit(LHS, RHS);
1950b57cec5SDimitry Andric   }
1960b57cec5SDimitry Andric 
operator ()__anondd72c81d0111::PPEntityComp1970b57cec5SDimitry Andric   bool operator()(SourceLocation LHS, PreprocessedEntity *R) const {
1980b57cec5SDimitry Andric     SourceLocation RHS = getLoc(R);
1990b57cec5SDimitry Andric     return SM.isBeforeInTranslationUnit(LHS, RHS);
2000b57cec5SDimitry Andric   }
2010b57cec5SDimitry Andric 
getLoc__anondd72c81d0111::PPEntityComp2020b57cec5SDimitry Andric   SourceLocation getLoc(PreprocessedEntity *PPE) const {
2030b57cec5SDimitry Andric     SourceRange Range = PPE->getSourceRange();
2040b57cec5SDimitry Andric     return (Range.*getRangeLoc)();
2050b57cec5SDimitry Andric   }
2060b57cec5SDimitry Andric };
2070b57cec5SDimitry Andric 
2080b57cec5SDimitry Andric } // namespace
2090b57cec5SDimitry Andric 
findBeginLocalPreprocessedEntity(SourceLocation Loc) const2100b57cec5SDimitry Andric unsigned PreprocessingRecord::findBeginLocalPreprocessedEntity(
2110b57cec5SDimitry Andric                                                      SourceLocation Loc) const {
2120b57cec5SDimitry Andric   if (SourceMgr.isLoadedSourceLocation(Loc))
2130b57cec5SDimitry Andric     return 0;
2140b57cec5SDimitry Andric 
2150b57cec5SDimitry Andric   size_t Count = PreprocessedEntities.size();
2160b57cec5SDimitry Andric   size_t Half;
2170b57cec5SDimitry Andric   std::vector<PreprocessedEntity *>::const_iterator
2180b57cec5SDimitry Andric     First = PreprocessedEntities.begin();
2190b57cec5SDimitry Andric   std::vector<PreprocessedEntity *>::const_iterator I;
2200b57cec5SDimitry Andric 
2210b57cec5SDimitry Andric   // Do a binary search manually instead of using std::lower_bound because
2220b57cec5SDimitry Andric   // The end locations of entities may be unordered (when a macro expansion
2230b57cec5SDimitry Andric   // is inside another macro argument), but for this case it is not important
2240b57cec5SDimitry Andric   // whether we get the first macro expansion or its containing macro.
2250b57cec5SDimitry Andric   while (Count > 0) {
2260b57cec5SDimitry Andric     Half = Count/2;
2270b57cec5SDimitry Andric     I = First;
2280b57cec5SDimitry Andric     std::advance(I, Half);
2290b57cec5SDimitry Andric     if (SourceMgr.isBeforeInTranslationUnit((*I)->getSourceRange().getEnd(),
2300b57cec5SDimitry Andric                                             Loc)){
2310b57cec5SDimitry Andric       First = I;
2320b57cec5SDimitry Andric       ++First;
2330b57cec5SDimitry Andric       Count = Count - Half - 1;
2340b57cec5SDimitry Andric     } else
2350b57cec5SDimitry Andric       Count = Half;
2360b57cec5SDimitry Andric   }
2370b57cec5SDimitry Andric 
2380b57cec5SDimitry Andric   return First - PreprocessedEntities.begin();
2390b57cec5SDimitry Andric }
2400b57cec5SDimitry Andric 
2410b57cec5SDimitry Andric unsigned
findEndLocalPreprocessedEntity(SourceLocation Loc) const2420b57cec5SDimitry Andric PreprocessingRecord::findEndLocalPreprocessedEntity(SourceLocation Loc) const {
2430b57cec5SDimitry Andric   if (SourceMgr.isLoadedSourceLocation(Loc))
2440b57cec5SDimitry Andric     return 0;
2450b57cec5SDimitry Andric 
2460b57cec5SDimitry Andric   auto I = llvm::upper_bound(PreprocessedEntities, Loc,
2470b57cec5SDimitry Andric                              PPEntityComp<&SourceRange::getBegin>(SourceMgr));
2480b57cec5SDimitry Andric   return I - PreprocessedEntities.begin();
2490b57cec5SDimitry Andric }
2500b57cec5SDimitry Andric 
2510b57cec5SDimitry Andric PreprocessingRecord::PPEntityID
addPreprocessedEntity(PreprocessedEntity * Entity)2520b57cec5SDimitry Andric PreprocessingRecord::addPreprocessedEntity(PreprocessedEntity *Entity) {
2530b57cec5SDimitry Andric   assert(Entity);
2540b57cec5SDimitry Andric   SourceLocation BeginLoc = Entity->getSourceRange().getBegin();
2550b57cec5SDimitry Andric 
2560b57cec5SDimitry Andric   if (isa<MacroDefinitionRecord>(Entity)) {
2570b57cec5SDimitry Andric     assert((PreprocessedEntities.empty() ||
2580b57cec5SDimitry Andric             !SourceMgr.isBeforeInTranslationUnit(
2590b57cec5SDimitry Andric                 BeginLoc,
2600b57cec5SDimitry Andric                 PreprocessedEntities.back()->getSourceRange().getBegin())) &&
2610b57cec5SDimitry Andric            "a macro definition was encountered out-of-order");
2620b57cec5SDimitry Andric     PreprocessedEntities.push_back(Entity);
2630b57cec5SDimitry Andric     return getPPEntityID(PreprocessedEntities.size()-1, /*isLoaded=*/false);
2640b57cec5SDimitry Andric   }
2650b57cec5SDimitry Andric 
2660b57cec5SDimitry Andric   // Check normal case, this entity begin location is after the previous one.
2670b57cec5SDimitry Andric   if (PreprocessedEntities.empty() ||
2680b57cec5SDimitry Andric       !SourceMgr.isBeforeInTranslationUnit(BeginLoc,
2690b57cec5SDimitry Andric                    PreprocessedEntities.back()->getSourceRange().getBegin())) {
2700b57cec5SDimitry Andric     PreprocessedEntities.push_back(Entity);
2710b57cec5SDimitry Andric     return getPPEntityID(PreprocessedEntities.size()-1, /*isLoaded=*/false);
2720b57cec5SDimitry Andric   }
2730b57cec5SDimitry Andric 
2740b57cec5SDimitry Andric   // The entity's location is not after the previous one; this can happen with
2750b57cec5SDimitry Andric   // include directives that form the filename using macros, e.g:
2760b57cec5SDimitry Andric   // "#include MACRO(STUFF)"
2770b57cec5SDimitry Andric   // or with macro expansions inside macro arguments where the arguments are
2780b57cec5SDimitry Andric   // not expanded in the same order as listed, e.g:
2790b57cec5SDimitry Andric   // \code
2800b57cec5SDimitry Andric   //  #define M1 1
2810b57cec5SDimitry Andric   //  #define M2 2
2820b57cec5SDimitry Andric   //  #define FM(x,y) y x
2830b57cec5SDimitry Andric   //  FM(M1, M2)
2840b57cec5SDimitry Andric   // \endcode
2850b57cec5SDimitry Andric 
2860b57cec5SDimitry Andric   using pp_iter = std::vector<PreprocessedEntity *>::iterator;
2870b57cec5SDimitry Andric 
2880b57cec5SDimitry Andric   // Usually there are few macro expansions when defining the filename, do a
2890b57cec5SDimitry Andric   // linear search for a few entities.
2900b57cec5SDimitry Andric   unsigned count = 0;
2910b57cec5SDimitry Andric   for (pp_iter RI    = PreprocessedEntities.end(),
2920b57cec5SDimitry Andric                Begin = PreprocessedEntities.begin();
2930b57cec5SDimitry Andric        RI != Begin && count < 4; --RI, ++count) {
2940b57cec5SDimitry Andric     pp_iter I = RI;
2950b57cec5SDimitry Andric     --I;
2960b57cec5SDimitry Andric     if (!SourceMgr.isBeforeInTranslationUnit(BeginLoc,
2970b57cec5SDimitry Andric                                            (*I)->getSourceRange().getBegin())) {
2980b57cec5SDimitry Andric       pp_iter insertI = PreprocessedEntities.insert(RI, Entity);
2990b57cec5SDimitry Andric       return getPPEntityID(insertI - PreprocessedEntities.begin(),
3000b57cec5SDimitry Andric                            /*isLoaded=*/false);
3010b57cec5SDimitry Andric     }
3020b57cec5SDimitry Andric   }
3030b57cec5SDimitry Andric 
3040b57cec5SDimitry Andric   // Linear search unsuccessful. Do a binary search.
3050b57cec5SDimitry Andric   pp_iter I =
3060b57cec5SDimitry Andric       llvm::upper_bound(PreprocessedEntities, BeginLoc,
3070b57cec5SDimitry Andric                         PPEntityComp<&SourceRange::getBegin>(SourceMgr));
3080b57cec5SDimitry Andric   pp_iter insertI = PreprocessedEntities.insert(I, Entity);
3090b57cec5SDimitry Andric   return getPPEntityID(insertI - PreprocessedEntities.begin(),
3100b57cec5SDimitry Andric                        /*isLoaded=*/false);
3110b57cec5SDimitry Andric }
3120b57cec5SDimitry Andric 
SetExternalSource(ExternalPreprocessingRecordSource & Source)3130b57cec5SDimitry Andric void PreprocessingRecord::SetExternalSource(
3140b57cec5SDimitry Andric                                     ExternalPreprocessingRecordSource &Source) {
3150b57cec5SDimitry Andric   assert(!ExternalSource &&
3160b57cec5SDimitry Andric          "Preprocessing record already has an external source");
3170b57cec5SDimitry Andric   ExternalSource = &Source;
3180b57cec5SDimitry Andric }
3190b57cec5SDimitry Andric 
allocateLoadedEntities(unsigned NumEntities)3200b57cec5SDimitry Andric unsigned PreprocessingRecord::allocateLoadedEntities(unsigned NumEntities) {
3210b57cec5SDimitry Andric   unsigned Result = LoadedPreprocessedEntities.size();
3220b57cec5SDimitry Andric   LoadedPreprocessedEntities.resize(LoadedPreprocessedEntities.size()
3230b57cec5SDimitry Andric                                     + NumEntities);
3240b57cec5SDimitry Andric   return Result;
3250b57cec5SDimitry Andric }
3260b57cec5SDimitry Andric 
allocateSkippedRanges(unsigned NumRanges)3270b57cec5SDimitry Andric unsigned PreprocessingRecord::allocateSkippedRanges(unsigned NumRanges) {
3280b57cec5SDimitry Andric   unsigned Result = SkippedRanges.size();
3290b57cec5SDimitry Andric   SkippedRanges.resize(SkippedRanges.size() + NumRanges);
3300b57cec5SDimitry Andric   SkippedRangesAllLoaded = false;
3310b57cec5SDimitry Andric   return Result;
3320b57cec5SDimitry Andric }
3330b57cec5SDimitry Andric 
ensureSkippedRangesLoaded()3340b57cec5SDimitry Andric void PreprocessingRecord::ensureSkippedRangesLoaded() {
3350b57cec5SDimitry Andric   if (SkippedRangesAllLoaded || !ExternalSource)
3360b57cec5SDimitry Andric     return;
3370b57cec5SDimitry Andric   for (unsigned Index = 0; Index != SkippedRanges.size(); ++Index) {
3380b57cec5SDimitry Andric     if (SkippedRanges[Index].isInvalid())
3390b57cec5SDimitry Andric       SkippedRanges[Index] = ExternalSource->ReadSkippedRange(Index);
3400b57cec5SDimitry Andric   }
3410b57cec5SDimitry Andric   SkippedRangesAllLoaded = true;
3420b57cec5SDimitry Andric }
3430b57cec5SDimitry Andric 
RegisterMacroDefinition(MacroInfo * Macro,MacroDefinitionRecord * Def)3440b57cec5SDimitry Andric void PreprocessingRecord::RegisterMacroDefinition(MacroInfo *Macro,
3450b57cec5SDimitry Andric                                                   MacroDefinitionRecord *Def) {
3460b57cec5SDimitry Andric   MacroDefinitions[Macro] = Def;
3470b57cec5SDimitry Andric }
3480b57cec5SDimitry Andric 
3490b57cec5SDimitry Andric /// Retrieve the preprocessed entity at the given ID.
getPreprocessedEntity(PPEntityID PPID)3500b57cec5SDimitry Andric PreprocessedEntity *PreprocessingRecord::getPreprocessedEntity(PPEntityID PPID){
3510b57cec5SDimitry Andric   if (PPID.ID < 0) {
3520b57cec5SDimitry Andric     unsigned Index = -PPID.ID - 1;
3530b57cec5SDimitry Andric     assert(Index < LoadedPreprocessedEntities.size() &&
3540b57cec5SDimitry Andric            "Out-of bounds loaded preprocessed entity");
3550b57cec5SDimitry Andric     return getLoadedPreprocessedEntity(Index);
3560b57cec5SDimitry Andric   }
3570b57cec5SDimitry Andric 
3580b57cec5SDimitry Andric   if (PPID.ID == 0)
3590b57cec5SDimitry Andric     return nullptr;
3600b57cec5SDimitry Andric   unsigned Index = PPID.ID - 1;
3610b57cec5SDimitry Andric   assert(Index < PreprocessedEntities.size() &&
3620b57cec5SDimitry Andric          "Out-of bounds local preprocessed entity");
3630b57cec5SDimitry Andric   return PreprocessedEntities[Index];
3640b57cec5SDimitry Andric }
3650b57cec5SDimitry Andric 
3660b57cec5SDimitry Andric /// Retrieve the loaded preprocessed entity at the given index.
3670b57cec5SDimitry Andric PreprocessedEntity *
getLoadedPreprocessedEntity(unsigned Index)3680b57cec5SDimitry Andric PreprocessingRecord::getLoadedPreprocessedEntity(unsigned Index) {
3690b57cec5SDimitry Andric   assert(Index < LoadedPreprocessedEntities.size() &&
3700b57cec5SDimitry Andric          "Out-of bounds loaded preprocessed entity");
3710b57cec5SDimitry Andric   assert(ExternalSource && "No external source to load from");
3720b57cec5SDimitry Andric   PreprocessedEntity *&Entity = LoadedPreprocessedEntities[Index];
3730b57cec5SDimitry Andric   if (!Entity) {
3740b57cec5SDimitry Andric     Entity = ExternalSource->ReadPreprocessedEntity(Index);
3750b57cec5SDimitry Andric     if (!Entity) // Failed to load.
3760b57cec5SDimitry Andric       Entity = new (*this)
3770b57cec5SDimitry Andric          PreprocessedEntity(PreprocessedEntity::InvalidKind, SourceRange());
3780b57cec5SDimitry Andric   }
3790b57cec5SDimitry Andric   return Entity;
3800b57cec5SDimitry Andric }
3810b57cec5SDimitry Andric 
3820b57cec5SDimitry Andric MacroDefinitionRecord *
findMacroDefinition(const MacroInfo * MI)3830b57cec5SDimitry Andric PreprocessingRecord::findMacroDefinition(const MacroInfo *MI) {
38406c3fb27SDimitry Andric   return MacroDefinitions.lookup(MI);
3850b57cec5SDimitry Andric }
3860b57cec5SDimitry Andric 
addMacroExpansion(const Token & Id,const MacroInfo * MI,SourceRange Range)3870b57cec5SDimitry Andric void PreprocessingRecord::addMacroExpansion(const Token &Id,
3880b57cec5SDimitry Andric                                             const MacroInfo *MI,
3890b57cec5SDimitry Andric                                             SourceRange Range) {
3900b57cec5SDimitry Andric   // We don't record nested macro expansions.
3910b57cec5SDimitry Andric   if (Id.getLocation().isMacroID())
3920b57cec5SDimitry Andric     return;
3930b57cec5SDimitry Andric 
3940b57cec5SDimitry Andric   if (MI->isBuiltinMacro())
3950b57cec5SDimitry Andric     addPreprocessedEntity(new (*this)
3960b57cec5SDimitry Andric                               MacroExpansion(Id.getIdentifierInfo(), Range));
3970b57cec5SDimitry Andric   else if (MacroDefinitionRecord *Def = findMacroDefinition(MI))
3980b57cec5SDimitry Andric     addPreprocessedEntity(new (*this) MacroExpansion(Def, Range));
3990b57cec5SDimitry Andric }
4000b57cec5SDimitry Andric 
Ifdef(SourceLocation Loc,const Token & MacroNameTok,const MacroDefinition & MD)4010b57cec5SDimitry Andric void PreprocessingRecord::Ifdef(SourceLocation Loc, const Token &MacroNameTok,
4020b57cec5SDimitry Andric                                 const MacroDefinition &MD) {
4030b57cec5SDimitry Andric   // This is not actually a macro expansion but record it as a macro reference.
4040b57cec5SDimitry Andric   if (MD)
4050b57cec5SDimitry Andric     addMacroExpansion(MacroNameTok, MD.getMacroInfo(),
4060b57cec5SDimitry Andric                       MacroNameTok.getLocation());
4070b57cec5SDimitry Andric }
4080b57cec5SDimitry Andric 
Elifdef(SourceLocation Loc,const Token & MacroNameTok,const MacroDefinition & MD)409fe6060f1SDimitry Andric void PreprocessingRecord::Elifdef(SourceLocation Loc, const Token &MacroNameTok,
410fe6060f1SDimitry Andric                                   const MacroDefinition &MD) {
411fe6060f1SDimitry Andric   // This is not actually a macro expansion but record it as a macro reference.
412fe6060f1SDimitry Andric   if (MD)
413fe6060f1SDimitry Andric     addMacroExpansion(MacroNameTok, MD.getMacroInfo(),
414fe6060f1SDimitry Andric                       MacroNameTok.getLocation());
415fe6060f1SDimitry Andric }
416fe6060f1SDimitry Andric 
Ifndef(SourceLocation Loc,const Token & MacroNameTok,const MacroDefinition & MD)4170b57cec5SDimitry Andric void PreprocessingRecord::Ifndef(SourceLocation Loc, const Token &MacroNameTok,
4180b57cec5SDimitry Andric                                  const MacroDefinition &MD) {
4190b57cec5SDimitry Andric   // This is not actually a macro expansion but record it as a macro reference.
4200b57cec5SDimitry Andric   if (MD)
4210b57cec5SDimitry Andric     addMacroExpansion(MacroNameTok, MD.getMacroInfo(),
4220b57cec5SDimitry Andric                       MacroNameTok.getLocation());
4230b57cec5SDimitry Andric }
4240b57cec5SDimitry Andric 
Elifndef(SourceLocation Loc,const Token & MacroNameTok,const MacroDefinition & MD)425fe6060f1SDimitry Andric void PreprocessingRecord::Elifndef(SourceLocation Loc,
426fe6060f1SDimitry Andric                                    const Token &MacroNameTok,
427fe6060f1SDimitry Andric                                    const MacroDefinition &MD) {
428fe6060f1SDimitry Andric   // This is not actually a macro expansion but record it as a macro reference.
429fe6060f1SDimitry Andric   if (MD)
430fe6060f1SDimitry Andric     addMacroExpansion(MacroNameTok, MD.getMacroInfo(),
431fe6060f1SDimitry Andric                       MacroNameTok.getLocation());
432fe6060f1SDimitry Andric }
433fe6060f1SDimitry Andric 
Defined(const Token & MacroNameTok,const MacroDefinition & MD,SourceRange Range)4340b57cec5SDimitry Andric void PreprocessingRecord::Defined(const Token &MacroNameTok,
4350b57cec5SDimitry Andric                                   const MacroDefinition &MD,
4360b57cec5SDimitry Andric                                   SourceRange Range) {
4370b57cec5SDimitry Andric   // This is not actually a macro expansion but record it as a macro reference.
4380b57cec5SDimitry Andric   if (MD)
4390b57cec5SDimitry Andric     addMacroExpansion(MacroNameTok, MD.getMacroInfo(),
4400b57cec5SDimitry Andric                       MacroNameTok.getLocation());
4410b57cec5SDimitry Andric }
4420b57cec5SDimitry Andric 
SourceRangeSkipped(SourceRange Range,SourceLocation EndifLoc)4430b57cec5SDimitry Andric void PreprocessingRecord::SourceRangeSkipped(SourceRange Range,
4440b57cec5SDimitry Andric                                              SourceLocation EndifLoc) {
4450b57cec5SDimitry Andric   assert(Range.isValid());
4460b57cec5SDimitry Andric   SkippedRanges.emplace_back(Range.getBegin(), EndifLoc);
4470b57cec5SDimitry Andric }
4480b57cec5SDimitry Andric 
MacroExpands(const Token & Id,const MacroDefinition & MD,SourceRange Range,const MacroArgs * Args)4490b57cec5SDimitry Andric void PreprocessingRecord::MacroExpands(const Token &Id,
4500b57cec5SDimitry Andric                                        const MacroDefinition &MD,
4510b57cec5SDimitry Andric                                        SourceRange Range,
4520b57cec5SDimitry Andric                                        const MacroArgs *Args) {
4530b57cec5SDimitry Andric   addMacroExpansion(Id, MD.getMacroInfo(), Range);
4540b57cec5SDimitry Andric }
4550b57cec5SDimitry Andric 
MacroDefined(const Token & Id,const MacroDirective * MD)4560b57cec5SDimitry Andric void PreprocessingRecord::MacroDefined(const Token &Id,
4570b57cec5SDimitry Andric                                        const MacroDirective *MD) {
4580b57cec5SDimitry Andric   const MacroInfo *MI = MD->getMacroInfo();
4590b57cec5SDimitry Andric   SourceRange R(MI->getDefinitionLoc(), MI->getDefinitionEndLoc());
4600b57cec5SDimitry Andric   MacroDefinitionRecord *Def =
4610b57cec5SDimitry Andric       new (*this) MacroDefinitionRecord(Id.getIdentifierInfo(), R);
4620b57cec5SDimitry Andric   addPreprocessedEntity(Def);
4630b57cec5SDimitry Andric   MacroDefinitions[MI] = Def;
4640b57cec5SDimitry Andric }
4650b57cec5SDimitry Andric 
MacroUndefined(const Token & Id,const MacroDefinition & MD,const MacroDirective * Undef)4660b57cec5SDimitry Andric void PreprocessingRecord::MacroUndefined(const Token &Id,
4670b57cec5SDimitry Andric                                          const MacroDefinition &MD,
4680b57cec5SDimitry Andric                                          const MacroDirective *Undef) {
4690b57cec5SDimitry Andric   MD.forAllDefinitions([&](MacroInfo *MI) { MacroDefinitions.erase(MI); });
4700b57cec5SDimitry Andric }
4710b57cec5SDimitry Andric 
InclusionDirective(SourceLocation HashLoc,const Token & IncludeTok,StringRef FileName,bool IsAngled,CharSourceRange FilenameRange,OptionalFileEntryRef File,StringRef SearchPath,StringRef RelativePath,const Module * Imported,SrcMgr::CharacteristicKind FileType)4720b57cec5SDimitry Andric void PreprocessingRecord::InclusionDirective(
473bdd1243dSDimitry Andric     SourceLocation HashLoc, const Token &IncludeTok, StringRef FileName,
474bdd1243dSDimitry Andric     bool IsAngled, CharSourceRange FilenameRange, OptionalFileEntryRef File,
475bdd1243dSDimitry Andric     StringRef SearchPath, StringRef RelativePath, const Module *Imported,
4760b57cec5SDimitry Andric     SrcMgr::CharacteristicKind FileType) {
4770b57cec5SDimitry Andric   InclusionDirective::InclusionKind Kind = InclusionDirective::Include;
4780b57cec5SDimitry Andric 
4790b57cec5SDimitry Andric   switch (IncludeTok.getIdentifierInfo()->getPPKeywordID()) {
4800b57cec5SDimitry Andric   case tok::pp_include:
4810b57cec5SDimitry Andric     Kind = InclusionDirective::Include;
4820b57cec5SDimitry Andric     break;
4830b57cec5SDimitry Andric 
4840b57cec5SDimitry Andric   case tok::pp_import:
4850b57cec5SDimitry Andric     Kind = InclusionDirective::Import;
4860b57cec5SDimitry Andric     break;
4870b57cec5SDimitry Andric 
4880b57cec5SDimitry Andric   case tok::pp_include_next:
4890b57cec5SDimitry Andric     Kind = InclusionDirective::IncludeNext;
4900b57cec5SDimitry Andric     break;
4910b57cec5SDimitry Andric 
4920b57cec5SDimitry Andric   case tok::pp___include_macros:
4930b57cec5SDimitry Andric     Kind = InclusionDirective::IncludeMacros;
4940b57cec5SDimitry Andric     break;
4950b57cec5SDimitry Andric 
4960b57cec5SDimitry Andric   default:
4970b57cec5SDimitry Andric     llvm_unreachable("Unknown include directive kind");
4980b57cec5SDimitry Andric   }
4990b57cec5SDimitry Andric 
5000b57cec5SDimitry Andric   SourceLocation EndLoc;
5010b57cec5SDimitry Andric   if (!IsAngled) {
5020b57cec5SDimitry Andric     EndLoc = FilenameRange.getBegin();
5030b57cec5SDimitry Andric   } else {
5040b57cec5SDimitry Andric     EndLoc = FilenameRange.getEnd();
5050b57cec5SDimitry Andric     if (FilenameRange.isCharRange())
5060b57cec5SDimitry Andric       EndLoc = EndLoc.getLocWithOffset(-1); // the InclusionDirective expects
5070b57cec5SDimitry Andric                                             // a token range.
5080b57cec5SDimitry Andric   }
5090b57cec5SDimitry Andric   clang::InclusionDirective *ID =
5100b57cec5SDimitry Andric       new (*this) clang::InclusionDirective(*this, Kind, FileName, !IsAngled,
5110b57cec5SDimitry Andric                                             (bool)Imported, File,
5120b57cec5SDimitry Andric                                             SourceRange(HashLoc, EndLoc));
5130b57cec5SDimitry Andric   addPreprocessedEntity(ID);
5140b57cec5SDimitry Andric }
5150b57cec5SDimitry Andric 
getTotalMemory() const5160b57cec5SDimitry Andric size_t PreprocessingRecord::getTotalMemory() const {
5170b57cec5SDimitry Andric   return BumpAlloc.getTotalMemory()
5180b57cec5SDimitry Andric     + llvm::capacity_in_bytes(MacroDefinitions)
5190b57cec5SDimitry Andric     + llvm::capacity_in_bytes(PreprocessedEntities)
5200b57cec5SDimitry Andric     + llvm::capacity_in_bytes(LoadedPreprocessedEntities)
5210b57cec5SDimitry Andric     + llvm::capacity_in_bytes(SkippedRanges);
5220b57cec5SDimitry Andric }
523