From: Hans Wennborg Date: Wed, 18 Jan 2017 04:36:52 +0000 (+0000) Subject: Merging r292183: X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=4077c4b193467c625c86757e456f96c45d65e608;p=clang Merging r292183: ------------------------------------------------------------------------ r292183 | rsmith | 2017-01-16 18:14:37 -0800 (Mon, 16 Jan 2017) | 14 lines Partial revert of r290511. The rules around typechecking deduced template arguments during partial ordering are not clear, and while the prior behavior does not seem to be correct (it doesn't follow the general model of partial ordering where each template parameter is replaced by a non-dependent but unique value), the new behavior is also not clearly right and breaks some existing idioms. The new behavior is retained for dealing with non-type template parameters with 'auto' types, as without it even the most basic uses of that feature don't work. We can revisit this once CWG has come to an agreement on how partial ordering with 'auto' non-type template parameters is supposed to work. ------------------------------------------------------------------------ git-svn-id: https://llvm.org/svn/llvm-project/cfe/branches/release_40@292338 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index 8ad5b5951e..ad1e89a0ca 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -5127,18 +5127,22 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, if (CTAK == CTAK_Deduced && !Context.hasSameType(ParamType.getNonLValueExprType(Context), Arg->getType())) { - // C++ [temp.deduct.type]p17: (DR1770) - // If P has a form that contains , and if the type of i differs from - // the type of the corresponding template parameter of the template named - // by the enclosing simple-template-id, deduction fails. - // - // Note that CTAK will be CTAK_DeducedFromArrayBound if the form was [i] - // rather than . - // - // FIXME: We interpret the 'i' here as referring to the expression - // denoting the non-type template parameter rather than the parameter - // itself, and so strip off references before comparing types. It's - // not clear how this is supposed to work for references. + // FIXME: If either type is dependent, we skip the check. This isn't + // correct, since during deduction we're supposed to have replaced each + // template parameter with some unique (non-dependent) placeholder. + // FIXME: If the argument type contains 'auto', we carry on and fail the + // type check in order to force specific types to be more specialized than + // 'auto'. It's not clear how partial ordering with 'auto' is supposed to + // work. + if ((ParamType->isDependentType() || Arg->isTypeDependent()) && + !Arg->getType()->getContainedAutoType()) { + Converted = TemplateArgument(Arg); + return Arg; + } + // FIXME: This attempts to implement C++ [temp.deduct.type]p17. Per DR1770, + // we should actually be checking the type of the template argument in P, + // not the type of the template argument deduced from A, against the + // template parameter type. Diag(StartLoc, diag::err_deduced_non_type_template_arg_type_mismatch) << Arg->getType() << ParamType.getUnqualifiedType(); diff --git a/test/SemaTemplate/class-template-spec.cpp b/test/SemaTemplate/class-template-spec.cpp index 518ec78e6f..00e03ef61e 100644 --- a/test/SemaTemplate/class-template-spec.cpp +++ b/test/SemaTemplate/class-template-spec.cpp @@ -207,19 +207,19 @@ namespace NTTPTypeVsPartialOrder { struct X { typedef int value_type; }; template struct Y { typedef T value_type; }; - template struct A; // expected-note {{template}} + template struct A; template struct A {}; - template struct A, N> {}; // expected-error {{not more specialized}} expected-note {{'T' vs 'typename Y::value_type'}} + template struct A, N> {}; A ax; A, 0> ay; - template struct B; // expected-note {{template}} - template struct B<0, T, N>; // expected-note {{matches}} + template struct B; + template struct B<0, T, N>; template struct B<0, X, N> {}; - template struct B<0, Y, N> {}; // expected-error {{not more specialized}} expected-note {{'T' vs 'typename Y::value_type'}} expected-note {{matches}} + template struct B<0, Y, N> {}; B<0, X, 0> bx; - B<0, Y, 0> by; // expected-error {{ambiguous}} + B<0, Y, 0> by; } namespace DefaultArgVsPartialSpec { diff --git a/test/SemaTemplate/partial-order.cpp b/test/SemaTemplate/partial-order.cpp new file mode 100644 index 0000000000..0a151de390 --- /dev/null +++ b/test/SemaTemplate/partial-order.cpp @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 -std=c++1z %s -verify + +// expected-no-diagnostics + +namespace hana_enable_if_idiom { + template struct A {}; + template> struct B; + template struct B> {}; + template struct B> {}; + struct C { + static const bool value = true; + }; + B b; +} diff --git a/test/SemaTemplate/temp_arg_nontype.cpp b/test/SemaTemplate/temp_arg_nontype.cpp index 27a0a03f84..5b72b8c654 100644 --- a/test/SemaTemplate/temp_arg_nontype.cpp +++ b/test/SemaTemplate/temp_arg_nontype.cpp @@ -370,13 +370,13 @@ namespace PR17696 { } namespace partial_order_different_types { - // These are unordered because the type of the final argument doesn't match. - template struct A; // expected-note {{here}} - template struct A<0, N, T, U, V> {}; // expected-note {{matches}} - template struct A<0, 0, T, U, V> {}; // expected-note {{matches}} - // expected-error@-1 {{not more specialized than the primary}} - // expected-note@-2 {{deduced non-type template argument does not have the same type as the corresponding template parameter ('U' vs 'type-parameter-0-0')}} - A<0, 0, int, int, 0> a; // expected-error {{ambiguous partial specializations}} + template struct A; + template struct A<0, N, T, U, V>; // expected-note {{matches}} + // FIXME: It appears that this partial specialization should be ill-formed as + // it is not more specialized than the primary template. V is not deducible + // because it does not have the same type as the corresponding parameter. + template struct A<0, N, T, U, V> {}; // expected-note {{matches}} + A<0, 0, int, int, 0> a; // expected-error {{ambiguous}} } namespace partial_order_references { @@ -434,7 +434,7 @@ namespace dependent_nested_partial_specialization { template struct E { template struct F; // expected-note {{template}} - template struct F {}; // expected-error {{not more specialized than the primary}} expected-note {{does not have the same type}} + template struct F {}; // expected-error {{not more specialized than the primary}} }; E::F e1; // expected-note {{instantiation of}} } diff --git a/test/SemaTemplate/temp_arg_template_cxx1z.cpp b/test/SemaTemplate/temp_arg_template_cxx1z.cpp index aa517c3285..703935dcd5 100644 --- a/test/SemaTemplate/temp_arg_template_cxx1z.cpp +++ b/test/SemaTemplate/temp_arg_template_cxx1z.cpp @@ -79,13 +79,13 @@ namespace Auto { TInt ia; TInt iap; // expected-error {{different template parameters}} - TInt ida; // FIXME expected-error {{different template parameters}} + TInt ida; TInt ii; TInt iip; // expected-error {{different template parameters}} TIntPtr ipa; TIntPtr ipap; - TIntPtr ipda; // FIXME expected-error {{different template parameters}} + TIntPtr ipda; TIntPtr ipi; // expected-error {{different template parameters}} TIntPtr ipip; @@ -114,6 +114,6 @@ namespace Auto { int n; template struct SubstFailure; - TInt isf; // expected-error {{different template parameters}} - TIntPtr ipsf; // expected-error {{different template parameters}} + TInt isf; // FIXME: this should be ill-formed + TIntPtr ipsf; }