From 13f0e8680d7ac8e3c911293edf3f6d2e1fafe181 Mon Sep 17 00:00:00 2001 From: Vassil Vassilev Date: Sat, 4 May 2024 19:37:20 +0000 Subject: [PATCH] Provide a backup plan if we fail to delay the handling of declarations. This patch enhances the work done in #766 where we assumed the clients are going to be well-behaved such as clang or clang-repl. However, we can have clients which connect the clang components in a non-standard way and we should provide a reasonable fallback. This patch detects if the setup is non-standard and teaches clad to handle requests as they come, pretty much the same way as before #766 was implemented. Of course this comes with a cost when we try to differentiate declarations that are defined later in the translation unit. We expect such setups to be rare and mostly in the cases of incremental processing and old repls such as Cling. --- tools/ClangPlugin.cpp | 9 ++++++++- tools/ClangPlugin.h | 14 ++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/tools/ClangPlugin.cpp b/tools/ClangPlugin.cpp index ef38173aa..4bd485524 100644 --- a/tools/ClangPlugin.cpp +++ b/tools/ClangPlugin.cpp @@ -129,6 +129,10 @@ namespace clad { SetRequestOptions(opts); DiffCollector collector(DGR, CladEnabledRange, m_DiffRequestGraph, S, opts); + // We could not delay the processing of derivatives, inform act as if each + // call is final. That would still have vgvassilev/clad#248 unresolved. + if (!m_Multiplexer) + FinalizeTranslationUnit(); } FunctionDecl* CladPlugin::ProcessDiffRequest(DiffRequest& request) { @@ -394,7 +398,7 @@ namespace clad { SetTBRAnalysisOptions(m_DO, opts); } - void CladPlugin::HandleTranslationUnit(ASTContext& C) { + void CladPlugin::FinalizeTranslationUnit() { Sema& S = m_CI.getSema(); // Restore the TUScope that became a 0 in Sema::ActOnEndOfTranslationUnit. if (!m_CI.getPreprocessor().isIncrementalProcessingEnabled()) @@ -418,7 +422,10 @@ namespace clad { // Force emission of the produced pending template instantiations. LocalInstantiations.perform(); GlobalInstantiations.perform(); + } + void CladPlugin::HandleTranslationUnit(ASTContext& C) { + FinalizeTranslationUnit(); SendToMultiplexer(); m_Multiplexer->HandleTranslationUnit(C); } diff --git a/tools/ClangPlugin.h b/tools/ClangPlugin.h index 5543b1b2d..3ec1f9be6 100644 --- a/tools/ClangPlugin.h +++ b/tools/ClangPlugin.h @@ -23,6 +23,7 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/Support/Casting.h" #include "llvm/Support/Timer.h" namespace clang { @@ -167,6 +168,14 @@ class CladTimerGroup { AppendDelayed({CallKind::HandleCXXStaticMemberVarInstantiation, D}); } bool HandleTopLevelDecl(clang::DeclGroupRef D) override { + if (D.isSingleDecl()) + if (auto* FD = llvm::dyn_cast(D.getSingleDecl())) + if (m_DFC.IsDerivative(FD)) { + assert(!m_Multiplexer && + "Must happen only if we failed to rearrange the consumers"); + return true; + } + HandleTopLevelDeclForClad(D); AppendDelayed({CallKind::HandleTopLevelDecl, D}); return true; // happyness, continue parsing @@ -250,6 +259,7 @@ class CladTimerGroup { "Must start from index 0!"); m_DelayedCalls.push_back(DCI); } + void FinalizeTranslationUnit(); void SendToMultiplexer(); bool CheckBuiltins(); void SetRequestOptions(RequestOptions& opts) const; @@ -258,6 +268,10 @@ class CladTimerGroup { DelayedCallInfo DCI{CallKind::HandleTopLevelDecl, D}; assert(!llvm::is_contained(m_DelayedCalls, DCI) && "Already exists!"); AppendDelayed(DCI); + // We could not delay the process due to some strange way of + // initialization, inform the consumers now. + if (!m_Multiplexer) + m_CI.getASTConsumer().HandleTopLevelDecl(DCI.m_DGR); } void HandleTopLevelDeclForClad(clang::DeclGroupRef DGR); };