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 std::pair<PreprocessingRecord::iterator, PreprocessingRecord::iterator> 49 PreprocessingRecord::getPreprocessedEntitiesInRange(SourceRange Range) { 50 if (Range.isInvalid()) 51 return std::make_pair(iterator(), iterator()); 52 53 if (CachedRangeQuery.Range == Range) { 54 return std::make_pair(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 std::make_pair(iterator(this, Res.first), iterator(this, Res.second)); 64 } 65 66 static bool isPreprocessedEntityIfInFileID(PreprocessedEntity *PPE, FileID FID, 67 SourceManager &SM) { 68 assert(!FID.isInvalid()); 69 if (!PPE) 70 return false; 71 72 SourceLocation Loc = PPE->getSourceRange().getBegin(); 73 if (Loc.isInvalid()) 74 return false; 75 76 if (SM.isInFileID(SM.getFileLoc(Loc), FID)) 77 return true; 78 else 79 return false; 80 } 81 82 /// \brief Returns true if the preprocessed entity that \arg PPEI iterator 83 /// points to is coming from the file \arg FID. 84 /// 85 /// Can be used to avoid implicit deserializations of preallocated 86 /// preprocessed entities if we only care about entities of a specific file 87 /// and not from files \#included in the range given at 88 /// \see getPreprocessedEntitiesInRange. 89 bool PreprocessingRecord::isEntityInFileID(iterator PPEI, FileID FID) { 90 if (FID.isInvalid()) 91 return false; 92 93 int Pos = PPEI.Position; 94 if (Pos < 0) { 95 if (unsigned(-Pos-1) >= LoadedPreprocessedEntities.size()) { 96 assert(0 && "Out-of bounds loaded preprocessed entity"); 97 return false; 98 } 99 assert(ExternalSource && "No external source to load from"); 100 unsigned LoadedIndex = LoadedPreprocessedEntities.size()+Pos; 101 if (PreprocessedEntity *PPE = LoadedPreprocessedEntities[LoadedIndex]) 102 return isPreprocessedEntityIfInFileID(PPE, FID, SourceMgr); 103 104 // See if the external source can see if the entity is in the file without 105 // deserializing it. 106 Optional<bool> IsInFile = 107 ExternalSource->isPreprocessedEntityInFileID(LoadedIndex, FID); 108 if (IsInFile.hasValue()) 109 return IsInFile.getValue(); 110 111 // The external source did not provide a definite answer, go and deserialize 112 // the entity to check it. 113 return isPreprocessedEntityIfInFileID( 114 getLoadedPreprocessedEntity(LoadedIndex), 115 FID, SourceMgr); 116 } 117 118 if (unsigned(Pos) >= PreprocessedEntities.size()) { 119 assert(0 && "Out-of bounds local preprocessed entity"); 120 return false; 121 } 122 return isPreprocessedEntityIfInFileID(PreprocessedEntities[Pos], 123 FID, SourceMgr); 124 } 125 126 /// \brief Returns a pair of [Begin, End) iterators of preprocessed entities 127 /// that source range \arg R encompasses. 128 std::pair<int, int> 129 PreprocessingRecord::getPreprocessedEntitiesInRangeSlow(SourceRange Range) { 130 assert(Range.isValid()); 131 assert(!SourceMgr.isBeforeInTranslationUnit(Range.getEnd(),Range.getBegin())); 132 133 std::pair<unsigned, unsigned> 134 Local = findLocalPreprocessedEntitiesInRange(Range); 135 136 // Check if range spans local entities. 137 if (!ExternalSource || SourceMgr.isLocalSourceLocation(Range.getBegin())) 138 return std::make_pair(Local.first, Local.second); 139 140 std::pair<unsigned, unsigned> 141 Loaded = ExternalSource->findPreprocessedEntitiesInRange(Range); 142 143 // Check if range spans local entities. 144 if (Loaded.first == Loaded.second) 145 return std::make_pair(Local.first, Local.second); 146 147 unsigned TotalLoaded = LoadedPreprocessedEntities.size(); 148 149 // Check if range spans loaded entities. 150 if (Local.first == Local.second) 151 return std::make_pair(int(Loaded.first)-TotalLoaded, 152 int(Loaded.second)-TotalLoaded); 153 154 // Range spands loaded and local entities. 155 return std::make_pair(int(Loaded.first)-TotalLoaded, Local.second); 156 } 157 158 std::pair<unsigned, unsigned> 159 PreprocessingRecord::findLocalPreprocessedEntitiesInRange( 160 SourceRange Range) const { 161 if (Range.isInvalid()) 162 return std::make_pair(0,0); 163 assert(!SourceMgr.isBeforeInTranslationUnit(Range.getEnd(),Range.getBegin())); 164 165 unsigned Begin = findBeginLocalPreprocessedEntity(Range.getBegin()); 166 unsigned End = findEndLocalPreprocessedEntity(Range.getEnd()); 167 return std::make_pair(Begin, End); 168 } 169 170 namespace { 171 172 template <SourceLocation (SourceRange::*getRangeLoc)() const> 173 struct PPEntityComp { 174 const SourceManager &SM; 175 176 explicit PPEntityComp(const SourceManager &SM) : SM(SM) { } 177 178 bool operator()(PreprocessedEntity *L, PreprocessedEntity *R) const { 179 SourceLocation LHS = getLoc(L); 180 SourceLocation RHS = getLoc(R); 181 return SM.isBeforeInTranslationUnit(LHS, RHS); 182 } 183 184 bool operator()(PreprocessedEntity *L, SourceLocation RHS) const { 185 SourceLocation LHS = getLoc(L); 186 return SM.isBeforeInTranslationUnit(LHS, RHS); 187 } 188 189 bool operator()(SourceLocation LHS, PreprocessedEntity *R) const { 190 SourceLocation RHS = getLoc(R); 191 return SM.isBeforeInTranslationUnit(LHS, RHS); 192 } 193 194 SourceLocation getLoc(PreprocessedEntity *PPE) const { 195 SourceRange Range = PPE->getSourceRange(); 196 return (Range.*getRangeLoc)(); 197 } 198 }; 199 200 } 201 202 unsigned PreprocessingRecord::findBeginLocalPreprocessedEntity( 203 SourceLocation Loc) const { 204 if (SourceMgr.isLoadedSourceLocation(Loc)) 205 return 0; 206 207 size_t Count = PreprocessedEntities.size(); 208 size_t Half; 209 std::vector<PreprocessedEntity *>::const_iterator 210 First = PreprocessedEntities.begin(); 211 std::vector<PreprocessedEntity *>::const_iterator I; 212 213 // Do a binary search manually instead of using std::lower_bound because 214 // The end locations of entities may be unordered (when a macro expansion 215 // is inside another macro argument), but for this case it is not important 216 // whether we get the first macro expansion or its containing macro. 217 while (Count > 0) { 218 Half = Count/2; 219 I = First; 220 std::advance(I, Half); 221 if (SourceMgr.isBeforeInTranslationUnit((*I)->getSourceRange().getEnd(), 222 Loc)){ 223 First = I; 224 ++First; 225 Count = Count - Half - 1; 226 } else 227 Count = Half; 228 } 229 230 return First - PreprocessedEntities.begin(); 231 } 232 233 unsigned PreprocessingRecord::findEndLocalPreprocessedEntity( 234 SourceLocation Loc) const { 235 if (SourceMgr.isLoadedSourceLocation(Loc)) 236 return 0; 237 238 std::vector<PreprocessedEntity *>::const_iterator 239 I = std::upper_bound(PreprocessedEntities.begin(), 240 PreprocessedEntities.end(), 241 Loc, 242 PPEntityComp<&SourceRange::getBegin>(SourceMgr)); 243 return I - PreprocessedEntities.begin(); 244 } 245 246 PreprocessingRecord::PPEntityID 247 PreprocessingRecord::addPreprocessedEntity(PreprocessedEntity *Entity) { 248 assert(Entity); 249 SourceLocation BeginLoc = Entity->getSourceRange().getBegin(); 250 251 if (isa<MacroDefinition>(Entity)) { 252 assert((PreprocessedEntities.empty() || 253 !SourceMgr.isBeforeInTranslationUnit(BeginLoc, 254 PreprocessedEntities.back()->getSourceRange().getBegin())) && 255 "a macro definition was encountered out-of-order"); 256 PreprocessedEntities.push_back(Entity); 257 return getPPEntityID(PreprocessedEntities.size()-1, /*isLoaded=*/false); 258 } 259 260 // Check normal case, this entity begin location is after the previous one. 261 if (PreprocessedEntities.empty() || 262 !SourceMgr.isBeforeInTranslationUnit(BeginLoc, 263 PreprocessedEntities.back()->getSourceRange().getBegin())) { 264 PreprocessedEntities.push_back(Entity); 265 return getPPEntityID(PreprocessedEntities.size()-1, /*isLoaded=*/false); 266 } 267 268 // The entity's location is not after the previous one; this can happen with 269 // include directives that form the filename using macros, e.g: 270 // "#include MACRO(STUFF)" 271 // or with macro expansions inside macro arguments where the arguments are 272 // not expanded in the same order as listed, e.g: 273 // \code 274 // #define M1 1 275 // #define M2 2 276 // #define FM(x,y) y x 277 // FM(M1, M2) 278 // \endcode 279 280 typedef std::vector<PreprocessedEntity *>::iterator pp_iter; 281 282 // Usually there are few macro expansions when defining the filename, do a 283 // linear search for a few entities. 284 unsigned count = 0; 285 for (pp_iter RI = PreprocessedEntities.end(), 286 Begin = PreprocessedEntities.begin(); 287 RI != Begin && count < 4; --RI, ++count) { 288 pp_iter I = RI; 289 --I; 290 if (!SourceMgr.isBeforeInTranslationUnit(BeginLoc, 291 (*I)->getSourceRange().getBegin())) { 292 pp_iter insertI = PreprocessedEntities.insert(RI, Entity); 293 return getPPEntityID(insertI - PreprocessedEntities.begin(), 294 /*isLoaded=*/false); 295 } 296 } 297 298 // Linear search unsuccessful. Do a binary search. 299 pp_iter I = std::upper_bound(PreprocessedEntities.begin(), 300 PreprocessedEntities.end(), 301 BeginLoc, 302 PPEntityComp<&SourceRange::getBegin>(SourceMgr)); 303 pp_iter insertI = PreprocessedEntities.insert(I, Entity); 304 return getPPEntityID(insertI - PreprocessedEntities.begin(), 305 /*isLoaded=*/false); 306 } 307 308 void PreprocessingRecord::SetExternalSource( 309 ExternalPreprocessingRecordSource &Source) { 310 assert(!ExternalSource && 311 "Preprocessing record already has an external source"); 312 ExternalSource = &Source; 313 } 314 315 unsigned PreprocessingRecord::allocateLoadedEntities(unsigned NumEntities) { 316 unsigned Result = LoadedPreprocessedEntities.size(); 317 LoadedPreprocessedEntities.resize(LoadedPreprocessedEntities.size() 318 + NumEntities); 319 return Result; 320 } 321 322 void PreprocessingRecord::RegisterMacroDefinition(MacroInfo *Macro, 323 MacroDefinition *Def) { 324 MacroDefinitions[Macro] = Def; 325 } 326 327 /// \brief Retrieve the preprocessed entity at the given ID. 328 PreprocessedEntity *PreprocessingRecord::getPreprocessedEntity(PPEntityID PPID){ 329 if (PPID.ID < 0) { 330 unsigned Index = -PPID.ID - 1; 331 assert(Index < LoadedPreprocessedEntities.size() && 332 "Out-of bounds loaded preprocessed entity"); 333 return getLoadedPreprocessedEntity(Index); 334 } 335 336 if (PPID.ID == 0) 337 return nullptr; 338 unsigned Index = PPID.ID - 1; 339 assert(Index < PreprocessedEntities.size() && 340 "Out-of bounds local preprocessed entity"); 341 return PreprocessedEntities[Index]; 342 } 343 344 /// \brief Retrieve the loaded preprocessed entity at the given index. 345 PreprocessedEntity * 346 PreprocessingRecord::getLoadedPreprocessedEntity(unsigned Index) { 347 assert(Index < LoadedPreprocessedEntities.size() && 348 "Out-of bounds loaded preprocessed entity"); 349 assert(ExternalSource && "No external source to load from"); 350 PreprocessedEntity *&Entity = LoadedPreprocessedEntities[Index]; 351 if (!Entity) { 352 Entity = ExternalSource->ReadPreprocessedEntity(Index); 353 if (!Entity) // Failed to load. 354 Entity = new (*this) 355 PreprocessedEntity(PreprocessedEntity::InvalidKind, SourceRange()); 356 } 357 return Entity; 358 } 359 360 MacroDefinition *PreprocessingRecord::findMacroDefinition(const MacroInfo *MI) { 361 llvm::DenseMap<const MacroInfo *, MacroDefinition *>::iterator Pos 362 = MacroDefinitions.find(MI); 363 if (Pos == MacroDefinitions.end()) 364 return nullptr; 365 366 return Pos->second; 367 } 368 369 void PreprocessingRecord::addMacroExpansion(const Token &Id, 370 const MacroInfo *MI, 371 SourceRange Range) { 372 // We don't record nested macro expansions. 373 if (Id.getLocation().isMacroID()) 374 return; 375 376 if (MI->isBuiltinMacro()) 377 addPreprocessedEntity( 378 new (*this) MacroExpansion(Id.getIdentifierInfo(),Range)); 379 else if (MacroDefinition *Def = findMacroDefinition(MI)) 380 addPreprocessedEntity( 381 new (*this) MacroExpansion(Def, Range)); 382 } 383 384 void PreprocessingRecord::Ifdef(SourceLocation Loc, const Token &MacroNameTok, 385 const MacroDirective *MD) { 386 // This is not actually a macro expansion but record it as a macro reference. 387 if (MD) 388 addMacroExpansion(MacroNameTok, MD->getMacroInfo(), 389 MacroNameTok.getLocation()); 390 } 391 392 void PreprocessingRecord::Ifndef(SourceLocation Loc, const Token &MacroNameTok, 393 const MacroDirective *MD) { 394 // This is not actually a macro expansion but record it as a macro reference. 395 if (MD) 396 addMacroExpansion(MacroNameTok, MD->getMacroInfo(), 397 MacroNameTok.getLocation()); 398 } 399 400 void PreprocessingRecord::Defined(const Token &MacroNameTok, 401 const MacroDirective *MD, 402 SourceRange Range) { 403 // This is not actually a macro expansion but record it as a macro reference. 404 if (MD) 405 addMacroExpansion(MacroNameTok, MD->getMacroInfo(), 406 MacroNameTok.getLocation()); 407 } 408 409 void PreprocessingRecord::SourceRangeSkipped(SourceRange Range) { 410 SkippedRanges.push_back(Range); 411 } 412 413 void PreprocessingRecord::MacroExpands(const Token &Id,const MacroDirective *MD, 414 SourceRange Range, 415 const MacroArgs *Args) { 416 addMacroExpansion(Id, MD->getMacroInfo(), Range); 417 } 418 419 void PreprocessingRecord::MacroDefined(const Token &Id, 420 const MacroDirective *MD) { 421 const MacroInfo *MI = MD->getMacroInfo(); 422 SourceRange R(MI->getDefinitionLoc(), MI->getDefinitionEndLoc()); 423 MacroDefinition *Def 424 = new (*this) MacroDefinition(Id.getIdentifierInfo(), R); 425 addPreprocessedEntity(Def); 426 MacroDefinitions[MI] = Def; 427 } 428 429 void PreprocessingRecord::MacroUndefined(const Token &Id, 430 const MacroDirective *MD) { 431 // Note: MI may be null (when #undef'ining an undefined macro). 432 if (MD) 433 MacroDefinitions.erase(MD->getMacroInfo()); 434 } 435 436 void PreprocessingRecord::InclusionDirective( 437 SourceLocation HashLoc, 438 const clang::Token &IncludeTok, 439 StringRef FileName, 440 bool IsAngled, 441 CharSourceRange FilenameRange, 442 const FileEntry *File, 443 StringRef SearchPath, 444 StringRef RelativePath, 445 const Module *Imported) { 446 InclusionDirective::InclusionKind Kind = InclusionDirective::Include; 447 448 switch (IncludeTok.getIdentifierInfo()->getPPKeywordID()) { 449 case tok::pp_include: 450 Kind = InclusionDirective::Include; 451 break; 452 453 case tok::pp_import: 454 Kind = InclusionDirective::Import; 455 break; 456 457 case tok::pp_include_next: 458 Kind = InclusionDirective::IncludeNext; 459 break; 460 461 case tok::pp___include_macros: 462 Kind = InclusionDirective::IncludeMacros; 463 break; 464 465 default: 466 llvm_unreachable("Unknown include directive kind"); 467 } 468 469 SourceLocation EndLoc; 470 if (!IsAngled) { 471 EndLoc = FilenameRange.getBegin(); 472 } else { 473 EndLoc = FilenameRange.getEnd(); 474 if (FilenameRange.isCharRange()) 475 EndLoc = EndLoc.getLocWithOffset(-1); // the InclusionDirective expects 476 // a token range. 477 } 478 clang::InclusionDirective *ID 479 = new (*this) clang::InclusionDirective(*this, Kind, FileName, !IsAngled, 480 (bool)Imported, 481 File, SourceRange(HashLoc, EndLoc)); 482 addPreprocessedEntity(ID); 483 } 484 485 size_t PreprocessingRecord::getTotalMemory() const { 486 return BumpAlloc.getTotalMemory() 487 + llvm::capacity_in_bytes(MacroDefinitions) 488 + llvm::capacity_in_bytes(PreprocessedEntities) 489 + llvm::capacity_in_bytes(LoadedPreprocessedEntities); 490 } 491