!140 [backport][Clang] Defer the instantiation of explicit-specifier until constraint checking completes
From: @mmzzmm Reviewed-by: @liyunfei33 Signed-off-by: @liyunfei33
This commit is contained in:
commit
8dcd305989
@ -0,0 +1,259 @@
|
|||||||
|
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
|
||||||
|
|
||||||
@ -37,7 +37,7 @@
|
|||||||
|
|
||||||
Name: %{pkg_name}
|
Name: %{pkg_name}
|
||||||
Version: %{clang_version}
|
Version: %{clang_version}
|
||||||
Release: 17
|
Release: 18
|
||||||
Summary: A C language family front-end for LLVM
|
Summary: A C language family front-end for LLVM
|
||||||
|
|
||||||
License: NCSA
|
License: NCSA
|
||||||
@ -62,6 +62,7 @@ Patch13: 0013-Ignored-option-Wa-generate-missing-build-notes.patch
|
|||||||
Patch14: 0014-Update-llvm-lit-config-to-support-build_for_openeule.patch
|
Patch14: 0014-Update-llvm-lit-config-to-support-build_for_openeule.patch
|
||||||
Patch15: 0015-Complete-fgcc-compatible-option-scope.patch
|
Patch15: 0015-Complete-fgcc-compatible-option-scope.patch
|
||||||
Patch16: 0016-Handling-of-option-Wall-and-Werror-format-2-override.patch
|
Patch16: 0016-Handling-of-option-Wall-and-Werror-format-2-override.patch
|
||||||
|
Patch17: 0017-Backport-Defer-the-instantiation-of-explicit-specifier-until-.patch
|
||||||
|
|
||||||
# Patches for clang-tools-extra
|
# Patches for clang-tools-extra
|
||||||
# See https://reviews.llvm.org/D120301
|
# See https://reviews.llvm.org/D120301
|
||||||
@ -396,6 +397,10 @@ LD_LIBRARY_PATH=%{buildroot}/%{install_libdir} %{__ninja} check-all -C ./_build
|
|||||||
%{install_bindir}/git-clang-format
|
%{install_bindir}/git-clang-format
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
|
* Thu Sep 05 2024 Zhao Mengmeng <zhaomengmeng@kylinos.cn> - 17.0.6-18
|
||||||
|
- Fix the too-early instantiation of conditional "explict" by applying the patch
|
||||||
|
of https://github.com/llvm/llvm-project/commit/128b3b61fe6768c724975fd1df2be0abec848cf6
|
||||||
|
|
||||||
* Mon Jul 22 2024 wangqiang <wangqiang1@kylinos.cn> - 17.0.6-17
|
* Mon Jul 22 2024 wangqiang <wangqiang1@kylinos.cn> - 17.0.6-17
|
||||||
- Complete -fgcc-compatible option scope to Langopts and Diagopts, and handling of option `-Wall` and `-Werror=format=2` override `-Wno`
|
- Complete -fgcc-compatible option scope to Langopts and Diagopts, and handling of option `-Wall` and `-Werror=format=2` override `-Wno`
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user