diff mbox

[C++] PR 65370

Message ID 54FF12D4.3060603@oracle.com
State New
Headers show

Commit Message

Paolo Carlini March 10, 2015, 3:50 p.m. UTC
Hi,

my fix for c++/15339 caused this regression, where we now reject the 
below valid testcase. I think we can handle the problem by adding an 
early return to check_redeclaration_no_default_args.

Tested x86_64-linux.

Thanks,
Paolo.

///////////////////////
/cp
2015-03-10  Paolo Carlini  <paolo.carlini@oracle.com>

	PR c++/65370
	* decl.c (check_redeclaration_no_default_args): Avoid spurious
	errors for member template functions of specialized class templates.

/testsuite
2015-03-10  Paolo Carlini  <paolo.carlini@oracle.com>

	PR c++/65370
	* g++.dg/other/default11.C: New.

Comments

Jason Merrill March 10, 2015, 4:19 p.m. UTC | #1
On 03/10/2015 11:50 AM, Paolo Carlini wrote:
> +  /* Don't get fooled by, eg:
> +
> +     template <typename> class C
> +     {
> +       template <typename U>
> +       C(const C<U>&, bool = false);
> +     };
> +
> +     template <>
> +     template <typename U>
> +     C<int>::C(const C<U>&, bool);  */
> +
> +  if (DECL_FUNCTION_MEMBER_P (decl)
> +      && CLASSTYPE_SPECIALIZATION_OF_PRIMARY_TEMPLATE_P (DECL_CONTEXT (decl)))
> +    return;

Wouldn't this also allow

template<>
template<typename U>
C<int>::C(const C<U>&, bool = false);

?

Would it work to avoid calling this function if the DECL_SOURCE_LOCATION 
of the new decl matches the location of the old decl?

Jason
Paolo Carlini March 10, 2015, 5:03 p.m. UTC | #2
Hi,

On 03/10/2015 05:19 PM, Jason Merrill wrote:
> On 03/10/2015 11:50 AM, Paolo Carlini wrote:
>> +  /* Don't get fooled by, eg:
>> +
>> +     template <typename> class C
>> +     {
>> +       template <typename U>
>> +       C(const C<U>&, bool = false);
>> +     };
>> +
>> +     template <>
>> +     template <typename U>
>> +     C<int>::C(const C<U>&, bool);  */
>> +
>> +  if (DECL_FUNCTION_MEMBER_P (decl)
>> +      && CLASSTYPE_SPECIALIZATION_OF_PRIMARY_TEMPLATE_P 
>> (DECL_CONTEXT (decl)))
>> +    return;
>
> Wouldn't this also allow
>
> template<>
> template<typename U>
> C<int>::C(const C<U>&, bool = false);
>
> ?
Good question, but we don't have this issue, because for that we emit 
anyway:

65370.C:11:36: error: default argument specified in explicit 
specialization [-fpermissive]
  C<int>::C(const C<U>&, bool = false);

nothing changes about that kind of testcase, usual behavior.

Thanks,
Paolo.
Jason Merrill March 10, 2015, 6:10 p.m. UTC | #3
On 03/10/2015 01:03 PM, Paolo Carlini wrote:
> Good question, but we don't have this issue, because for that we emit
> anyway:
>
> 65370.C:11:36: error: default argument specified in explicit
> specialization [-fpermissive]
>   C<int>::C(const C<U>&, bool = false);
>
> nothing changes about that kind of testcase, usual behavior.

Ah.  So here we can ignore any template instantiation or specialization, 
with a comment that check_explicit_specialization will handle them.  But 
I suspect that checking the decl itself will be better; I would expect 
checking the context to lead you to accept

template<> class C<int> {
   template <typename U>
   C(const C<U>&, bool);
};

template <typename U> C<int>::C(const C<U>&, bool = false);

Since here C<int> is a specialization of C, but the constructor is not 
itself a partial instantiation.

Jason
diff mbox

Patch

Index: cp/decl.c
===================================================================
--- cp/decl.c	(revision 221317)
+++ cp/decl.c	(working copy)
@@ -1271,6 +1271,22 @@  check_redeclaration_no_default_args (tree decl)
 {
   gcc_assert (DECL_DECLARES_FUNCTION_P (decl));
 
+  /* Don't get fooled by, eg:
+
+     template <typename> class C
+     {
+       template <typename U>
+       C(const C<U>&, bool = false);
+     };
+
+     template <>
+     template <typename U>
+     C<int>::C(const C<U>&, bool);  */
+
+  if (DECL_FUNCTION_MEMBER_P (decl)
+      && CLASSTYPE_SPECIALIZATION_OF_PRIMARY_TEMPLATE_P (DECL_CONTEXT (decl)))
+    return;
+
   for (tree t = FUNCTION_FIRST_USER_PARMTYPE (decl);
        t && t != void_list_node; t = TREE_CHAIN (t))
     if (TREE_PURPOSE (t))
Index: testsuite/g++.dg/other/default11.C
===================================================================
--- testsuite/g++.dg/other/default11.C	(revision 0)
+++ testsuite/g++.dg/other/default11.C	(working copy)
@@ -0,0 +1,11 @@ 
+// PR c++/65370
+
+template <typename> class C
+{
+  template <typename U>
+  C(const C<U>&, bool = false);
+};
+
+template <>
+template <typename U>
+C<int>::C(const C<U>&, bool);