[lld] [clang] [lldb] [llvm] [Clang] Defer the instantiation of explicit-specifier until constraint checking completes (PR #70548)

Erich Keane via cfe-commits cfe-commits at lists.llvm.org
Wed Nov 1 06:45:48 PDT 2023


https://github.com/erichkeane updated https://github.com/llvm/llvm-project/pull/70548

>From 11ceaed39b3f0c60c5a44c3b3a2b5856e7ee9a8d Mon Sep 17 00:00:00 2001
From: letrec <liuyupei951018 at hotmail.com>
Date: Sat, 28 Oct 2023 18:05:36 +0800
Subject: [PATCH 1/7] Defer the instantiation of explicit-specifier after
 constraint checking

---
 clang/docs/ReleaseNotes.rst                   |  4 ++
 clang/include/clang/Sema/Sema.h               |  3 +
 clang/lib/Sema/SemaTemplateDeduction.cpp      | 59 +++++++++++++++++++
 .../lib/Sema/SemaTemplateInstantiateDecl.cpp  | 40 ++++++++-----
 .../SemaCXX/cxx2a-explicit-bool-deferred.cpp  | 31 ++++++++++
 5 files changed, 123 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 bc28bb567f6932a..d9980694de40f6f 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -670,6 +670,10 @@ Bug Fixes to C++ Support
   default initializing a base class in a constant expression context. Fixes:
   (`#69890 <https://github.com/llvm/llvm-project/issues/69890>`_)
 
+- 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
 ^^^^^^^^^^^^^^^^^^^^^^^^^
 - Fixed an import failure of recursive friend class template.
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 91a4211a5cf5cce..daed24be0a86d11 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -10430,6 +10430,9 @@ class Sema final {
                                   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 0b3f0247ea3bee3..f06332770f51d1f 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -3553,6 +3553,56 @@ static unsigned getPackIndexForParam(Sema &S,
   llvm_unreachable("parameter index would not be produced from template");
 }
 
+// if `Specialization` is a `CXXConstructorDecl` or `CXXConversionDecl`
+// we try to instantiate and update its explicit specifier after constraint
+// checking.
+static Sema::TemplateDeductionResult
+tryInstantiateExplicitSpecifier(Sema &S, FunctionDecl *Specialization,
+                                const MultiLevelTemplateArgumentList &SubstArgs,
+                                TemplateDeductionInfo &Info,
+                                FunctionTemplateDecl *FunctionTemplate,
+                                ArrayRef<TemplateArgument> DeducedArgs) {
+
+  const auto TryInstantiateExplicitSpecifierForSingleDecl =
+      [&](auto *ExplicitDecl) {
+        ExplicitSpecifier ExplicitSpecifier =
+            ExplicitDecl->getExplicitSpecifier();
+        Expr *const Expr = ExplicitSpecifier.getExpr();
+        if (!Expr) {
+          return Sema::TDK_Success;
+        }
+        if (!Expr->isValueDependent()) {
+          return Sema::TDK_Success;
+        }
+        // TemplateDeclInstantiator::InitFunctionInstantiation set the
+        // ActiveInstType to TemplateInstantiation, but we need
+        // to enable SFINAE when instantiating explicit specifier.
+        Sema::InstantiatingTemplate Inst(
+            S, Info.getLocation(), FunctionTemplate, DeducedArgs,
+            Sema::CodeSynthesisContext::DeducedTemplateArgumentSubstitution,
+            Info);
+        const auto Instantiated =
+            S.instantiateExplicitSpecifier(SubstArgs, ExplicitSpecifier);
+        if (Instantiated.isInvalid()) {
+          ExplicitDecl->setInvalidDecl(true);
+          return clang::Sema::TDK_SubstitutionFailure;
+        }
+        ExplicitDecl->setExplicitSpecifier(Instantiated);
+        return clang::Sema::TDK_Success;
+      };
+  Sema::TemplateDeductionResult DeductionResult = clang::Sema::TDK_Success;
+  if (CXXConstructorDecl *ConstructorDecl =
+          dyn_cast_or_null<CXXConstructorDecl>(Specialization)) {
+    DeductionResult =
+        TryInstantiateExplicitSpecifierForSingleDecl(ConstructorDecl);
+  } else if (CXXConversionDecl *ConversionDecl =
+                 dyn_cast_or_null<CXXConversionDecl>(Specialization)) {
+    DeductionResult =
+        TryInstantiateExplicitSpecifierForSingleDecl(ConversionDecl);
+  }
+  return DeductionResult;
+}
+
 /// Finish template argument deduction for a function template,
 /// checking the deduced template arguments for completeness and forming
 /// the function template specialization.
@@ -3682,6 +3732,15 @@ Sema::TemplateDeductionResult Sema::FinishTemplateArgumentDeduction(
     }
   }
 
+  // We skipped the instantiation of the explicit-specifier during subst the
+  // decl before. Now, we try to instantiate it back if the Specialization is a
+  // constructor or a conversion.
+  if (TDK_Success !=
+      tryInstantiateExplicitSpecifier(*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 78a7892a35a320b..163dbef03e80a4d 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -563,18 +563,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();
     }
@@ -582,7 +580,7 @@ instantiateExplicitSpecifier(Sema &S,
   }
   ExplicitSpecifier Result(Cond, ES.getKind());
   if (!Cond->isTypeDependent())
-    S.tryResolveExplicitSpecifier(Result);
+    tryResolveExplicitSpecifier(Result);
   return Result;
 }
 
@@ -2073,8 +2071,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;
   }
@@ -2453,11 +2451,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 000000000000000..4d667008f2e2763
--- /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 at 17{{cannot initialize}}
+// expected-note at 20{{in instantiation of function template specialization}}
+// expected-note at 30{{while substituting deduced template arguments}}
+// expected-note at 30{{in instantiation of function template specialization}}
+T t2(5.0f);
+} // namespace deferred_instantiation

>From d7db83b18369d3b6bfa485befde699b01148dd8f Mon Sep 17 00:00:00 2001
From: letrec <liuyupei951018 at hotmail.com>
Date: Tue, 31 Oct 2023 00:47:39 +0800
Subject: [PATCH 2/7] fix CR comments

---
 clang/lib/Sema/SemaTemplateDeduction.cpp | 94 ++++++++++++------------
 1 file changed, 45 insertions(+), 49 deletions(-)

diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp
index f06332770f51d1f..0218c4319ad01a0 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -3557,50 +3557,44 @@ static unsigned getPackIndexForParam(Sema &S,
 // we try to instantiate and update its explicit specifier after constraint
 // checking.
 static Sema::TemplateDeductionResult
-tryInstantiateExplicitSpecifier(Sema &S, FunctionDecl *Specialization,
-                                const MultiLevelTemplateArgumentList &SubstArgs,
-                                TemplateDeductionInfo &Info,
-                                FunctionTemplateDecl *FunctionTemplate,
-                                ArrayRef<TemplateArgument> DeducedArgs) {
-
-  const auto TryInstantiateExplicitSpecifierForSingleDecl =
-      [&](auto *ExplicitDecl) {
-        ExplicitSpecifier ExplicitSpecifier =
-            ExplicitDecl->getExplicitSpecifier();
-        Expr *const Expr = ExplicitSpecifier.getExpr();
-        if (!Expr) {
-          return Sema::TDK_Success;
-        }
-        if (!Expr->isValueDependent()) {
-          return Sema::TDK_Success;
-        }
-        // TemplateDeclInstantiator::InitFunctionInstantiation set the
-        // ActiveInstType to TemplateInstantiation, but we need
-        // to enable SFINAE when instantiating explicit specifier.
-        Sema::InstantiatingTemplate Inst(
-            S, Info.getLocation(), FunctionTemplate, DeducedArgs,
-            Sema::CodeSynthesisContext::DeducedTemplateArgumentSubstitution,
-            Info);
-        const auto Instantiated =
-            S.instantiateExplicitSpecifier(SubstArgs, ExplicitSpecifier);
-        if (Instantiated.isInvalid()) {
-          ExplicitDecl->setInvalidDecl(true);
-          return clang::Sema::TDK_SubstitutionFailure;
-        }
-        ExplicitDecl->setExplicitSpecifier(Instantiated);
-        return clang::Sema::TDK_Success;
-      };
-  Sema::TemplateDeductionResult DeductionResult = clang::Sema::TDK_Success;
-  if (CXXConstructorDecl *ConstructorDecl =
-          dyn_cast_or_null<CXXConstructorDecl>(Specialization)) {
-    DeductionResult =
-        TryInstantiateExplicitSpecifierForSingleDecl(ConstructorDecl);
-  } else if (CXXConversionDecl *ConversionDecl =
-                 dyn_cast_or_null<CXXConversionDecl>(Specialization)) {
-    DeductionResult =
-        TryInstantiateExplicitSpecifierForSingleDecl(ConversionDecl);
-  }
-  return DeductionResult;
+resolveExplicitSpecifier(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 ExplicitSpecifier = GetExplicitSpecifier(Specialization);
+  Expr *const Expr = ExplicitSpecifier.getExpr();
+  if (!Expr) {
+    return Sema::TDK_Success;
+  }
+  if (!Expr->isValueDependent()) {
+    return Sema::TDK_Success;
+  }
+  // TemplateDeclInstantiator::InitFunctionInstantiation set the
+  // ActiveInstType to TemplateInstantiation, but we need
+  // to enable SFINAE when instantiating an explicit specifier.
+  Sema::InstantiatingTemplate Inst(
+      S, Info.getLocation(), FunctionTemplate, DeducedArgs,
+      Sema::CodeSynthesisContext::DeducedTemplateArgumentSubstitution, Info);
+  const auto Instantiated =
+      S.instantiateExplicitSpecifier(SubstArgs, ExplicitSpecifier);
+  if (Instantiated.isInvalid()) {
+    Specialization->setInvalidDecl(true);
+    return clang::Sema::TDK_SubstitutionFailure;
+  }
+  SetExplicitSpecifier(Specialization, Instantiated);
+  return clang::Sema::TDK_Success;
 }
 
 /// Finish template argument deduction for a function template,
@@ -3733,12 +3727,14 @@ Sema::TemplateDeductionResult Sema::FinishTemplateArgumentDeduction(
   }
 
   // We skipped the instantiation of the explicit-specifier during subst the
-  // decl before. Now, we try to instantiate it back if the Specialization is a
+  // FD before. So we try to instantiate it back if the `Specialization` is a
   // constructor or a conversion.
-  if (TDK_Success !=
-      tryInstantiateExplicitSpecifier(*this, Specialization, SubstArgs, Info,
-                                      FunctionTemplate, DeducedArgs)) {
-    return TDK_SubstitutionFailure;
+  if (isa<CXXConstructorDecl, CXXConversionDecl>(Specialization)) {
+    if (TDK_Success !=
+        resolveExplicitSpecifier(*this, Specialization, SubstArgs, Info,
+                                 FunctionTemplate, DeducedArgs)) {
+      return TDK_SubstitutionFailure;
+    }
   }
 
   if (OriginalCallArgs) {

>From 808802b1e40e9add618072fcfe8b7491a7f17201 Mon Sep 17 00:00:00 2001
From: letrec <liuyupei951018 at hotmail.com>
Date: Tue, 31 Oct 2023 01:05:57 +0800
Subject: [PATCH 3/7] unify ES identifier

---
 clang/lib/Sema/SemaTemplateDeduction.cpp | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp
index 0218c4319ad01a0..f905391279c02dc 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -3573,8 +3573,8 @@ resolveExplicitSpecifier(Sema &S, FunctionDecl *Specialization,
         : cast<CXXConversionDecl>(D)->setExplicitSpecifier(ES);
   };
 
-  ExplicitSpecifier ExplicitSpecifier = GetExplicitSpecifier(Specialization);
-  Expr *const Expr = ExplicitSpecifier.getExpr();
+  ExplicitSpecifier ES = GetExplicitSpecifier(Specialization);
+  Expr *const Expr = ES.getExpr();
   if (!Expr) {
     return Sema::TDK_Success;
   }
@@ -3587,8 +3587,7 @@ resolveExplicitSpecifier(Sema &S, FunctionDecl *Specialization,
   Sema::InstantiatingTemplate Inst(
       S, Info.getLocation(), FunctionTemplate, DeducedArgs,
       Sema::CodeSynthesisContext::DeducedTemplateArgumentSubstitution, Info);
-  const auto Instantiated =
-      S.instantiateExplicitSpecifier(SubstArgs, ExplicitSpecifier);
+  const auto Instantiated = S.instantiateExplicitSpecifier(SubstArgs, ES);
   if (Instantiated.isInvalid()) {
     Specialization->setInvalidDecl(true);
     return clang::Sema::TDK_SubstitutionFailure;

>From 53c6c6a398ef3b791fa30f7fd3ee011a504dbe0d Mon Sep 17 00:00:00 2001
From: letrec <liuyupei951018 at hotmail.com>
Date: Tue, 31 Oct 2023 23:56:34 +0800
Subject: [PATCH 4/7] add hasErrorOccurred check

---
 clang/lib/Sema/SemaTemplateDeduction.cpp | 44 +++++++++++++-----------
 1 file changed, 24 insertions(+), 20 deletions(-)

diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp
index f905391279c02dc..c2bfa58b2288241 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -3553,15 +3553,14 @@ static unsigned getPackIndexForParam(Sema &S,
   llvm_unreachable("parameter index would not be produced from template");
 }
 
-// if `Specialization` is a `CXXConstructorDecl` or `CXXConversionDecl`
-// we try to instantiate and update its explicit specifier after constraint
+// if `Specialization` is a `CXXConstructorDecl` or `CXXConversionDecl`,
+// we'll try to instantiate and update its explicit specifier after constraint
 // checking.
-static Sema::TemplateDeductionResult
-resolveExplicitSpecifier(Sema &S, FunctionDecl *Specialization,
-                         const MultiLevelTemplateArgumentList &SubstArgs,
-                         TemplateDeductionInfo &Info,
-                         FunctionTemplateDecl *FunctionTemplate,
-                         ArrayRef<TemplateArgument> DeducedArgs) {
+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()
@@ -3581,19 +3580,24 @@ resolveExplicitSpecifier(Sema &S, FunctionDecl *Specialization,
   if (!Expr->isValueDependent()) {
     return Sema::TDK_Success;
   }
-  // TemplateDeclInstantiator::InitFunctionInstantiation set the
-  // ActiveInstType to TemplateInstantiation, but we need
-  // to enable SFINAE when instantiating an explicit specifier.
+  // The `InstantiatingTemplate` here is used to restore `ActiveInstType` to
+  // `DeducedTemplateArgumentSubstitution` because ActiveInstType was set to
+  // `TemplateInstantiation` in
+  // `TemplateDeclInstantiator::InitFunctionInstantiation`. The real depth of
+  // instantiation should be the same as the depth in
+  // `FinishTemplateArgumentDeduction`.
+  // So we don't check `InstantiatingTemplate::IsValid` here.
   Sema::InstantiatingTemplate Inst(
       S, Info.getLocation(), FunctionTemplate, DeducedArgs,
       Sema::CodeSynthesisContext::DeducedTemplateArgumentSubstitution, Info);
+  Sema::SFINAETrap Trap(S);
   const auto Instantiated = S.instantiateExplicitSpecifier(SubstArgs, ES);
-  if (Instantiated.isInvalid()) {
+  if (Instantiated.isInvalid() || Trap.hasErrorOccurred()) {
     Specialization->setInvalidDecl(true);
-    return clang::Sema::TDK_SubstitutionFailure;
+    return Sema::TDK_SubstitutionFailure;
   }
   SetExplicitSpecifier(Specialization, Instantiated);
-  return clang::Sema::TDK_Success;
+  return Sema::TDK_Success;
 }
 
 /// Finish template argument deduction for a function template,
@@ -3725,13 +3729,13 @@ Sema::TemplateDeductionResult Sema::FinishTemplateArgumentDeduction(
     }
   }
 
-  // We skipped the instantiation of the explicit-specifier during subst the
-  // FD before. So we try to instantiate it back if the `Specialization` is a
-  // constructor or a conversion.
+  // 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 !=
-        resolveExplicitSpecifier(*this, Specialization, SubstArgs, Info,
-                                 FunctionTemplate, DeducedArgs)) {
+    if (TDK_Success != instantiateExplicitSpecifierDeferred(
+                           *this, Specialization, SubstArgs, Info,
+                           FunctionTemplate, DeducedArgs)) {
       return TDK_SubstitutionFailure;
     }
   }

>From fd03551f26e37ba21d0f5a80ccc581bfbdf40637 Mon Sep 17 00:00:00 2001
From: letrec <liuyupei951018 at hotmail.com>
Date: Wed, 1 Nov 2023 00:52:12 +0800
Subject: [PATCH 5/7] add `IsInvalid` check

---
 clang/lib/Sema/SemaTemplateDeduction.cpp | 10 +++-------
 1 file changed, 3 insertions(+), 7 deletions(-)

diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp
index c2bfa58b2288241..e20ce8f884a9206 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -3580,16 +3580,12 @@ static Sema::TemplateDeductionResult instantiateExplicitSpecifierDeferred(
   if (!Expr->isValueDependent()) {
     return Sema::TDK_Success;
   }
-  // The `InstantiatingTemplate` here is used to restore `ActiveInstType` to
-  // `DeducedTemplateArgumentSubstitution` because ActiveInstType was set to
-  // `TemplateInstantiation` in
-  // `TemplateDeclInstantiator::InitFunctionInstantiation`. The real depth of
-  // instantiation should be the same as the depth in
-  // `FinishTemplateArgumentDeduction`.
-  // So we don't check `InstantiatingTemplate::IsValid` here.
   Sema::InstantiatingTemplate Inst(
       S, Info.getLocation(), FunctionTemplate, DeducedArgs,
       Sema::CodeSynthesisContext::DeducedTemplateArgumentSubstitution, Info);
+  if (Inst.isInvalid()) {
+    return Sema::TDK_InstantiationDepth;
+  }
   Sema::SFINAETrap Trap(S);
   const auto Instantiated = S.instantiateExplicitSpecifier(SubstArgs, ES);
   if (Instantiated.isInvalid() || Trap.hasErrorOccurred()) {

>From fe4d5f1f0131baef5a960294d3eea16a3c5d5479 Mon Sep 17 00:00:00 2001
From: letrec <liuyupei951018 at hotmail.com>
Date: Wed, 1 Nov 2023 00:57:30 +0800
Subject: [PATCH 6/7] remove braces for simple if

---
 clang/lib/Sema/SemaTemplateDeduction.cpp | 10 ++++------
 1 file changed, 4 insertions(+), 6 deletions(-)

diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp
index e20ce8f884a9206..98d6484515168b9 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -3574,18 +3574,16 @@ static Sema::TemplateDeductionResult instantiateExplicitSpecifierDeferred(
 
   ExplicitSpecifier ES = GetExplicitSpecifier(Specialization);
   Expr *const Expr = ES.getExpr();
-  if (!Expr) {
+  if (!Expr)
     return Sema::TDK_Success;
-  }
-  if (!Expr->isValueDependent()) {
+  if (!Expr->isValueDependent())
     return Sema::TDK_Success;
-  }
+
   Sema::InstantiatingTemplate Inst(
       S, Info.getLocation(), FunctionTemplate, DeducedArgs,
       Sema::CodeSynthesisContext::DeducedTemplateArgumentSubstitution, Info);
-  if (Inst.isInvalid()) {
+  if (Inst.isInvalid())
     return Sema::TDK_InstantiationDepth;
-  }
   Sema::SFINAETrap Trap(S);
   const auto Instantiated = S.instantiateExplicitSpecifier(SubstArgs, ES);
   if (Instantiated.isInvalid() || Trap.hasErrorOccurred()) {

>From aaa687ee2c1246d4800c7d2f4bf1054aaabdee08 Mon Sep 17 00:00:00 2001
From: letrec <liuyupei951018 at hotmail.com>
Date: Wed, 1 Nov 2023 01:10:30 +0800
Subject: [PATCH 7/7] fix CR comments

---
 clang/lib/Sema/SemaTemplateDeduction.cpp | 13 +++++++------
 1 file changed, 7 insertions(+), 6 deletions(-)

diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp
index 98d6484515168b9..699e0985e595b65 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -3573,10 +3573,10 @@ static Sema::TemplateDeductionResult instantiateExplicitSpecifierDeferred(
   };
 
   ExplicitSpecifier ES = GetExplicitSpecifier(Specialization);
-  Expr *const Expr = ES.getExpr();
-  if (!Expr)
+  Expr *ExplicitExpr = ES.getExpr();
+  if (!ExplicitExpr)
     return Sema::TDK_Success;
-  if (!Expr->isValueDependent())
+  if (!ExplicitExpr->isValueDependent())
     return Sema::TDK_Success;
 
   Sema::InstantiatingTemplate Inst(
@@ -3585,12 +3585,13 @@ static Sema::TemplateDeductionResult instantiateExplicitSpecifierDeferred(
   if (Inst.isInvalid())
     return Sema::TDK_InstantiationDepth;
   Sema::SFINAETrap Trap(S);
-  const auto Instantiated = S.instantiateExplicitSpecifier(SubstArgs, ES);
-  if (Instantiated.isInvalid() || Trap.hasErrorOccurred()) {
+  const ExplicitSpecifier InstantiatedES =
+      S.instantiateExplicitSpecifier(SubstArgs, ES);
+  if (InstantiatedES.isInvalid() || Trap.hasErrorOccurred()) {
     Specialization->setInvalidDecl(true);
     return Sema::TDK_SubstitutionFailure;
   }
-  SetExplicitSpecifier(Specialization, Instantiated);
+  SetExplicitSpecifier(Specialization, InstantiatedES);
   return Sema::TDK_Success;
 }
 



More information about the cfe-commits mailing list