Index: include/clang/Serialization/ASTReader.h =================================================================== --- include/clang/Serialization/ASTReader.h +++ include/clang/Serialization/ASTReader.h @@ -984,14 +984,26 @@ /// \brief The generation number of each identifier, which keeps track of /// the last time we loaded information about this identifier. llvm::DenseMap IdentifierGeneration; - - /// \brief Contains declarations and definitions that will be + + class InterestingDecl { + Decl *D; + bool DeclHasPendingBody; + + public: + InterestingDecl(Decl *D, bool HasBody) + : D(D), DeclHasPendingBody(HasBody) {} + Decl *getDecl() { return D; } + /// Whether the declaration has a pending body. + bool hasPendingBody() { return DeclHasPendingBody; } + }; + + /// \brief Contains declarations and definitions that could be /// "interesting" to the ASTConsumer, when we get that AST consumer. /// /// "Interesting" declarations are those that have data that may /// need to be emitted, such as inline function definitions or /// Objective-C protocols. - std::deque InterestingDecls; + std::deque PotentiallyInterestingDecls; /// \brief The list of redeclaration chains that still need to be /// reconstructed, and the local offset to the corresponding list Index: lib/Serialization/ASTReader.cpp =================================================================== --- lib/Serialization/ASTReader.cpp +++ lib/Serialization/ASTReader.cpp @@ -7191,31 +7191,6 @@ Consumer->HandleInterestingDecl(DeclGroupRef(ImplD)); } -void ASTReader::PassInterestingDeclsToConsumer() { - assert(Consumer); - - if (PassingDeclsToConsumer) - return; - - // Guard variable to avoid recursively redoing the process of passing - // decls to consumer. - SaveAndRestore GuardPassingDeclsToConsumer(PassingDeclsToConsumer, - true); - - // Ensure that we've loaded all potentially-interesting declarations - // that need to be eagerly loaded. - for (auto ID : EagerlyDeserializedDecls) - GetDecl(ID); - EagerlyDeserializedDecls.clear(); - - while (!InterestingDecls.empty()) { - Decl *D = InterestingDecls.front(); - InterestingDecls.pop_front(); - - PassInterestingDeclToConsumer(D); - } -} - void ASTReader::PassInterestingDeclToConsumer(Decl *D) { if (ObjCImplDecl *ImplD = dyn_cast(D)) PassObjCImplDeclToConsumer(ImplD, Consumer); Index: lib/Serialization/ASTReaderDecl.cpp =================================================================== --- lib/Serialization/ASTReaderDecl.cpp +++ lib/Serialization/ASTReaderDecl.cpp @@ -3609,12 +3609,37 @@ // AST consumer might need to know about, queue it. // We don't pass it to the consumer immediately because we may be in recursive // loading, and some declarations may still be initializing. - if (isConsumerInterestedIn(Context, D, Reader.hasPendingBody())) - InterestingDecls.push_back(D); + PotentiallyInterestingDecls.push_back( + InterestingDecl(D, Reader.hasPendingBody())); return D; } +void ASTReader::PassInterestingDeclsToConsumer() { + assert(Consumer); + + if (PassingDeclsToConsumer) + return; + + // Guard variable to avoid recursively redoing the process of passing + // decls to consumer. + SaveAndRestore GuardPassingDeclsToConsumer(PassingDeclsToConsumer, + true); + + // Ensure that we've loaded all potentially-interesting declarations + // that need to be eagerly loaded. + for (auto ID : EagerlyDeserializedDecls) + GetDecl(ID); + EagerlyDeserializedDecls.clear(); + + while (!PotentiallyInterestingDecls.empty()) { + InterestingDecl D = PotentiallyInterestingDecls.front(); + PotentiallyInterestingDecls.pop_front(); + if (isConsumerInterestedIn(Context, D.getDecl(), D.hasPendingBody())) + PassInterestingDeclToConsumer(D.getDecl()); + } +} + void ASTReader::loadDeclUpdateRecords(serialization::DeclID ID, Decl *D) { // The declaration may have been modified by files later in the chain. // If this is the case, read the record containing the updates from each file @@ -3625,6 +3650,9 @@ auto UpdateOffsets = std::move(UpdI->second); DeclUpdateOffsets.erase(UpdI); + // FIXME: This call to isConsumerInterestedIn is not safe because + // we could be deserializing declarations at the moment. We should + // delay calling this in the same way as done in D30793. bool WasInteresting = isConsumerInterestedIn(Context, D, false); for (auto &FileAndOffset : UpdateOffsets) { ModuleFile *F = FileAndOffset.first; @@ -3646,7 +3674,8 @@ // we need to hand it off to the consumer. if (!WasInteresting && isConsumerInterestedIn(Context, D, Reader.hasPendingBody())) { - InterestingDecls.push_back(D); + PotentiallyInterestingDecls.push_back( + InterestingDecl(D, Reader.hasPendingBody())); WasInteresting = true; } }