Commit d82de6f0 authored by Hans Wennborg's avatar Hans Wennborg
Browse files

Merging r276473:

------------------------------------------------------------------------
r276473 | vvassilev | 2016-07-22 14:08:24 -0700 (Fri, 22 Jul 2016) | 13 lines

[modules] Teach the ASTWriter to ignore mutations coming from the ASTReader.

Processing update records (and loading a module, in general) might trigger
unexpected calls to the ASTWriter (being a mutation listener). Now we have a
mechanism to suppress those calls to the ASTWriter but notify other possible
mutation listeners.

Fixes https://llvm.org/bugs/show_bug.cgi?id=28332

Patch by Cristina Cristescu and me.

Reviewed by Richard Smith (D21800).

------------------------------------------------------------------------

llvm-svn: 276757
parent d6dff71d
Loading
Loading
Loading
Loading
+22 −0
Original line number Diff line number Diff line
@@ -843,6 +843,9 @@ private:
  /// \brief Whether we have tried loading the global module index yet.
  bool TriedLoadingGlobalIndex;

  ///\brief Whether we are currently processing update records.
  bool ProcessingUpdateRecords;

  typedef llvm::DenseMap<unsigned, SwitchCase *> SwitchCaseMapTy;
  /// \brief Mapping from switch-case IDs in the chain to switch-case statements
  ///
@@ -1042,6 +1045,23 @@ private:
    ~ReadingKindTracker() { Reader.ReadingKind = PrevKind; }
  };

  /// \brief RAII object to mark the start of processing updates.
  class ProcessingUpdatesRAIIObj {
    ASTReader &Reader;
    bool PrevState;

    ProcessingUpdatesRAIIObj(const ProcessingUpdatesRAIIObj &) = delete;
    void operator=(const ProcessingUpdatesRAIIObj &) = delete;

  public:
    ProcessingUpdatesRAIIObj(ASTReader &reader)
      : Reader(reader), PrevState(Reader.ProcessingUpdateRecords) {
      Reader.ProcessingUpdateRecords = true;
    }

    ~ProcessingUpdatesRAIIObj() { Reader.ProcessingUpdateRecords = PrevState; }
  };

  /// \brief Suggested contents of the predefines buffer, after this
  /// PCH file has been processed.
  ///
@@ -2130,6 +2150,8 @@ public:

  /// \brief Loads comments ranges.
  void ReadComments() override;

  bool isProcessingUpdateRecords() { return ProcessingUpdateRecords; }
};

/// \brief Helper class that saves the current stream position and
+2 −0
Original line number Diff line number Diff line
@@ -8637,6 +8637,7 @@ void ASTReader::FinishedDeserializing() {
      auto Updates = std::move(PendingExceptionSpecUpdates);
      PendingExceptionSpecUpdates.clear();
      for (auto Update : Updates) {
        ProcessingUpdatesRAIIObj ProcessingUpdates(*this);
        auto *FPT = Update.second->getType()->castAs<FunctionProtoType>();
        auto ESI = FPT->getExtProtoInfo().ExceptionSpec;
        if (auto *Listener = Context.getASTMutationListener())
@@ -8707,6 +8708,7 @@ ASTReader::ASTReader(
      AllowConfigurationMismatch(AllowConfigurationMismatch),
      ValidateSystemInputs(ValidateSystemInputs),
      UseGlobalIndex(UseGlobalIndex), TriedLoadingGlobalIndex(false),
      ProcessingUpdateRecords(false),
      CurrSwitchCaseStmts(&SwitchCaseStmts), NumSLocEntriesRead(0),
      TotalNumSLocEntries(0), NumStatementsRead(0), TotalNumStatements(0),
      NumMacrosRead(0), TotalNumMacros(0), NumIdentifierLookups(0),
+4 −9
Original line number Diff line number Diff line
@@ -3484,6 +3484,7 @@ 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
  // and pass it to ASTDeclReader to make the modifications.
  ProcessingUpdatesRAIIObj ProcessingUpdates(*this);
  DeclUpdateOffsetsMap::iterator UpdI = DeclUpdateOffsets.find(ID);
  if (UpdI != DeclUpdateOffsets.end()) {
    auto UpdateOffsets = std::move(UpdI->second);
@@ -3902,11 +3903,8 @@ void ASTDeclReader::UpdateDecl(Decl *D, ModuleFile &ModuleFile,
    }

    case UPD_DECL_MARKED_USED: {
      // FIXME: This doesn't send the right notifications if there are
      // ASTMutationListeners other than an ASTWriter.

      // Maintain AST consistency: any later redeclarations are used too.
      D->setIsUsed();
      D->markUsed(Reader.Context);
      break;
    }

@@ -3930,11 +3928,8 @@ void ASTDeclReader::UpdateDecl(Decl *D, ModuleFile &ModuleFile,
        Exported = TD->getDefinition();
      Module *Owner = SubmoduleID ? Reader.getSubmodule(SubmoduleID) : nullptr;
      if (Reader.getContext().getLangOpts().ModulesLocalVisibility) {
        // FIXME: This doesn't send the right notifications if there are
        // ASTMutationListeners other than an ASTWriter.
        Reader.getContext().mergeDefinitionIntoModule(
            cast<NamedDecl>(Exported), Owner,
            /*NotifyListeners*/ false);
        Reader.getContext().mergeDefinitionIntoModule(cast<NamedDecl>(Exported),
                                                      Owner);
        Reader.PendingMergedDefinitionsToDeduplicate.insert(
            cast<NamedDecl>(Exported));
      } else if (Owner && Owner->NameVisibility != Module::AllVisible) {
+17 −1
Original line number Diff line number Diff line
@@ -5637,6 +5637,7 @@ void ASTWriter::ModuleRead(serialization::SubmoduleID ID, Module *Mod) {
}

void ASTWriter::CompletedTagDefinition(const TagDecl *D) {
  if (Chain && Chain->isProcessingUpdateRecords()) return;
  assert(D->isCompleteDefinition());
  assert(!WritingAST && "Already writing the AST!");
  if (auto *RD = dyn_cast<CXXRecordDecl>(D)) {
@@ -5663,6 +5664,7 @@ static bool isImportedDeclContext(ASTReader *Chain, const Decl *D) {
}

void ASTWriter::AddedVisibleDecl(const DeclContext *DC, const Decl *D) {
  if (Chain && Chain->isProcessingUpdateRecords()) return;
  assert(DC->isLookupContext() &&
          "Should not add lookup results to non-lookup contexts!");

@@ -5697,6 +5699,7 @@ void ASTWriter::AddedVisibleDecl(const DeclContext *DC, const Decl *D) {
}

void ASTWriter::AddedCXXImplicitMember(const CXXRecordDecl *RD, const Decl *D) {
  if (Chain && Chain->isProcessingUpdateRecords()) return;
  assert(D->isImplicit());

  // We're only interested in cases where a local declaration is added to an
@@ -5714,6 +5717,7 @@ void ASTWriter::AddedCXXImplicitMember(const CXXRecordDecl *RD, const Decl *D) {
}

void ASTWriter::ResolvedExceptionSpec(const FunctionDecl *FD) {
  if (Chain && Chain->isProcessingUpdateRecords()) return;
  assert(!DoneWritingDeclsAndTypes && "Already done writing updates!");
  if (!Chain) return;
  Chain->forEachImportedKeyDecl(FD, [&](const Decl *D) {
@@ -5728,6 +5732,7 @@ void ASTWriter::ResolvedExceptionSpec(const FunctionDecl *FD) {
}

void ASTWriter::DeducedReturnType(const FunctionDecl *FD, QualType ReturnType) {
  if (Chain && Chain->isProcessingUpdateRecords()) return;
  assert(!WritingAST && "Already writing the AST!");
  if (!Chain) return;
  Chain->forEachImportedKeyDecl(FD, [&](const Decl *D) {
@@ -5738,6 +5743,7 @@ void ASTWriter::DeducedReturnType(const FunctionDecl *FD, QualType ReturnType) {

void ASTWriter::ResolvedOperatorDelete(const CXXDestructorDecl *DD,
                                       const FunctionDecl *Delete) {
  if (Chain && Chain->isProcessingUpdateRecords()) return;
  assert(!WritingAST && "Already writing the AST!");
  assert(Delete && "Not given an operator delete");
  if (!Chain) return;
@@ -5747,6 +5753,7 @@ void ASTWriter::ResolvedOperatorDelete(const CXXDestructorDecl *DD,
}

void ASTWriter::CompletedImplicitDefinition(const FunctionDecl *D) {
  if (Chain && Chain->isProcessingUpdateRecords()) return;
  assert(!WritingAST && "Already writing the AST!");
  if (!D->isFromASTFile())
    return; // Declaration not imported from PCH.
@@ -5756,6 +5763,7 @@ void ASTWriter::CompletedImplicitDefinition(const FunctionDecl *D) {
}

void ASTWriter::FunctionDefinitionInstantiated(const FunctionDecl *D) {
  if (Chain && Chain->isProcessingUpdateRecords()) return;
  assert(!WritingAST && "Already writing the AST!");
  if (!D->isFromASTFile())
    return;
@@ -5764,6 +5772,7 @@ void ASTWriter::FunctionDefinitionInstantiated(const FunctionDecl *D) {
}

void ASTWriter::StaticDataMemberInstantiated(const VarDecl *D) {
  if (Chain && Chain->isProcessingUpdateRecords()) return;
  assert(!WritingAST && "Already writing the AST!");
  if (!D->isFromASTFile())
    return;
@@ -5776,6 +5785,7 @@ void ASTWriter::StaticDataMemberInstantiated(const VarDecl *D) {
}

void ASTWriter::DefaultArgumentInstantiated(const ParmVarDecl *D) {
  if (Chain && Chain->isProcessingUpdateRecords()) return;
  assert(!WritingAST && "Already writing the AST!");
  if (!D->isFromASTFile())
    return;
@@ -5786,6 +5796,7 @@ void ASTWriter::DefaultArgumentInstantiated(const ParmVarDecl *D) {

void ASTWriter::AddedObjCCategoryToInterface(const ObjCCategoryDecl *CatD,
                                             const ObjCInterfaceDecl *IFD) {
  if (Chain && Chain->isProcessingUpdateRecords()) return;
  assert(!WritingAST && "Already writing the AST!");
  if (!IFD->isFromASTFile())
    return; // Declaration not imported from PCH.
@@ -5796,6 +5807,7 @@ void ASTWriter::AddedObjCCategoryToInterface(const ObjCCategoryDecl *CatD,
}

void ASTWriter::DeclarationMarkedUsed(const Decl *D) {
  if (Chain && Chain->isProcessingUpdateRecords()) return;
  assert(!WritingAST && "Already writing the AST!");

  // If there is *any* declaration of the entity that's not from an AST file,
@@ -5809,6 +5821,7 @@ void ASTWriter::DeclarationMarkedUsed(const Decl *D) {
}

void ASTWriter::DeclarationMarkedOpenMPThreadPrivate(const Decl *D) {
  if (Chain && Chain->isProcessingUpdateRecords()) return;
  assert(!WritingAST && "Already writing the AST!");
  if (!D->isFromASTFile())
    return;
@@ -5818,6 +5831,7 @@ void ASTWriter::DeclarationMarkedOpenMPThreadPrivate(const Decl *D) {

void ASTWriter::DeclarationMarkedOpenMPDeclareTarget(const Decl *D,
                                                     const Attr *Attr) {
  if (Chain && Chain->isProcessingUpdateRecords()) return;
  assert(!WritingAST && "Already writing the AST!");
  if (!D->isFromASTFile())
    return;
@@ -5827,6 +5841,7 @@ void ASTWriter::DeclarationMarkedOpenMPDeclareTarget(const Decl *D,
}

void ASTWriter::RedefinedHiddenDefinition(const NamedDecl *D, Module *M) {
  if (Chain && Chain->isProcessingUpdateRecords()) return;
  assert(!WritingAST && "Already writing the AST!");
  assert(D->isHidden() && "expected a hidden declaration");
  DeclUpdates[D].push_back(DeclUpdate(UPD_DECL_EXPORTED, M));
@@ -5834,6 +5849,7 @@ void ASTWriter::RedefinedHiddenDefinition(const NamedDecl *D, Module *M) {

void ASTWriter::AddedAttributeToRecord(const Attr *Attr,
                                       const RecordDecl *Record) {
  if (Chain && Chain->isProcessingUpdateRecords()) return;
  assert(!WritingAST && "Already writing the AST!");
  if (!Record->isFromASTFile())
    return;
+7 −0
Original line number Diff line number Diff line
#ifndef LLVM_ADT_SMALLVECTORIMPL_H
#define LLVM_ADT_SMALLVECTORIMPL_H
class SmallVectorImpl {
public:
  ~SmallVectorImpl();
};
#endif
 No newline at end of file
Loading