clang API Documentation

PreprocessingRecord.cpp
Go to the documentation of this file.
00001 //===--- PreprocessingRecord.cpp - Record of Preprocessing ------*- C++ -*-===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 //
00010 //  This file implements the PreprocessingRecord class, which maintains a record
00011 //  of what occurred during preprocessing, and its helpers.
00012 //
00013 //===----------------------------------------------------------------------===//
00014 #include "clang/Lex/PreprocessingRecord.h"
00015 #include "clang/Lex/MacroInfo.h"
00016 #include "clang/Lex/Token.h"
00017 #include "llvm/Support/ErrorHandling.h"
00018 #include "llvm/Support/Capacity.h"
00019 
00020 using namespace clang;
00021 
00022 ExternalPreprocessingRecordSource::~ExternalPreprocessingRecordSource() { }
00023 
00024 
00025 InclusionDirective::InclusionDirective(PreprocessingRecord &PPRec,
00026                                        InclusionKind Kind, 
00027                                        StringRef FileName, 
00028                                        bool InQuotes, const FileEntry *File, 
00029                                        SourceRange Range)
00030   : PreprocessingDirective(InclusionDirectiveKind, Range), 
00031     InQuotes(InQuotes), Kind(Kind), File(File) 
00032 { 
00033   char *Memory 
00034     = (char*)PPRec.Allocate(FileName.size() + 1, llvm::alignOf<char>());
00035   memcpy(Memory, FileName.data(), FileName.size());
00036   Memory[FileName.size()] = 0;
00037   this->FileName = StringRef(Memory, FileName.size());
00038 }
00039 
00040 PreprocessingRecord::PreprocessingRecord(SourceManager &SM,
00041                                          bool RecordConditionalDirectives)
00042   : SourceMgr(SM),
00043     RecordCondDirectives(RecordConditionalDirectives), CondDirectiveNextIdx(0),
00044     ExternalSource(0)
00045 {
00046   if (RecordCondDirectives)
00047     CondDirectiveStack.push_back(CondDirectiveNextIdx++);
00048 }
00049 
00050 /// \brief Returns a pair of [Begin, End) iterators of preprocessed entities
00051 /// that source range \arg R encompasses.
00052 std::pair<PreprocessingRecord::iterator, PreprocessingRecord::iterator>
00053 PreprocessingRecord::getPreprocessedEntitiesInRange(SourceRange Range) {
00054   if (Range.isInvalid())
00055     return std::make_pair(iterator(), iterator());
00056 
00057   if (CachedRangeQuery.Range == Range) {
00058     return std::make_pair(iterator(this, CachedRangeQuery.Result.first),
00059                           iterator(this, CachedRangeQuery.Result.second));
00060   }
00061 
00062   std::pair<PPEntityID, PPEntityID>
00063     Res = getPreprocessedEntitiesInRangeSlow(Range);
00064   
00065   CachedRangeQuery.Range = Range;
00066   CachedRangeQuery.Result = Res;
00067   
00068   return std::make_pair(iterator(this, Res.first), iterator(this, Res.second));
00069 }
00070 
00071 static bool isPreprocessedEntityIfInFileID(PreprocessedEntity *PPE, FileID FID,
00072                                            SourceManager &SM) {
00073   assert(!FID.isInvalid());
00074   if (!PPE)
00075     return false;
00076 
00077   SourceLocation Loc = PPE->getSourceRange().getBegin();
00078   if (Loc.isInvalid())
00079     return false;
00080   
00081   if (SM.isInFileID(SM.getFileLoc(Loc), FID))
00082     return true;
00083   else
00084     return false;
00085 }
00086 
00087 /// \brief Returns true if the preprocessed entity that \arg PPEI iterator
00088 /// points to is coming from the file \arg FID.
00089 ///
00090 /// Can be used to avoid implicit deserializations of preallocated
00091 /// preprocessed entities if we only care about entities of a specific file
00092 /// and not from files #included in the range given at
00093 /// \see getPreprocessedEntitiesInRange.
00094 bool PreprocessingRecord::isEntityInFileID(iterator PPEI, FileID FID) {
00095   if (FID.isInvalid())
00096     return false;
00097 
00098   PPEntityID PPID = PPEI.Position;
00099   if (PPID < 0) {
00100     assert(unsigned(-PPID-1) < LoadedPreprocessedEntities.size() &&
00101            "Out-of bounds loaded preprocessed entity");
00102     assert(ExternalSource && "No external source to load from");
00103     unsigned LoadedIndex = LoadedPreprocessedEntities.size()+PPID;
00104     if (PreprocessedEntity *PPE = LoadedPreprocessedEntities[LoadedIndex])
00105       return isPreprocessedEntityIfInFileID(PPE, FID, SourceMgr);
00106 
00107     // See if the external source can see if the entity is in the file without
00108     // deserializing it.
00109     llvm::Optional<bool>
00110       IsInFile = ExternalSource->isPreprocessedEntityInFileID(LoadedIndex, FID);
00111     if (IsInFile.hasValue())
00112       return IsInFile.getValue();
00113 
00114     // The external source did not provide a definite answer, go and deserialize
00115     // the entity to check it.
00116     return isPreprocessedEntityIfInFileID(
00117                                        getLoadedPreprocessedEntity(LoadedIndex),
00118                                           FID, SourceMgr);
00119   }
00120 
00121   assert(unsigned(PPID) < PreprocessedEntities.size() &&
00122          "Out-of bounds local preprocessed entity");
00123   return isPreprocessedEntityIfInFileID(PreprocessedEntities[PPID],
00124                                         FID, SourceMgr);
00125 }
00126 
00127 /// \brief Returns a pair of [Begin, End) iterators of preprocessed entities
00128 /// that source range \arg R encompasses.
00129 std::pair<PreprocessingRecord::PPEntityID, PreprocessingRecord::PPEntityID>
00130 PreprocessingRecord::getPreprocessedEntitiesInRangeSlow(SourceRange Range) {
00131   assert(Range.isValid());
00132   assert(!SourceMgr.isBeforeInTranslationUnit(Range.getEnd(),Range.getBegin()));
00133   
00134   std::pair<unsigned, unsigned>
00135     Local = findLocalPreprocessedEntitiesInRange(Range);
00136   
00137   // Check if range spans local entities.
00138   if (!ExternalSource || SourceMgr.isLocalSourceLocation(Range.getBegin()))
00139     return std::make_pair(Local.first, Local.second);
00140   
00141   std::pair<unsigned, unsigned>
00142     Loaded = ExternalSource->findPreprocessedEntitiesInRange(Range);
00143   
00144   // Check if range spans local entities.
00145   if (Loaded.first == Loaded.second)
00146     return std::make_pair(Local.first, Local.second);
00147   
00148   unsigned TotalLoaded = LoadedPreprocessedEntities.size();
00149   
00150   // Check if range spans loaded entities.
00151   if (Local.first == Local.second)
00152     return std::make_pair(int(Loaded.first)-TotalLoaded,
00153                           int(Loaded.second)-TotalLoaded);
00154   
00155   // Range spands loaded and local entities.
00156   return std::make_pair(int(Loaded.first)-TotalLoaded, Local.second);
00157 }
00158 
00159 std::pair<unsigned, unsigned>
00160 PreprocessingRecord::findLocalPreprocessedEntitiesInRange(
00161                                                       SourceRange Range) const {
00162   if (Range.isInvalid())
00163     return std::make_pair(0,0);
00164   assert(!SourceMgr.isBeforeInTranslationUnit(Range.getEnd(),Range.getBegin()));
00165 
00166   unsigned Begin = findBeginLocalPreprocessedEntity(Range.getBegin());
00167   unsigned End = findEndLocalPreprocessedEntity(Range.getEnd());
00168   return std::make_pair(Begin, End);
00169 }
00170 
00171 namespace {
00172 
00173 template <SourceLocation (SourceRange::*getRangeLoc)() const>
00174 struct PPEntityComp {
00175   const SourceManager &SM;
00176 
00177   explicit PPEntityComp(const SourceManager &SM) : SM(SM) { }
00178 
00179   bool operator()(PreprocessedEntity *L, PreprocessedEntity *R) const {
00180     SourceLocation LHS = getLoc(L);
00181     SourceLocation RHS = getLoc(R);
00182     return SM.isBeforeInTranslationUnit(LHS, RHS);
00183   }
00184 
00185   bool operator()(PreprocessedEntity *L, SourceLocation RHS) const {
00186     SourceLocation LHS = getLoc(L);
00187     return SM.isBeforeInTranslationUnit(LHS, RHS);
00188   }
00189 
00190   bool operator()(SourceLocation LHS, PreprocessedEntity *R) const {
00191     SourceLocation RHS = getLoc(R);
00192     return SM.isBeforeInTranslationUnit(LHS, RHS);
00193   }
00194 
00195   SourceLocation getLoc(PreprocessedEntity *PPE) const {
00196     SourceRange Range = PPE->getSourceRange();
00197     return (Range.*getRangeLoc)();
00198   }
00199 };
00200 
00201 }
00202 
00203 unsigned PreprocessingRecord::findBeginLocalPreprocessedEntity(
00204                                                      SourceLocation Loc) const {
00205   if (SourceMgr.isLoadedSourceLocation(Loc))
00206     return 0;
00207 
00208   size_t Count = PreprocessedEntities.size();
00209   size_t Half;
00210   std::vector<PreprocessedEntity *>::const_iterator
00211     First = PreprocessedEntities.begin();
00212   std::vector<PreprocessedEntity *>::const_iterator I;
00213 
00214   // Do a binary search manually instead of using std::lower_bound because
00215   // The end locations of entities may be unordered (when a macro expansion
00216   // is inside another macro argument), but for this case it is not important
00217   // whether we get the first macro expansion or its containing macro.
00218   while (Count > 0) {
00219     Half = Count/2;
00220     I = First;
00221     std::advance(I, Half);
00222     if (SourceMgr.isBeforeInTranslationUnit((*I)->getSourceRange().getEnd(),
00223                                             Loc)){
00224       First = I;
00225       ++First;
00226       Count = Count - Half - 1;
00227     } else
00228       Count = Half;
00229   }
00230 
00231   return First - PreprocessedEntities.begin();
00232 }
00233 
00234 unsigned PreprocessingRecord::findEndLocalPreprocessedEntity(
00235                                                      SourceLocation Loc) const {
00236   if (SourceMgr.isLoadedSourceLocation(Loc))
00237     return 0;
00238 
00239   std::vector<PreprocessedEntity *>::const_iterator
00240   I = std::upper_bound(PreprocessedEntities.begin(),
00241                        PreprocessedEntities.end(),
00242                        Loc,
00243                        PPEntityComp<&SourceRange::getBegin>(SourceMgr));
00244   return I - PreprocessedEntities.begin();
00245 }
00246 
00247 PreprocessingRecord::PPEntityID
00248 PreprocessingRecord::addPreprocessedEntity(PreprocessedEntity *Entity) {
00249   assert(Entity);
00250   SourceLocation BeginLoc = Entity->getSourceRange().getBegin();
00251 
00252   if (!isa<class InclusionDirective>(Entity)) {
00253     assert((PreprocessedEntities.empty() ||
00254             !SourceMgr.isBeforeInTranslationUnit(BeginLoc,
00255                    PreprocessedEntities.back()->getSourceRange().getBegin())) &&
00256            "a macro directive was encountered out-of-order");
00257     PreprocessedEntities.push_back(Entity);
00258     return getPPEntityID(PreprocessedEntities.size()-1, /*isLoaded=*/false);
00259   }
00260 
00261   // Check normal case, this entity begin location is after the previous one.
00262   if (PreprocessedEntities.empty() ||
00263       !SourceMgr.isBeforeInTranslationUnit(BeginLoc,
00264                    PreprocessedEntities.back()->getSourceRange().getBegin())) {
00265     PreprocessedEntities.push_back(Entity);
00266     return getPPEntityID(PreprocessedEntities.size()-1, /*isLoaded=*/false);
00267   }
00268 
00269   // The entity's location is not after the previous one; this can happen with
00270   // include directives that form the filename using macros, e.g:
00271   // "#include MACRO(STUFF)".
00272 
00273   typedef std::vector<PreprocessedEntity *>::iterator pp_iter;
00274 
00275   // Usually there are few macro expansions when defining the filename, do a
00276   // linear search for a few entities.
00277   unsigned count = 0;
00278   for (pp_iter RI    = PreprocessedEntities.end(),
00279                Begin = PreprocessedEntities.begin();
00280        RI != Begin && count < 4; --RI, ++count) {
00281     pp_iter I = RI;
00282     --I;
00283     if (!SourceMgr.isBeforeInTranslationUnit(BeginLoc,
00284                                            (*I)->getSourceRange().getBegin())) {
00285       pp_iter insertI = PreprocessedEntities.insert(RI, Entity);
00286       return getPPEntityID(insertI - PreprocessedEntities.begin(),
00287                            /*isLoaded=*/false);
00288     }
00289   }
00290 
00291   // Linear search unsuccessful. Do a binary search.
00292   pp_iter I = std::upper_bound(PreprocessedEntities.begin(),
00293                                PreprocessedEntities.end(),
00294                                BeginLoc,
00295                                PPEntityComp<&SourceRange::getBegin>(SourceMgr));
00296   pp_iter insertI = PreprocessedEntities.insert(I, Entity);
00297   return getPPEntityID(insertI - PreprocessedEntities.begin(),
00298                        /*isLoaded=*/false);
00299 }
00300 
00301 void PreprocessingRecord::SetExternalSource(
00302                                     ExternalPreprocessingRecordSource &Source) {
00303   assert(!ExternalSource &&
00304          "Preprocessing record already has an external source");
00305   ExternalSource = &Source;
00306 }
00307 
00308 unsigned PreprocessingRecord::allocateLoadedEntities(unsigned NumEntities) {
00309   unsigned Result = LoadedPreprocessedEntities.size();
00310   LoadedPreprocessedEntities.resize(LoadedPreprocessedEntities.size() 
00311                                     + NumEntities);
00312   return Result;
00313 }
00314 
00315 void PreprocessingRecord::RegisterMacroDefinition(MacroInfo *Macro,
00316                                                   PPEntityID PPID) {
00317   MacroDefinitions[Macro] = PPID;
00318 }
00319 
00320 /// \brief Retrieve the preprocessed entity at the given ID.
00321 PreprocessedEntity *PreprocessingRecord::getPreprocessedEntity(PPEntityID PPID){
00322   if (PPID < 0) {
00323     assert(unsigned(-PPID-1) < LoadedPreprocessedEntities.size() &&
00324            "Out-of bounds loaded preprocessed entity");
00325     return getLoadedPreprocessedEntity(LoadedPreprocessedEntities.size()+PPID);
00326   }
00327   assert(unsigned(PPID) < PreprocessedEntities.size() &&
00328          "Out-of bounds local preprocessed entity");
00329   return PreprocessedEntities[PPID];
00330 }
00331 
00332 /// \brief Retrieve the loaded preprocessed entity at the given index.
00333 PreprocessedEntity *
00334 PreprocessingRecord::getLoadedPreprocessedEntity(unsigned Index) {
00335   assert(Index < LoadedPreprocessedEntities.size() && 
00336          "Out-of bounds loaded preprocessed entity");
00337   assert(ExternalSource && "No external source to load from");
00338   PreprocessedEntity *&Entity = LoadedPreprocessedEntities[Index];
00339   if (!Entity) {
00340     Entity = ExternalSource->ReadPreprocessedEntity(Index);
00341     if (!Entity) // Failed to load.
00342       Entity = new (*this)
00343          PreprocessedEntity(PreprocessedEntity::InvalidKind, SourceRange());
00344   }
00345   return Entity;
00346 }
00347 
00348 MacroDefinition *PreprocessingRecord::findMacroDefinition(const MacroInfo *MI) {
00349   llvm::DenseMap<const MacroInfo *, PPEntityID>::iterator Pos
00350     = MacroDefinitions.find(MI);
00351   if (Pos == MacroDefinitions.end())
00352     return 0;
00353   
00354   PreprocessedEntity *Entity = getPreprocessedEntity(Pos->second);
00355   if (Entity->isInvalid())
00356     return 0;
00357   return cast<MacroDefinition>(Entity);
00358 }
00359 
00360 void PreprocessingRecord::MacroExpands(const Token &Id, const MacroInfo* MI,
00361                                        SourceRange Range) {
00362   // We don't record nested macro expansions.
00363   if (Id.getLocation().isMacroID())
00364     return;
00365 
00366   if (MI->isBuiltinMacro())
00367     addPreprocessedEntity(
00368                       new (*this) MacroExpansion(Id.getIdentifierInfo(),Range));
00369   else if (MacroDefinition *Def = findMacroDefinition(MI))
00370     addPreprocessedEntity(
00371                        new (*this) MacroExpansion(Def, Range));
00372 }
00373 
00374 void PreprocessingRecord::MacroDefined(const Token &Id,
00375                                        const MacroInfo *MI) {
00376   SourceRange R(MI->getDefinitionLoc(), MI->getDefinitionEndLoc());
00377   MacroDefinition *Def
00378       = new (*this) MacroDefinition(Id.getIdentifierInfo(), R);
00379   MacroDefinitions[MI] = addPreprocessedEntity(Def);
00380 }
00381 
00382 void PreprocessingRecord::MacroUndefined(const Token &Id,
00383                                          const MacroInfo *MI) {
00384   MacroDefinitions.erase(MI);
00385 }
00386 
00387 void PreprocessingRecord::InclusionDirective(
00388     SourceLocation HashLoc,
00389     const clang::Token &IncludeTok,
00390     StringRef FileName,
00391     bool IsAngled,
00392     const FileEntry *File,
00393     clang::SourceLocation EndLoc,
00394     StringRef SearchPath,
00395     StringRef RelativePath) {
00396   InclusionDirective::InclusionKind Kind = InclusionDirective::Include;
00397   
00398   switch (IncludeTok.getIdentifierInfo()->getPPKeywordID()) {
00399   case tok::pp_include: 
00400     Kind = InclusionDirective::Include; 
00401     break;
00402     
00403   case tok::pp_import: 
00404     Kind = InclusionDirective::Import; 
00405     break;
00406     
00407   case tok::pp_include_next: 
00408     Kind = InclusionDirective::IncludeNext; 
00409     break;
00410     
00411   case tok::pp___include_macros: 
00412     Kind = InclusionDirective::IncludeMacros;
00413     break;
00414     
00415   default:
00416     llvm_unreachable("Unknown include directive kind");
00417   }
00418   
00419   clang::InclusionDirective *ID
00420     = new (*this) clang::InclusionDirective(*this, Kind, FileName, !IsAngled, 
00421                                             File, SourceRange(HashLoc, EndLoc));
00422   addPreprocessedEntity(ID);
00423 }
00424 
00425 bool PreprocessingRecord::rangeIntersectsConditionalDirective(
00426                                                       SourceRange Range) const {
00427   if (Range.isInvalid())
00428     return false;
00429 
00430   CondDirectiveLocsTy::const_iterator
00431     low = std::lower_bound(CondDirectiveLocs.begin(), CondDirectiveLocs.end(),
00432                            Range.getBegin(), CondDirectiveLoc::Comp(SourceMgr));
00433   if (low == CondDirectiveLocs.end())
00434     return false;
00435 
00436   if (SourceMgr.isBeforeInTranslationUnit(Range.getEnd(), low->getLoc()))
00437     return false;
00438 
00439   CondDirectiveLocsTy::const_iterator
00440     upp = std::upper_bound(low, CondDirectiveLocs.end(),
00441                            Range.getEnd(), CondDirectiveLoc::Comp(SourceMgr));
00442   unsigned uppIdx;
00443   if (upp != CondDirectiveLocs.end())
00444     uppIdx = upp->getIdx();
00445   else
00446     uppIdx = 0;
00447 
00448   return low->getIdx() != uppIdx;
00449 }
00450 
00451 unsigned PreprocessingRecord::findCondDirectiveIdx(SourceLocation Loc) const {
00452   if (Loc.isInvalid())
00453     return 0;
00454 
00455   CondDirectiveLocsTy::const_iterator
00456     low = std::lower_bound(CondDirectiveLocs.begin(), CondDirectiveLocs.end(),
00457                            Loc, CondDirectiveLoc::Comp(SourceMgr));
00458   if (low == CondDirectiveLocs.end())
00459     return 0;
00460   return low->getIdx();
00461 }
00462 
00463 void PreprocessingRecord::addCondDirectiveLoc(CondDirectiveLoc DirLoc) {
00464   // Ignore directives in system headers.
00465   if (SourceMgr.isInSystemHeader(DirLoc.getLoc()))
00466     return;
00467 
00468   assert(CondDirectiveLocs.empty() ||
00469          SourceMgr.isBeforeInTranslationUnit(CondDirectiveLocs.back().getLoc(),
00470                                              DirLoc.getLoc()));
00471   CondDirectiveLocs.push_back(DirLoc);
00472 }
00473 
00474 void PreprocessingRecord::If(SourceLocation Loc, SourceRange ConditionRange) {
00475   if (RecordCondDirectives) {
00476     addCondDirectiveLoc(CondDirectiveLoc(Loc, CondDirectiveStack.back()));
00477     CondDirectiveStack.push_back(CondDirectiveNextIdx++);
00478   }
00479 }
00480 
00481 void PreprocessingRecord::Ifdef(SourceLocation Loc, const Token &MacroNameTok) {
00482   if (RecordCondDirectives) {
00483     addCondDirectiveLoc(CondDirectiveLoc(Loc, CondDirectiveStack.back()));
00484     CondDirectiveStack.push_back(CondDirectiveNextIdx++);
00485   }
00486 }
00487 
00488 void PreprocessingRecord::Ifndef(SourceLocation Loc,const Token &MacroNameTok) {
00489   if (RecordCondDirectives) {
00490     addCondDirectiveLoc(CondDirectiveLoc(Loc, CondDirectiveStack.back()));
00491     CondDirectiveStack.push_back(CondDirectiveNextIdx++);
00492   }
00493 }
00494 
00495 void PreprocessingRecord::Elif(SourceLocation Loc, SourceRange ConditionRange,
00496                                SourceLocation IfLoc) {
00497   if (RecordCondDirectives)
00498     addCondDirectiveLoc(CondDirectiveLoc(Loc, CondDirectiveStack.back()));
00499 }
00500 
00501 void PreprocessingRecord::Else(SourceLocation Loc, SourceLocation IfLoc) {
00502   if (RecordCondDirectives)
00503     addCondDirectiveLoc(CondDirectiveLoc(Loc, CondDirectiveStack.back()));
00504 }
00505 
00506 void PreprocessingRecord::Endif(SourceLocation Loc, SourceLocation IfLoc) {
00507   if (RecordCondDirectives) {
00508     addCondDirectiveLoc(CondDirectiveLoc(Loc, CondDirectiveStack.back()));
00509     assert(!CondDirectiveStack.empty());
00510     CondDirectiveStack.pop_back();
00511   }
00512 }
00513 
00514 size_t PreprocessingRecord::getTotalMemory() const {
00515   return BumpAlloc.getTotalMemory()
00516     + llvm::capacity_in_bytes(MacroDefinitions)
00517     + llvm::capacity_in_bytes(PreprocessedEntities)
00518     + llvm::capacity_in_bytes(LoadedPreprocessedEntities);
00519 }