| |
@@ -0,0 +1,260 @@
|
| |
+ From fabda7312b91a768617f4ff1fabe0e1cc7d9131c 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] [Clang] 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>
|
| |
+ (cherry picked from commit 128b3b61fe6768c724975fd1df2be0abec848cf6)
|
| |
+ ---
|
| |
+ clang/docs/ReleaseNotes.rst | 4 ++
|
| |
+ clang/include/clang/Sema/Sema.h | 3 ++
|
| |
+ clang/lib/Sema/SemaTemplateDeduction.cpp | 53 +++++++++++++++++++
|
| |
+ .../lib/Sema/SemaTemplateInstantiateDecl.cpp | 40 +++++++++-----
|
| |
+ .../SemaCXX/cxx2a-explicit-bool-deferred.cpp | 31 +++++++++++
|
| |
+ 5 files changed, 117 insertions(+), 14 deletions(-)
|
| |
+ create mode 100644 clang/test/SemaCXX/cxx2a-explicit-bool-deferred.cpp
|
| |
+
|
| |
+ diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
|
| |
+ index a1143e14562e..8e3b94ca2017 100644
|
| |
+ --- a/clang/docs/ReleaseNotes.rst
|
| |
+ +++ b/clang/docs/ReleaseNotes.rst
|
| |
+ @@ -857,6 +857,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 3752a23faa85..b2ab6d0f8445 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 31ea7be2975e..58dd1b783bac 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 f78d46f59503..a40510ce5f2c 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 000000000000..4d667008f2e2
|
| |
+ --- /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.43.0
|
| |
+
|
| |
since LLVM 17.0.6 is the last release of 17.x branch. the fix backported
by this change helps to address a critical build failure with libstdc++
shipped with GCC-13, so we need to include it in the clang packages.
the fix has been tested after being applied on the top of upstream's
llvmorg-17.0.6 tag.
Signed-off-by: Kefu Chai tchaikov@gmail.com