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, "");
+}


        
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to