PreprocessingRecord.cpp revision 243830
1//===--- PreprocessingRecord.cpp - Record of Preprocessing ------*- C++ -*-===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// This file implements the PreprocessingRecord class, which maintains a record 11// of what occurred during preprocessing, and its helpers. 12// 13//===----------------------------------------------------------------------===// 14#include "clang/Lex/PreprocessingRecord.h" 15#include "clang/Lex/MacroInfo.h" 16#include "clang/Lex/Token.h" 17#include "llvm/Support/ErrorHandling.h" 18#include "llvm/Support/Capacity.h" 19 20using namespace clang; 21 22ExternalPreprocessingRecordSource::~ExternalPreprocessingRecordSource() { } 23 24 25InclusionDirective::InclusionDirective(PreprocessingRecord &PPRec, 26 InclusionKind Kind, 27 StringRef FileName, 28 bool InQuotes, bool ImportedModule, 29 const FileEntry *File, 30 SourceRange Range) 31 : PreprocessingDirective(InclusionDirectiveKind, Range), 32 InQuotes(InQuotes), Kind(Kind), ImportedModule(ImportedModule), File(File) 33{ 34 char *Memory 35 = (char*)PPRec.Allocate(FileName.size() + 1, llvm::alignOf<char>()); 36 memcpy(Memory, FileName.data(), FileName.size()); 37 Memory[FileName.size()] = 0; 38 this->FileName = StringRef(Memory, FileName.size()); 39} 40 41PreprocessingRecord::PreprocessingRecord(SourceManager &SM, 42 bool RecordConditionalDirectives) 43 : SourceMgr(SM), 44 RecordCondDirectives(RecordConditionalDirectives), CondDirectiveNextIdx(0), 45 ExternalSource(0) 46{ 47 if (RecordCondDirectives) 48 CondDirectiveStack.push_back(CondDirectiveNextIdx++); 49} 50 51/// \brief Returns a pair of [Begin, End) iterators of preprocessed entities 52/// that source range \p Range encompasses. 53std::pair<PreprocessingRecord::iterator, PreprocessingRecord::iterator> 54PreprocessingRecord::getPreprocessedEntitiesInRange(SourceRange Range) { 55 if (Range.isInvalid()) 56 return std::make_pair(iterator(), iterator()); 57 58 if (CachedRangeQuery.Range == Range) { 59 return std::make_pair(iterator(this, CachedRangeQuery.Result.first), 60 iterator(this, CachedRangeQuery.Result.second)); 61 } 62 63 std::pair<int, int> Res = getPreprocessedEntitiesInRangeSlow(Range); 64 65 CachedRangeQuery.Range = Range; 66 CachedRangeQuery.Result = Res; 67 68 return std::make_pair(iterator(this, Res.first), iterator(this, Res.second)); 69} 70 71static bool isPreprocessedEntityIfInFileID(PreprocessedEntity *PPE, FileID FID, 72 SourceManager &SM) { 73 assert(!FID.isInvalid()); 74 if (!PPE) 75 return false; 76 77 SourceLocation Loc = PPE->getSourceRange().getBegin(); 78 if (Loc.isInvalid()) 79 return false; 80 81 if (SM.isInFileID(SM.getFileLoc(Loc), FID)) 82 return true; 83 else 84 return false; 85} 86 87/// \brief Returns true if the preprocessed entity that \arg PPEI iterator 88/// points to is coming from the file \arg FID. 89/// 90/// Can be used to avoid implicit deserializations of preallocated 91/// preprocessed entities if we only care about entities of a specific file 92/// and not from files \#included in the range given at 93/// \see getPreprocessedEntitiesInRange. 94bool PreprocessingRecord::isEntityInFileID(iterator PPEI, FileID FID) { 95 if (FID.isInvalid()) 96 return false; 97 98 int Pos = PPEI.Position; 99 if (Pos < 0) { 100 assert(unsigned(-Pos-1) < LoadedPreprocessedEntities.size() && 101 "Out-of bounds loaded preprocessed entity"); 102 assert(ExternalSource && "No external source to load from"); 103 unsigned LoadedIndex = LoadedPreprocessedEntities.size()+Pos; 104 if (PreprocessedEntity *PPE = LoadedPreprocessedEntities[LoadedIndex]) 105 return isPreprocessedEntityIfInFileID(PPE, FID, SourceMgr); 106 107 // See if the external source can see if the entity is in the file without 108 // deserializing it. 109 llvm::Optional<bool> 110 IsInFile = ExternalSource->isPreprocessedEntityInFileID(LoadedIndex, FID); 111 if (IsInFile.hasValue()) 112 return IsInFile.getValue(); 113 114 // The external source did not provide a definite answer, go and deserialize 115 // the entity to check it. 116 return isPreprocessedEntityIfInFileID( 117 getLoadedPreprocessedEntity(LoadedIndex), 118 FID, SourceMgr); 119 } 120 121 assert(unsigned(Pos) < PreprocessedEntities.size() && 122 "Out-of bounds local preprocessed entity"); 123 return isPreprocessedEntityIfInFileID(PreprocessedEntities[Pos], 124 FID, SourceMgr); 125} 126 127/// \brief Returns a pair of [Begin, End) iterators of preprocessed entities 128/// that source range \arg R encompasses. 129std::pair<int, int> 130PreprocessingRecord::getPreprocessedEntitiesInRangeSlow(SourceRange Range) { 131 assert(Range.isValid()); 132 assert(!SourceMgr.isBeforeInTranslationUnit(Range.getEnd(),Range.getBegin())); 133 134 std::pair<unsigned, unsigned> 135 Local = findLocalPreprocessedEntitiesInRange(Range); 136 137 // Check if range spans local entities. 138 if (!ExternalSource || SourceMgr.isLocalSourceLocation(Range.getBegin())) 139 return std::make_pair(Local.first, Local.second); 140 141 std::pair<unsigned, unsigned> 142 Loaded = ExternalSource->findPreprocessedEntitiesInRange(Range); 143 144 // Check if range spans local entities. 145 if (Loaded.first == Loaded.second) 146 return std::make_pair(Local.first, Local.second); 147 148 unsigned TotalLoaded = LoadedPreprocessedEntities.size(); 149 150 // Check if range spans loaded entities. 151 if (Local.first == Local.second) 152 return std::make_pair(int(Loaded.first)-TotalLoaded, 153 int(Loaded.second)-TotalLoaded); 154 155 // Range spands loaded and local entities. 156 return std::make_pair(int(Loaded.first)-TotalLoaded, Local.second); 157} 158 159std::pair<unsigned, unsigned> 160PreprocessingRecord::findLocalPreprocessedEntitiesInRange( 161 SourceRange Range) const { 162 if (Range.isInvalid()) 163 return std::make_pair(0,0); 164 assert(!SourceMgr.isBeforeInTranslationUnit(Range.getEnd(),Range.getBegin())); 165 166 unsigned Begin = findBeginLocalPreprocessedEntity(Range.getBegin()); 167 unsigned End = findEndLocalPreprocessedEntity(Range.getEnd()); 168 return std::make_pair(Begin, End); 169} 170 171namespace { 172 173template <SourceLocation (SourceRange::*getRangeLoc)() const> 174struct PPEntityComp { 175 const SourceManager &SM; 176 177 explicit PPEntityComp(const SourceManager &SM) : SM(SM) { } 178 179 bool operator()(PreprocessedEntity *L, PreprocessedEntity *R) const { 180 SourceLocation LHS = getLoc(L); 181 SourceLocation RHS = getLoc(R); 182 return SM.isBeforeInTranslationUnit(LHS, RHS); 183 } 184 185 bool operator()(PreprocessedEntity *L, SourceLocation RHS) const { 186 SourceLocation LHS = getLoc(L); 187 return SM.isBeforeInTranslationUnit(LHS, RHS); 188 } 189 190 bool operator()(SourceLocation LHS, PreprocessedEntity *R) const { 191 SourceLocation RHS = getLoc(R); 192 return SM.isBeforeInTranslationUnit(LHS, RHS); 193 } 194 195 SourceLocation getLoc(PreprocessedEntity *PPE) const { 196 SourceRange Range = PPE->getSourceRange(); 197 return (Range.*getRangeLoc)(); 198 } 199}; 200 201} 202 203unsigned PreprocessingRecord::findBeginLocalPreprocessedEntity( 204 SourceLocation Loc) const { 205 if (SourceMgr.isLoadedSourceLocation(Loc)) 206 return 0; 207 208 size_t Count = PreprocessedEntities.size(); 209 size_t Half; 210 std::vector<PreprocessedEntity *>::const_iterator 211 First = PreprocessedEntities.begin(); 212 std::vector<PreprocessedEntity *>::const_iterator I; 213 214 // Do a binary search manually instead of using std::lower_bound because 215 // The end locations of entities may be unordered (when a macro expansion 216 // is inside another macro argument), but for this case it is not important 217 // whether we get the first macro expansion or its containing macro. 218 while (Count > 0) { 219 Half = Count/2; 220 I = First; 221 std::advance(I, Half); 222 if (SourceMgr.isBeforeInTranslationUnit((*I)->getSourceRange().getEnd(), 223 Loc)){ 224 First = I; 225 ++First; 226 Count = Count - Half - 1; 227 } else 228 Count = Half; 229 } 230 231 return First - PreprocessedEntities.begin(); 232} 233 234unsigned PreprocessingRecord::findEndLocalPreprocessedEntity( 235 SourceLocation Loc) const { 236 if (SourceMgr.isLoadedSourceLocation(Loc)) 237 return 0; 238 239 std::vector<PreprocessedEntity *>::const_iterator 240 I = std::upper_bound(PreprocessedEntities.begin(), 241 PreprocessedEntities.end(), 242 Loc, 243 PPEntityComp<&SourceRange::getBegin>(SourceMgr)); 244 return I - PreprocessedEntities.begin(); 245} 246 247PreprocessingRecord::PPEntityID 248PreprocessingRecord::addPreprocessedEntity(PreprocessedEntity *Entity) { 249 assert(Entity); 250 SourceLocation BeginLoc = Entity->getSourceRange().getBegin(); 251 252 if (!isa<class InclusionDirective>(Entity)) { 253 assert((PreprocessedEntities.empty() || 254 !SourceMgr.isBeforeInTranslationUnit(BeginLoc, 255 PreprocessedEntities.back()->getSourceRange().getBegin())) && 256 "a macro directive was encountered out-of-order"); 257 PreprocessedEntities.push_back(Entity); 258 return getPPEntityID(PreprocessedEntities.size()-1, /*isLoaded=*/false); 259 } 260 261 // Check normal case, this entity begin location is after the previous one. 262 if (PreprocessedEntities.empty() || 263 !SourceMgr.isBeforeInTranslationUnit(BeginLoc, 264 PreprocessedEntities.back()->getSourceRange().getBegin())) { 265 PreprocessedEntities.push_back(Entity); 266 return getPPEntityID(PreprocessedEntities.size()-1, /*isLoaded=*/false); 267 } 268 269 // The entity's location is not after the previous one; this can happen with 270 // include directives that form the filename using macros, e.g: 271 // "#include MACRO(STUFF)". 272 273 typedef std::vector<PreprocessedEntity *>::iterator pp_iter; 274 275 // Usually there are few macro expansions when defining the filename, do a 276 // linear search for a few entities. 277 unsigned count = 0; 278 for (pp_iter RI = PreprocessedEntities.end(), 279 Begin = PreprocessedEntities.begin(); 280 RI != Begin && count < 4; --RI, ++count) { 281 pp_iter I = RI; 282 --I; 283 if (!SourceMgr.isBeforeInTranslationUnit(BeginLoc, 284 (*I)->getSourceRange().getBegin())) { 285 pp_iter insertI = PreprocessedEntities.insert(RI, Entity); 286 return getPPEntityID(insertI - PreprocessedEntities.begin(), 287 /*isLoaded=*/false); 288 } 289 } 290 291 // Linear search unsuccessful. Do a binary search. 292 pp_iter I = std::upper_bound(PreprocessedEntities.begin(), 293 PreprocessedEntities.end(), 294 BeginLoc, 295 PPEntityComp<&SourceRange::getBegin>(SourceMgr)); 296 pp_iter insertI = PreprocessedEntities.insert(I, Entity); 297 return getPPEntityID(insertI - PreprocessedEntities.begin(), 298 /*isLoaded=*/false); 299} 300 301void PreprocessingRecord::SetExternalSource( 302 ExternalPreprocessingRecordSource &Source) { 303 assert(!ExternalSource && 304 "Preprocessing record already has an external source"); 305 ExternalSource = &Source; 306} 307 308unsigned PreprocessingRecord::allocateLoadedEntities(unsigned NumEntities) { 309 unsigned Result = LoadedPreprocessedEntities.size(); 310 LoadedPreprocessedEntities.resize(LoadedPreprocessedEntities.size() 311 + NumEntities); 312 return Result; 313} 314 315void PreprocessingRecord::RegisterMacroDefinition(MacroInfo *Macro, 316 PPEntityID PPID) { 317 MacroDefinitions[Macro] = PPID; 318} 319 320/// \brief Retrieve the preprocessed entity at the given ID. 321PreprocessedEntity *PreprocessingRecord::getPreprocessedEntity(PPEntityID PPID){ 322 if (PPID.ID < 0) { 323 unsigned Index = -PPID.ID - 1; 324 assert(Index < LoadedPreprocessedEntities.size() && 325 "Out-of bounds loaded preprocessed entity"); 326 return getLoadedPreprocessedEntity(Index); 327 } 328 329 if (PPID.ID == 0) 330 return 0; 331 unsigned Index = PPID.ID - 1; 332 assert(Index < PreprocessedEntities.size() && 333 "Out-of bounds local preprocessed entity"); 334 return PreprocessedEntities[Index]; 335} 336 337/// \brief Retrieve the loaded preprocessed entity at the given index. 338PreprocessedEntity * 339PreprocessingRecord::getLoadedPreprocessedEntity(unsigned Index) { 340 assert(Index < LoadedPreprocessedEntities.size() && 341 "Out-of bounds loaded preprocessed entity"); 342 assert(ExternalSource && "No external source to load from"); 343 PreprocessedEntity *&Entity = LoadedPreprocessedEntities[Index]; 344 if (!Entity) { 345 Entity = ExternalSource->ReadPreprocessedEntity(Index); 346 if (!Entity) // Failed to load. 347 Entity = new (*this) 348 PreprocessedEntity(PreprocessedEntity::InvalidKind, SourceRange()); 349 } 350 return Entity; 351} 352 353MacroDefinition *PreprocessingRecord::findMacroDefinition(const MacroInfo *MI) { 354 llvm::DenseMap<const MacroInfo *, PPEntityID>::iterator Pos 355 = MacroDefinitions.find(MI); 356 if (Pos == MacroDefinitions.end()) 357 return 0; 358 359 PreprocessedEntity *Entity = getPreprocessedEntity(Pos->second); 360 if (Entity->isInvalid()) 361 return 0; 362 return cast<MacroDefinition>(Entity); 363} 364 365void PreprocessingRecord::MacroExpands(const Token &Id, const MacroInfo* MI, 366 SourceRange Range) { 367 // We don't record nested macro expansions. 368 if (Id.getLocation().isMacroID()) 369 return; 370 371 if (MI->isBuiltinMacro()) 372 addPreprocessedEntity( 373 new (*this) MacroExpansion(Id.getIdentifierInfo(),Range)); 374 else if (MacroDefinition *Def = findMacroDefinition(MI)) 375 addPreprocessedEntity( 376 new (*this) MacroExpansion(Def, Range)); 377} 378 379void PreprocessingRecord::MacroDefined(const Token &Id, 380 const MacroInfo *MI) { 381 SourceRange R(MI->getDefinitionLoc(), MI->getDefinitionEndLoc()); 382 MacroDefinition *Def 383 = new (*this) MacroDefinition(Id.getIdentifierInfo(), R); 384 MacroDefinitions[MI] = addPreprocessedEntity(Def); 385} 386 387void PreprocessingRecord::MacroUndefined(const Token &Id, 388 const MacroInfo *MI) { 389 MacroDefinitions.erase(MI); 390} 391 392void PreprocessingRecord::InclusionDirective( 393 SourceLocation HashLoc, 394 const clang::Token &IncludeTok, 395 StringRef FileName, 396 bool IsAngled, 397 CharSourceRange FilenameRange, 398 const FileEntry *File, 399 StringRef SearchPath, 400 StringRef RelativePath, 401 const Module *Imported) { 402 InclusionDirective::InclusionKind Kind = InclusionDirective::Include; 403 404 switch (IncludeTok.getIdentifierInfo()->getPPKeywordID()) { 405 case tok::pp_include: 406 Kind = InclusionDirective::Include; 407 break; 408 409 case tok::pp_import: 410 Kind = InclusionDirective::Import; 411 break; 412 413 case tok::pp_include_next: 414 Kind = InclusionDirective::IncludeNext; 415 break; 416 417 case tok::pp___include_macros: 418 Kind = InclusionDirective::IncludeMacros; 419 break; 420 421 default: 422 llvm_unreachable("Unknown include directive kind"); 423 } 424 425 SourceLocation EndLoc; 426 if (!IsAngled) { 427 EndLoc = FilenameRange.getBegin(); 428 } else { 429 EndLoc = FilenameRange.getEnd(); 430 if (FilenameRange.isCharRange()) 431 EndLoc = EndLoc.getLocWithOffset(-1); // the InclusionDirective expects 432 // a token range. 433 } 434 clang::InclusionDirective *ID 435 = new (*this) clang::InclusionDirective(*this, Kind, FileName, !IsAngled, 436 (bool)Imported, 437 File, SourceRange(HashLoc, EndLoc)); 438 addPreprocessedEntity(ID); 439} 440 441bool PreprocessingRecord::rangeIntersectsConditionalDirective( 442 SourceRange Range) const { 443 if (Range.isInvalid()) 444 return false; 445 446 CondDirectiveLocsTy::const_iterator 447 low = std::lower_bound(CondDirectiveLocs.begin(), CondDirectiveLocs.end(), 448 Range.getBegin(), CondDirectiveLoc::Comp(SourceMgr)); 449 if (low == CondDirectiveLocs.end()) 450 return false; 451 452 if (SourceMgr.isBeforeInTranslationUnit(Range.getEnd(), low->getLoc())) 453 return false; 454 455 CondDirectiveLocsTy::const_iterator 456 upp = std::upper_bound(low, CondDirectiveLocs.end(), 457 Range.getEnd(), CondDirectiveLoc::Comp(SourceMgr)); 458 unsigned uppIdx; 459 if (upp != CondDirectiveLocs.end()) 460 uppIdx = upp->getIdx(); 461 else 462 uppIdx = 0; 463 464 return low->getIdx() != uppIdx; 465} 466 467unsigned PreprocessingRecord::findCondDirectiveIdx(SourceLocation Loc) const { 468 if (Loc.isInvalid()) 469 return 0; 470 471 CondDirectiveLocsTy::const_iterator 472 low = std::lower_bound(CondDirectiveLocs.begin(), CondDirectiveLocs.end(), 473 Loc, CondDirectiveLoc::Comp(SourceMgr)); 474 if (low == CondDirectiveLocs.end()) 475 return 0; 476 return low->getIdx(); 477} 478 479void PreprocessingRecord::addCondDirectiveLoc(CondDirectiveLoc DirLoc) { 480 // Ignore directives in system headers. 481 if (SourceMgr.isInSystemHeader(DirLoc.getLoc())) 482 return; 483 484 assert(CondDirectiveLocs.empty() || 485 SourceMgr.isBeforeInTranslationUnit(CondDirectiveLocs.back().getLoc(), 486 DirLoc.getLoc())); 487 CondDirectiveLocs.push_back(DirLoc); 488} 489 490void PreprocessingRecord::If(SourceLocation Loc, SourceRange ConditionRange) { 491 if (RecordCondDirectives) { 492 addCondDirectiveLoc(CondDirectiveLoc(Loc, CondDirectiveStack.back())); 493 CondDirectiveStack.push_back(CondDirectiveNextIdx++); 494 } 495} 496 497void PreprocessingRecord::Ifdef(SourceLocation Loc, const Token &MacroNameTok) { 498 if (RecordCondDirectives) { 499 addCondDirectiveLoc(CondDirectiveLoc(Loc, CondDirectiveStack.back())); 500 CondDirectiveStack.push_back(CondDirectiveNextIdx++); 501 } 502} 503 504void PreprocessingRecord::Ifndef(SourceLocation Loc,const Token &MacroNameTok) { 505 if (RecordCondDirectives) { 506 addCondDirectiveLoc(CondDirectiveLoc(Loc, CondDirectiveStack.back())); 507 CondDirectiveStack.push_back(CondDirectiveNextIdx++); 508 } 509} 510 511void PreprocessingRecord::Elif(SourceLocation Loc, SourceRange ConditionRange, 512 SourceLocation IfLoc) { 513 if (RecordCondDirectives) 514 addCondDirectiveLoc(CondDirectiveLoc(Loc, CondDirectiveStack.back())); 515} 516 517void PreprocessingRecord::Else(SourceLocation Loc, SourceLocation IfLoc) { 518 if (RecordCondDirectives) 519 addCondDirectiveLoc(CondDirectiveLoc(Loc, CondDirectiveStack.back())); 520} 521 522void PreprocessingRecord::Endif(SourceLocation Loc, SourceLocation IfLoc) { 523 if (RecordCondDirectives) { 524 addCondDirectiveLoc(CondDirectiveLoc(Loc, CondDirectiveStack.back())); 525 assert(!CondDirectiveStack.empty()); 526 CondDirectiveStack.pop_back(); 527 } 528} 529 530size_t PreprocessingRecord::getTotalMemory() const { 531 return BumpAlloc.getTotalMemory() 532 + llvm::capacity_in_bytes(MacroDefinitions) 533 + llvm::capacity_in_bytes(PreprocessedEntities) 534 + llvm::capacity_in_bytes(LoadedPreprocessedEntities); 535} 536