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