From b2bda922a0526294aa9e5f5158cd75bd94abbf5b Mon Sep 17 00:00:00 2001 From: Kefu Chai Date: Fri, 26 Jan 2024 22:28:10 +0800 Subject: [PATCH] Backport a patch from LLVM trunk Since LLVM 17.0.6 is the last release of the 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 include patch was updated to resolve the conflicts when being applied to the llvmorg-17.0.6 tag. the fix has been tested after applying it on top of upstream's llvmorg-17.0.6 tag. Signed-off-by: Kefu Chai --- ...instantiation-of-explicit-specifier-.patch | 260 ++++++++++++++++++ clang.spec | 7 +- 2 files changed, 266 insertions(+), 1 deletion(-) create mode 100644 0001-Clang-Defer-the-instantiation-of-explicit-specifier-.patch diff --git a/0001-Clang-Defer-the-instantiation-of-explicit-specifier-.patch b/0001-Clang-Defer-the-instantiation-of-explicit-specifier-.patch new file mode 100644 index 0000000..69fb3ba --- /dev/null +++ b/0001-Clang-Defer-the-instantiation-of-explicit-specifier-.patch @@ -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?= +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 +(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 `_) and + (`#64723 `_). + ++- Clang now defers the instantiation of explicit specifier until constraint checking ++ completes (except deduction guides). Fixes: ++ (`#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 DeducedArgs) { ++ auto GetExplicitSpecifier = [](FunctionDecl *D) { ++ return isa(D) ++ ? cast(D)->getExplicitSpecifier() ++ : cast(D)->getExplicitSpecifier(); ++ }; ++ auto SetExplicitSpecifier = [](FunctionDecl *D, ExplicitSpecifier ES) { ++ isa(D) ++ ? cast(D)->setExplicitSpecifier(ES) ++ : cast(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(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(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 struct is_same { ++ static constexpr bool value = false; ++}; ++ ++template struct is_same { ++ static constexpr bool value = true; ++}; ++ ++template ++concept SameHelper = is_same::value; ++template ++concept same_as = SameHelper && SameHelper; ++ ++namespace deferred_instantiation { ++template constexpr X do_not_instantiate() { return nullptr; } ++ ++struct T { ++ template X> explicit(do_not_instantiate()) 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 + diff --git a/clang.spec b/clang.spec index da9712c..32fae34 100644 --- a/clang.spec +++ b/clang.spec @@ -55,7 +55,7 @@ Name: %pkg_name Version: %{clang_version}%{?rc_ver:~rc%{rc_ver}}%{?llvm_snapshot_version_suffix:~%{llvm_snapshot_version_suffix}} -Release: 5%{?dist} +Release: 6%{?dist} Summary: A C language family front-end for LLVM License: Apache-2.0 WITH LLVM-exception OR NCSA @@ -93,6 +93,7 @@ Patch5: 0001-Workaround-a-bug-in-ORC-on-ppc64le.patch Patch6: cfg.patch Patch7: tsa.patch Patch8: 0001-Clang-Fix-build-with-GCC-14-on-ARM.patch +Patch9: 0001-Clang-Defer-the-instantiation-of-explicit-specifier-.patch # RHEL specific patches @@ -623,6 +624,10 @@ LD_LIBRARY_PATH=%{buildroot}/%{_libdir} %{__ninja} check-all -C %{__cmake_buildd %endif %changelog +* Fri Jan 26 2024 Kefu Chai - 17.0.6-6 +- Fix the too-early instantiation of conditional "explict" by applying the patch + of https://github.com/llvm/llvm-project/commit/128b3b61fe6768c724975fd1df2be0abec848cf6 + * Tue Jan 23 2024 Fedora Release Engineering - 17.0.6-5 - Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild