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/Capacity.h" 18 #include "llvm/Support/ErrorHandling.h" 19 20 using namespace clang; 21 22 ExternalPreprocessingRecordSource::~ExternalPreprocessingRecordSource() { } 23 24 25 InclusionDirective::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 41 PreprocessingRecord::PreprocessingRecord(SourceManager &SM) 42 : SourceMgr(SM), 43 ExternalSource(nullptr) { 44 } 45 46 /// \brief Returns a pair of [Begin, End) iterators of preprocessed entities 47 /// that source range \p Range encompasses. 48 llvm::iterator_range<PreprocessingRecord::iterator> 49 PreprocessingRecord::getPreprocessedEntitiesInRange(SourceRange Range) { 50 if (Range.isInvalid()) 51 return llvm::make_range(iterator(), iterator()); 52 53 if (CachedRangeQuery.Range == Range) { 54 return llvm::make_range(iterator(this, CachedRangeQuery.Result.first), 55 iterator(this, CachedRangeQuery.Result.second)); 56 } 57 58 std::pair<int, int> Res = getPreprocessedEntitiesInRangeSlow(Range); 59 60 CachedRangeQuery.Range = Range; 61 CachedRangeQuery.Result = Res; 62 63 return llvm::make_range(iterator(this, Res.first), 64 iterator(this, Res.second)); 65 } 66 67 static bool isPreprocessedEntityIfInFileID(PreprocessedEntity *PPE, FileID FID, 68 SourceManager &SM) { 69 assert(!FID.isInvalid()); 70 if (!PPE) 71 return false; 72 73 SourceLocation Loc = PPE->getSourceRange().getBegin(); 74 if (Loc.isInvalid()) 75 return false; 76 77 if (SM.isInFileID(SM.getFileLoc(Loc), FID)) 78 return true; 79 else 80 return false; 81 } 82 83 /// \brief Returns true if the preprocessed entity that \arg PPEI iterator 84 /// points to is coming from the file \arg FID. 85 /// 86 /// Can be used to avoid implicit deserializations of preallocated 87 /// preprocessed entities if we only care about entities of a specific file 88 /// and not from files \#included in the range given at 89 /// \see getPreprocessedEntitiesInRange. 90 bool PreprocessingRecord::isEntityInFileID(iterator PPEI, FileID FID) { 91 if (FID.isInvalid()) 92 return false; 93 94 int Pos = PPEI.Position; 95 if (Pos < 0) { 96 if (unsigned(-Pos-1) >= LoadedPreprocessedEntities.size()) { 97 assert(0 && "Out-of bounds loaded preprocessed entity"); 98 return false; 99 } 100 assert(ExternalSource && "No external source to load from"); 101 unsigned LoadedIndex = LoadedPreprocessedEntities.size()+Pos; 102 if (PreprocessedEntity *PPE = LoadedPreprocessedEntities[LoadedIndex]) 103 return isPreprocessedEntityIfInFileID(PPE, FID, SourceMgr); 104 105 // See if the external source can see if the entity is in the file without 106 // deserializing it. 107 Optional<bool> IsInFile = 108 ExternalSource->isPreprocessedEntityInFileID(LoadedIndex, FID); 109 if (IsInFile.hasValue()) 110 return IsInFile.getValue(); 111 112 // The external source did not provide a definite answer, go and deserialize 113 // the entity to check it. 114 return isPreprocessedEntityIfInFileID( 115 getLoadedPreprocessedEntity(LoadedIndex), 116 FID, SourceMgr); 117 } 118 119 if (unsigned(Pos) >= PreprocessedEntities.size()) { 120 assert(0 && "Out-of bounds local preprocessed entity"); 121 return false; 122 } 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. 129 std::pair<int, int> 130 PreprocessingRecord::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 159 std::pair<unsigned, unsigned> 160 PreprocessingRecord::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 171 namespace { 172 173 template <SourceLocation (SourceRange::*getRangeLoc)() const> 174 struct 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 203 unsigned 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 234 unsigned 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 247 PreprocessingRecord::PPEntityID 248 PreprocessingRecord::addPreprocessedEntity(PreprocessedEntity *Entity) { 249 assert(Entity); 250 SourceLocation BeginLoc = Entity->getSourceRange().getBegin(); 251 252 if (isa<MacroDefinition>(Entity)) { 253 assert((PreprocessedEntities.empty() || 254 !SourceMgr.isBeforeInTranslationUnit(BeginLoc, 255 PreprocessedEntities.back()->getSourceRange().getBegin())) && 256 "a macro definition 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 // or with macro expansions inside macro arguments where the arguments are 273 // not expanded in the same order as listed, e.g: 274 // \code 275 // #define M1 1 276 // #define M2 2 277 // #define FM(x,y) y x 278 // FM(M1, M2) 279 // \endcode 280 281 typedef std::vector<PreprocessedEntity *>::iterator pp_iter; 282 283 // Usually there are few macro expansions when defining the filename, do a 284 // linear search for a few entities. 285 unsigned count = 0; 286 for (pp_iter RI = PreprocessedEntities.end(), 287 Begin = PreprocessedEntities.begin(); 288 RI != Begin && count < 4; --RI, ++count) { 289 pp_iter I = RI; 290 --I; 291 if (!SourceMgr.isBeforeInTranslationUnit(BeginLoc, 292 (*I)->getSourceRange().getBegin())) { 293 pp_iter insertI = PreprocessedEntities.insert(RI, Entity); 294 return getPPEntityID(insertI - PreprocessedEntities.begin(), 295 /*isLoaded=*/false); 296 } 297 } 298 299 // Linear search unsuccessful. Do a binary search. 300 pp_iter I = std::upper_bound(PreprocessedEntities.begin(), 301 PreprocessedEntities.end(), 302 BeginLoc, 303 PPEntityComp<&SourceRange::getBegin>(SourceMgr)); 304 pp_iter insertI = PreprocessedEntities.insert(I, Entity); 305 return getPPEntityID(insertI - PreprocessedEntities.begin(), 306 /*isLoaded=*/false); 307 } 308 309 void PreprocessingRecord::SetExternalSource( 310 ExternalPreprocessingRecordSource &Source) { 311 assert(!ExternalSource && 312 "Preprocessing record already has an external source"); 313 ExternalSource = &Source; 314 } 315 316 unsigned PreprocessingRecord::allocateLoadedEntities(unsigned NumEntities) { 317 unsigned Result = LoadedPreprocessedEntities.size(); 318 LoadedPreprocessedEntities.resize(LoadedPreprocessedEntities.size() 319 + NumEntities); 320 return Result; 321 } 322 323 void PreprocessingRecord::RegisterMacroDefinition(MacroInfo *Macro, 324 MacroDefinition *Def) { 325 MacroDefinitions[Macro] = Def; 326 } 327 328 /// \brief Retrieve the preprocessed entity at the given ID. 329 PreprocessedEntity *PreprocessingRecord::getPreprocessedEntity(PPEntityID PPID){ 330 if (PPID.ID < 0) { 331 unsigned Index = -PPID.ID - 1; 332 assert(Index < LoadedPreprocessedEntities.size() && 333 "Out-of bounds loaded preprocessed entity"); 334 return getLoadedPreprocessedEntity(Index); 335 } 336 337 if (PPID.ID == 0) 338 return nullptr; 339 unsigned Index = PPID.ID - 1; 340 assert(Index < PreprocessedEntities.size() && 341 "Out-of bounds local preprocessed entity"); 342 return PreprocessedEntities[Index]; 343 } 344 345 /// \brief Retrieve the loaded preprocessed entity at the given index. 346 PreprocessedEntity * 347 PreprocessingRecord::getLoadedPreprocessedEntity(unsigned Index) { 348 assert(Index < LoadedPreprocessedEntities.size() && 349 "Out-of bounds loaded preprocessed entity"); 350 assert(ExternalSource && "No external source to load from"); 351 PreprocessedEntity *&Entity = LoadedPreprocessedEntities[Index]; 352 if (!Entity) { 353 Entity = ExternalSource->ReadPreprocessedEntity(Index); 354 if (!Entity) // Failed to load. 355 Entity = new (*this) 356 PreprocessedEntity(PreprocessedEntity::InvalidKind, SourceRange()); 357 } 358 return Entity; 359 } 360 361 MacroDefinition *PreprocessingRecord::findMacroDefinition(const MacroInfo *MI) { 362 llvm::DenseMap<const MacroInfo *, MacroDefinition *>::iterator Pos 363 = MacroDefinitions.find(MI); 364 if (Pos == MacroDefinitions.end()) 365 return nullptr; 366 367 return Pos->second; 368 } 369 370 void PreprocessingRecord::addMacroExpansion(const Token &Id, 371 const MacroInfo *MI, 372 SourceRange Range) { 373 // We don't record nested macro expansions. 374 if (Id.getLocation().isMacroID()) 375 return; 376 377 if (MI->isBuiltinMacro()) 378 addPreprocessedEntity( 379 new (*this) MacroExpansion(Id.getIdentifierInfo(),Range)); 380 else if (MacroDefinition *Def = findMacroDefinition(MI)) 381 addPreprocessedEntity( 382 new (*this) MacroExpansion(Def, Range)); 383 } 384 385 void PreprocessingRecord::Ifdef(SourceLocation Loc, const Token &MacroNameTok, 386 const MacroDirective *MD) { 387 // This is not actually a macro expansion but record it as a macro reference. 388 if (MD) 389 addMacroExpansion(MacroNameTok, MD->getMacroInfo(), 390 MacroNameTok.getLocation()); 391 } 392 393 void PreprocessingRecord::Ifndef(SourceLocation Loc, const Token &MacroNameTok, 394 const MacroDirective *MD) { 395 // This is not actually a macro expansion but record it as a macro reference. 396 if (MD) 397 addMacroExpansion(MacroNameTok, MD->getMacroInfo(), 398 MacroNameTok.getLocation()); 399 } 400 401 void PreprocessingRecord::Defined(const Token &MacroNameTok, 402 const MacroDirective *MD, 403 SourceRange Range) { 404 // This is not actually a macro expansion but record it as a macro reference. 405 if (MD) 406 addMacroExpansion(MacroNameTok, MD->getMacroInfo(), 407 MacroNameTok.getLocation()); 408 } 409 410 void PreprocessingRecord::SourceRangeSkipped(SourceRange Range) { 411 SkippedRanges.push_back(Range); 412 } 413 414 void PreprocessingRecord::MacroExpands(const Token &Id,const MacroDirective *MD, 415 SourceRange Range, 416 const MacroArgs *Args) { 417 addMacroExpansion(Id, MD->getMacroInfo(), Range); 418 } 419 420 void PreprocessingRecord::MacroDefined(const Token &Id, 421 const MacroDirective *MD) { 422 const MacroInfo *MI = MD->getMacroInfo(); 423 SourceRange R(MI->getDefinitionLoc(), MI->getDefinitionEndLoc()); 424 MacroDefinition *Def 425 = new (*this) MacroDefinition(Id.getIdentifierInfo(), R); 426 addPreprocessedEntity(Def); 427 MacroDefinitions[MI] = Def; 428 } 429 430 void PreprocessingRecord::MacroUndefined(const Token &Id, 431 const MacroDirective *MD) { 432 // Note: MI may be null (when #undef'ining an undefined macro). 433 if (MD) 434 MacroDefinitions.erase(MD->getMacroInfo()); 435 } 436 437 void PreprocessingRecord::InclusionDirective( 438 SourceLocation HashLoc, 439 const clang::Token &IncludeTok, 440 StringRef FileName, 441 bool IsAngled, 442 CharSourceRange FilenameRange, 443 const FileEntry *File, 444 StringRef SearchPath, 445 StringRef RelativePath, 446 const Module *Imported) { 447 InclusionDirective::InclusionKind Kind = InclusionDirective::Include; 448 449 switch (IncludeTok.getIdentifierInfo()->getPPKeywordID()) { 450 case tok::pp_include: 451 Kind = InclusionDirective::Include; 452 break; 453 454 case tok::pp_import: 455 Kind = InclusionDirective::Import; 456 break; 457 458 case tok::pp_include_next: 459 Kind = InclusionDirective::IncludeNext; 460 break; 461 462 case tok::pp___include_macros: 463 Kind = InclusionDirective::IncludeMacros; 464 break; 465 466 default: 467 llvm_unreachable("Unknown include directive kind"); 468 } 469 470 SourceLocation EndLoc; 471 if (!IsAngled) { 472 EndLoc = FilenameRange.getBegin(); 473 } else { 474 EndLoc = FilenameRange.getEnd(); 475 if (FilenameRange.isCharRange()) 476 EndLoc = EndLoc.getLocWithOffset(-1); // the InclusionDirective expects 477 // a token range. 478 } 479 clang::InclusionDirective *ID 480 = new (*this) clang::InclusionDirective(*this, Kind, FileName, !IsAngled, 481 (bool)Imported, 482 File, SourceRange(HashLoc, EndLoc)); 483 addPreprocessedEntity(ID); 484 } 485 486 size_t PreprocessingRecord::getTotalMemory() const { 487 return BumpAlloc.getTotalMemory() 488 + llvm::capacity_in_bytes(MacroDefinitions) 489 + llvm::capacity_in_bytes(PreprocessedEntities) 490 + llvm::capacity_in_bytes(LoadedPreprocessedEntities); 491 } 492