#225 Backport a patch from LLVM trunk
Merged 4 months ago by nikic. Opened 4 months ago by tchaikov.
rpms/ tchaikov/clang rawhide  into  rawhide

@@ -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

+ 

file modified
+6 -1
@@ -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 @@ 

  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 @@ 

  

  %endif

  %changelog

+ * Fri Jan 26 2024 Kefu Chai <kefu.chai@scylladb.com> - 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 <releng@fedoraproject.org> - 17.0.6-5

  - Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild

  

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

Build succeeded.
https://fedora.softwarefactory-project.io/zuul/buildset/98ee1ac989ac4b1ba544629fea737c69

Can you generate the patch using git format-patch and also add a comment in the spec file with a link to the commit on github.

v2:

  • generate the patch using git format-patch
  • add a comment in the change to reference the github commit from which the patch was generated
  • correct the bogus date of the changelog entry. it was Fri Jan 26 2023, changed it to Fri Jan 26 2024

@tstellar Hi Tom, thank you for your review and suggestions. could you take another look?

rebased onto e47a3dd

4 months ago

rebased onto b2bda92

4 months ago

Build succeeded.
https://fedora.softwarefactory-project.io/zuul/buildset/18c6613fab0f4fe8a2de2ddcd1dc1ad8

Pull-Request has been merged by nikic

4 months ago

Do you need this merged into f38 as well?

Do you need this merged into f38 as well?

@nikic hi Nikita thank you for merging this change! Yeah, that'd be lovely! Could you please also merge this change into f39? the project i am working on is mainly using f38. and i am using f39 as my daily driver. we will (hopefully) move over to f39 in couple months.

Ah, I mixed up version numbers and was actually thinking of f39. The bodhi update for f39 is https://bodhi.fedoraproject.org/updates/FEDORA-2024-76bd2a4214, if you want to test it.

f38 has an older LLVM version, so it may not backport straightforwardly there.

Ah, I mixed up version numbers and was actually thinking of f39. The bodhi update for f39 is https://bodhi.fedoraproject.org/updates/FEDORA-2024-76bd2a4214, if you want to test it.

f38 has an older LLVM version, so it may not backport straightforwardly there.

thanks! i prepared #226 for f38. could please you take a look?