Projects
openEuler:24.03:SP1:Everything:64G
clang
_service:tar_scm:0015-Backport-Defer-the-instan...
Sign Up
Log In
Username
Password
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File _service:tar_scm:0015-Backport-Defer-the-instantiation-of-explicit-specifier-until-.patch of Package clang
From c2668403868559918b54671d3d31527fb2f04486 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=88=98=E9=9B=A8=E5=9F=B9?= <liuyupei951018@hotmail.com> Date: Wed, 1 Nov 2023 21:45:48 +0800 Subject: [PATCH] Defer the instantiation of explicit-specifier until constraint checking completes (#70548) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Modifications: - Skip the instantiation of the explicit-specifier during Decl substitution if we are deducing template arguments and the explicit-specifier is value dependent. - Instantiate the explicit-specifier after the constraint checking completes. - Make `instantiateExplicitSpecifier` a member function in order to instantiate the explicit-specifier in different stages. This PR doesn’t defer the instantiation of the explicit specifier for deduction guides, because I’m not familiar with deduction guides yet. I’ll dig into it after this PR. According to my local test, GCC 13 tuple works with this PR. Fixes #59827. --------- Co-authored-by: Erich Keane <ekeane@nvidia.com> --- docs/ReleaseNotes.rst | 4 ++ include/clang/Sema/Sema.h | 3 ++ lib/Sema/SemaTemplateDeduction.cpp | 53 +++++++++++++++++++ lib/Sema/SemaTemplateInstantiateDecl.cpp | 40 +++++++++----- test/SemaCXX/cxx2a-explicit-bool-deferred.cpp | 31 +++++++++++ 5 files changed, 117 insertions(+), 14 deletions(-) create mode 100644 test/SemaCXX/cxx2a-explicit-bool-deferred.cpp diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 5086a56e..05dad41c 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -860,6 +860,10 @@ Bug Fixes to C++ Support (`#64172 <https://github.com/llvm/llvm-project/issues/64172>`_) and (`#64723 <https://github.com/llvm/llvm-project/issues/64723>`_). +- Clang now defers the instantiation of explicit specifier until constraint checking + completes (except deduction guides). Fixes: + (`#59827 <https://github.com/llvm/llvm-project/issues/59827>`_) + Bug Fixes to AST Handling ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 3752a23f..b2ab6d0f 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -10293,6 +10293,9 @@ public: const CXXConstructorDecl *Tmpl, const MultiLevelTemplateArgumentList &TemplateArgs); + ExplicitSpecifier instantiateExplicitSpecifier( + const MultiLevelTemplateArgumentList &TemplateArgs, ExplicitSpecifier ES); + NamedDecl *FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D, const MultiLevelTemplateArgumentList &TemplateArgs, bool FindingInstantiatedContext = false); diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp index 31ea7be2..58dd1b78 100644 --- a/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/clang/lib/Sema/SemaTemplateDeduction.cpp @@ -3546,6 +3546,48 @@ static unsigned getPackIndexForParam(Sema &S, llvm_unreachable("parameter index would not be produced from template"); } +// if `Specialization` is a `CXXConstructorDecl` or `CXXConversionDecl`, +// we'll try to instantiate and update its explicit specifier after constraint +// checking. +static Sema::TemplateDeductionResult instantiateExplicitSpecifierDeferred( + Sema &S, FunctionDecl *Specialization, + const MultiLevelTemplateArgumentList &SubstArgs, + TemplateDeductionInfo &Info, FunctionTemplateDecl *FunctionTemplate, + ArrayRef<TemplateArgument> DeducedArgs) { + auto GetExplicitSpecifier = [](FunctionDecl *D) { + return isa<CXXConstructorDecl>(D) + ? cast<CXXConstructorDecl>(D)->getExplicitSpecifier() + : cast<CXXConversionDecl>(D)->getExplicitSpecifier(); + }; + auto SetExplicitSpecifier = [](FunctionDecl *D, ExplicitSpecifier ES) { + isa<CXXConstructorDecl>(D) + ? cast<CXXConstructorDecl>(D)->setExplicitSpecifier(ES) + : cast<CXXConversionDecl>(D)->setExplicitSpecifier(ES); + }; + + ExplicitSpecifier ES = GetExplicitSpecifier(Specialization); + Expr *ExplicitExpr = ES.getExpr(); + if (!ExplicitExpr) + return Sema::TDK_Success; + if (!ExplicitExpr->isValueDependent()) + return Sema::TDK_Success; + + Sema::InstantiatingTemplate Inst( + S, Info.getLocation(), FunctionTemplate, DeducedArgs, + Sema::CodeSynthesisContext::DeducedTemplateArgumentSubstitution, Info); + if (Inst.isInvalid()) + return Sema::TDK_InstantiationDepth; + Sema::SFINAETrap Trap(S); + const ExplicitSpecifier InstantiatedES = + S.instantiateExplicitSpecifier(SubstArgs, ES); + if (InstantiatedES.isInvalid() || Trap.hasErrorOccurred()) { + Specialization->setInvalidDecl(true); + return Sema::TDK_SubstitutionFailure; + } + SetExplicitSpecifier(Specialization, InstantiatedES); + return Sema::TDK_Success; +} + /// Finish template argument deduction for a function template, /// checking the deduced template arguments for completeness and forming /// the function template specialization. @@ -3675,6 +3717,17 @@ Sema::TemplateDeductionResult Sema::FinishTemplateArgumentDeduction( } } + // We skipped the instantiation of the explicit-specifier during the + // substitution of `FD` before. So, we try to instantiate it back if + // `Specialization` is either a constructor or a conversion function. + if (isa<CXXConstructorDecl, CXXConversionDecl>(Specialization)) { + if (TDK_Success != instantiateExplicitSpecifierDeferred( + *this, Specialization, SubstArgs, Info, + FunctionTemplate, DeducedArgs)) { + return TDK_SubstitutionFailure; + } + } + if (OriginalCallArgs) { // C++ [temp.deduct.call]p4: // In general, the deduction process attempts to find template argument diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index f78d46f5..a40510ce 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -555,18 +555,16 @@ static void instantiateDependentAMDGPUFlatWorkGroupSizeAttr( S.addAMDGPUFlatWorkGroupSizeAttr(New, Attr, MinExpr, MaxExpr); } -static ExplicitSpecifier -instantiateExplicitSpecifier(Sema &S, - const MultiLevelTemplateArgumentList &TemplateArgs, - ExplicitSpecifier ES, FunctionDecl *New) { +ExplicitSpecifier Sema::instantiateExplicitSpecifier( + const MultiLevelTemplateArgumentList &TemplateArgs, ExplicitSpecifier ES) { if (!ES.getExpr()) return ES; Expr *OldCond = ES.getExpr(); Expr *Cond = nullptr; { EnterExpressionEvaluationContext Unevaluated( - S, Sema::ExpressionEvaluationContext::ConstantEvaluated); - ExprResult SubstResult = S.SubstExpr(OldCond, TemplateArgs); + *this, Sema::ExpressionEvaluationContext::ConstantEvaluated); + ExprResult SubstResult = SubstExpr(OldCond, TemplateArgs); if (SubstResult.isInvalid()) { return ExplicitSpecifier::Invalid(); } @@ -574,7 +572,7 @@ instantiateExplicitSpecifier(Sema &S, } ExplicitSpecifier Result(Cond, ES.getKind()); if (!Cond->isTypeDependent()) - S.tryResolveExplicitSpecifier(Result); + tryResolveExplicitSpecifier(Result); return Result; } @@ -2065,8 +2063,8 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl( ExplicitSpecifier InstantiatedExplicitSpecifier; if (auto *DGuide = dyn_cast<CXXDeductionGuideDecl>(D)) { - InstantiatedExplicitSpecifier = instantiateExplicitSpecifier( - SemaRef, TemplateArgs, DGuide->getExplicitSpecifier(), DGuide); + InstantiatedExplicitSpecifier = SemaRef.instantiateExplicitSpecifier( + TemplateArgs, DGuide->getExplicitSpecifier()); if (InstantiatedExplicitSpecifier.isInvalid()) return nullptr; } @@ -2440,11 +2438,25 @@ Decl *TemplateDeclInstantiator::VisitCXXMethodDecl( } } - ExplicitSpecifier InstantiatedExplicitSpecifier = - instantiateExplicitSpecifier(SemaRef, TemplateArgs, - ExplicitSpecifier::getFromDecl(D), D); - if (InstantiatedExplicitSpecifier.isInvalid()) - return nullptr; + auto InstantiatedExplicitSpecifier = ExplicitSpecifier::getFromDecl(D); + // deduction guides need this + const bool CouldInstantiate = + InstantiatedExplicitSpecifier.getExpr() == nullptr || + !InstantiatedExplicitSpecifier.getExpr()->isValueDependent(); + + // Delay the instantiation of the explicit-specifier until after the + // constraints are checked during template argument deduction. + if (CouldInstantiate || + SemaRef.CodeSynthesisContexts.back().Kind != + Sema::CodeSynthesisContext::DeducedTemplateArgumentSubstitution) { + InstantiatedExplicitSpecifier = SemaRef.instantiateExplicitSpecifier( + TemplateArgs, InstantiatedExplicitSpecifier); + + if (InstantiatedExplicitSpecifier.isInvalid()) + return nullptr; + } else { + InstantiatedExplicitSpecifier.setKind(ExplicitSpecKind::Unresolved); + } // Implicit destructors/constructors created for local classes in // DeclareImplicit* (see SemaDeclCXX.cpp) might not have an associated TSI. diff --git a/clang/test/SemaCXX/cxx2a-explicit-bool-deferred.cpp b/clang/test/SemaCXX/cxx2a-explicit-bool-deferred.cpp new file mode 100644 index 00000000..4d667008 --- /dev/null +++ b/clang/test/SemaCXX/cxx2a-explicit-bool-deferred.cpp @@ -0,0 +1,31 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++2a %s + +template <typename T1, typename T2> struct is_same { + static constexpr bool value = false; +}; + +template <typename T> struct is_same<T, T> { + static constexpr bool value = true; +}; + +template <class T, class U> +concept SameHelper = is_same<T, U>::value; +template <class T, class U> +concept same_as = SameHelper<T, U> && SameHelper<U, T>; + +namespace deferred_instantiation { +template <class X> constexpr X do_not_instantiate() { return nullptr; } + +struct T { + template <same_as<float> X> explicit(do_not_instantiate<X>()) T(X) {} + + T(int) {} +}; + +T t(5); +// expected-error@17{{cannot initialize}} +// expected-note@20{{in instantiation of function template specialization}} +// expected-note@30{{while substituting deduced template arguments}} +// expected-note@30{{in instantiation of function template specialization}} +T t2(5.0f); +} // namespace deferred_instantiation -- 2.33.0
Locations
Projects
Search
Status Monitor
Help
Open Build Service
OBS Manuals
API Documentation
OBS Portal
Reporting a Bug
Contact
Mailing List
Forums
Chat (IRC)
Twitter
Open Build Service (OBS)
is an
openSUSE project
.
浙ICP备2022010568号-2