[clang] 6bbfa0f - When performing template argument deduction to select a partial

Richard Smith via cfe-commits cfe-commits at lists.llvm.org
Wed May 5 14:47:29 PDT 2021


Author: Richard Smith
Date: 2021-05-05T14:47:18-07:00
New Revision: 6bbfa0fd408e81055c360c2e059554dd76fd7f09

URL: https://github.com/llvm/llvm-project/commit/6bbfa0fd408e81055c360c2e059554dd76fd7f09
DIFF: https://github.com/llvm/llvm-project/commit/6bbfa0fd408e81055c360c2e059554dd76fd7f09.diff

LOG: When performing template argument deduction to select a partial
specialization while substituting a partial template parameter pack,
don't try to extend the existing deduction.

This caused us to select the wrong partial specialization in some rare
cases. A recent change to libc++ caused this to happen in practice for
code using std::conjunction.

Added: 
    

Modified: 
    clang/lib/Sema/SemaTemplateDeduction.cpp
    clang/test/SemaTemplate/partial-spec-instantiate.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp
index 7d548e4f8dee1..3c66c8eeda8b9 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -3079,6 +3079,10 @@ Sema::DeduceTemplateArguments(ClassTemplatePartialSpecializationDecl *Partial,
       *this, Sema::ExpressionEvaluationContext::Unevaluated);
   SFINAETrap Trap(*this);
 
+  // This deduction has no relation to any outer instantiation we might be
+  // performing.
+  LocalInstantiationScope InstantiationScope(*this);
+
   SmallVector<DeducedTemplateArgument, 4> Deduced;
   Deduced.resize(Partial->getTemplateParameters()->size());
   if (TemplateDeductionResult Result
@@ -3127,6 +3131,10 @@ Sema::DeduceTemplateArguments(VarTemplatePartialSpecializationDecl *Partial,
       *this, Sema::ExpressionEvaluationContext::Unevaluated);
   SFINAETrap Trap(*this);
 
+  // This deduction has no relation to any outer instantiation we might be
+  // performing.
+  LocalInstantiationScope InstantiationScope(*this);
+
   SmallVector<DeducedTemplateArgument, 4> Deduced;
   Deduced.resize(Partial->getTemplateParameters()->size());
   if (TemplateDeductionResult Result = ::DeduceTemplateArguments(

diff  --git a/clang/test/SemaTemplate/partial-spec-instantiate.cpp b/clang/test/SemaTemplate/partial-spec-instantiate.cpp
index 3b7cee88c42ec..369ff69aa3756 100644
--- a/clang/test/SemaTemplate/partial-spec-instantiate.cpp
+++ b/clang/test/SemaTemplate/partial-spec-instantiate.cpp
@@ -112,3 +112,25 @@ namespace InstantiationDependent {
   _Static_assert(!A<X>::specialized, "");
   _Static_assert(A<Y>::specialized, "");
 }
+
+namespace IgnorePartialSubstitution {
+  template <typename... T> struct tuple {}; // expected-warning 0-1{{extension}}
+  template <typename> struct IsTuple {
+    enum { value = false };
+  };
+  template <typename... Us> struct IsTuple<tuple<Us...> > { // expected-warning 0-1{{extension}}
+    enum { value = true };
+  };
+
+  template <bool...> using ignore = void; // expected-warning 0-2{{extension}}
+  template <class... Pred> ignore<Pred::value...> helper(); // expected-warning 0-1{{extension}}
+
+  using S = IsTuple<tuple<int> >; // expected-warning 0-1{{extension}}
+
+  // This used to pick the primary template, because we got confused and
+  // thought that template parameter 0 was the current partially-substituted
+  // pack (from `helper`) during the deduction for the partial specialization.
+  void f() { helper<S>(); }
+
+  _Static_assert(S::value, "");
+}


        


More information about the cfe-commits mailing list