void IncrementalParser::commitTransaction(Transaction* T) { //Transaction* CurT = m_Consumer->getTransaction(); assert(T->isCompleted() && "Transaction not ended!?"); assert(T->getState() != Transaction::kCommitted && "Committing an already committed transaction."); // If committing a nested transaction the active one should be its parent // from now on. if (T->isNestedTransaction()) m_Consumer->setTransaction(T->getParent()); // Check for errors... if (T->getIssuedDiags() == Transaction::kErrors) { rollbackTransaction(T); return; } if (T->hasNestedTransactions()) { for(Transaction::const_nested_iterator I = T->nested_begin(), E = T->nested_end(); I != E; ++I) if ((*I)->getState() != Transaction::kCommitted) commitTransaction(*I); } if (!transformTransactionAST(T)) return; // Here we expect a template instantiation. We need to open the transaction // that we are currently work with. Transaction::State oldState = T->getState(); T->setState(Transaction::kCollecting); // Pull all template instantiations in that came from the consumers. getCI()->getSema().PerformPendingInstantiations(); T->setState(oldState); m_Consumer->HandleTranslationUnit(getCI()->getASTContext()); if (T->getCompilationOpts().CodeGeneration && hasCodeGenerator()) { codeGenTransaction(T); transformTransactionIR(T); } // The static initializers might run anything and can thus cause more // decls that need to end up in a transaction. But this one is done // with CodeGen... T->setState(Transaction::kCommitted); if (T->getCompilationOpts().CodeGeneration && hasCodeGenerator()) { runStaticInitOnTransaction(T); } InterpreterCallbacks* callbacks = m_Interpreter->getCallbacks(); if (callbacks) callbacks->TransactionCommitted(*T); // If the transaction is empty do nothing. // Except it was nested transaction and we want to reuse it later on. if (T->empty() && T->isNestedTransaction()) { // We need to remove the marker from its parent. Transaction* ParentT = T->getParent(); for (size_t i = 0; i < ParentT->size(); ++i) if ((*ParentT)[i].m_DGR.isNull()) ParentT->erase(i); } }
void IncrementalParser::commitTransaction(ParseResultTransaction& PRT, bool ClearDiagClient) { Transaction* T = PRT.getPointer(); if (!T) { if (PRT.getInt() != kSuccess) { // Nothing has been emitted to Codegen, reset the Diags. DiagnosticsEngine& Diags = getCI()->getSema().getDiagnostics(); Diags.Reset(/*soft=*/true); if (ClearDiagClient) Diags.getClient()->clear(); } return; } assert(T->isCompleted() && "Transaction not ended!?"); assert(T->getState() != Transaction::kCommitted && "Committing an already committed transaction."); assert((T->getIssuedDiags() == Transaction::kErrors || !T->empty()) && "Valid Transactions must not be empty;"); // If committing a nested transaction the active one should be its parent // from now on. if (T->isNestedTransaction()) m_Consumer->setTransaction(T->getParent()); // Check for errors... if (T->getIssuedDiags() == Transaction::kErrors) { // Make module visible to TransactionUnloader. bool MustStartNewModule = false; if (!T->isNestedTransaction() && hasCodeGenerator()) { MustStartNewModule = true; std::unique_ptr<llvm::Module> M(getCodeGenerator()->ReleaseModule()); if (M) { T->setModule(std::move(M)); } } // Module has been released from Codegen, reset the Diags now. DiagnosticsEngine& Diags = getCI()->getSema().getDiagnostics(); Diags.Reset(/*soft=*/true); if (ClearDiagClient) Diags.getClient()->clear(); PRT.setPointer(nullptr); PRT.setInt(kFailed); m_Interpreter->unload(*T); // Create a new module if necessary. if (MustStartNewModule) StartModule(); return; } if (T->hasNestedTransactions()) { Transaction* TopmostParent = T->getTopmostParent(); EParseResult PR = kSuccess; if (TopmostParent->getIssuedDiags() == Transaction::kErrors) PR = kFailed; else if (TopmostParent->getIssuedDiags() == Transaction::kWarnings) PR = kSuccessWithWarnings; for (Transaction::const_nested_iterator I = T->nested_begin(), E = T->nested_end(); I != E; ++I) if ((*I)->getState() != Transaction::kCommitted) { ParseResultTransaction PRT(*I, PR); commitTransaction(PRT); } } // If there was an error coming from the transformers. if (T->getIssuedDiags() == Transaction::kErrors) { m_Interpreter->unload(*T); return; } // Here we expect a template instantiation. We need to open the transaction // that we are currently work with. { Transaction* prevConsumerT = m_Consumer->getTransaction(); m_Consumer->setTransaction(T); Transaction* nestedT = beginTransaction(T->getCompilationOpts()); // Pull all template instantiations in that came from the consumers. getCI()->getSema().PerformPendingInstantiations(); ParseResultTransaction nestedPRT = endTransaction(nestedT); commitTransaction(nestedPRT); m_Consumer->setTransaction(prevConsumerT); } m_Consumer->HandleTranslationUnit(getCI()->getASTContext()); // The static initializers might run anything and can thus cause more // decls that need to end up in a transaction. But this one is done // with CodeGen... if (T->getCompilationOpts().CodeGeneration && hasCodeGenerator()) { Transaction* prevConsumerT = m_Consumer->getTransaction(); m_Consumer->setTransaction(T); codeGenTransaction(T); T->setState(Transaction::kCommitted); if (!T->getParent()) { if (m_Interpreter->executeTransaction(*T) >= Interpreter::kExeFirstError) { // Roll back on error in initializers. // T maybe pointing to freed memory after this call: // Interpreter::unload // IncrementalParser::deregisterTransaction // TransactionPool::releaseTransaction m_Interpreter->unload(*T); return; } } m_Consumer->setTransaction(prevConsumerT); } T->setState(Transaction::kCommitted); if (InterpreterCallbacks* callbacks = m_Interpreter->getCallbacks()) callbacks->TransactionCommitted(*T); }