diff mbox

[C++] PR 53856

Message ID 5612AA65.1080308@oracle.com
State New
Headers show

Commit Message

Paolo Carlini Oct. 5, 2015, 4:50 p.m. UTC
Hi,

On 09/24/2015 03:24 PM, Jason Merrill wrote:
> On 09/22/2015 03:31 PM, Paolo Carlini wrote:
>>      msg = G_("default template arguments may not be used in "
>>           "partial specializations");
>> +  else if (current_class_type && !CLASSTYPE_IS_TEMPLATE 
>> (current_class_type))
>> +    /* Per [temp.param]/9, "A default template-argument shall not be
>> +       specified in the template-parameter-lists of the definition of
>> +       a member of a class template that appears outside of the 
>> member's
>> +       class.", thus if we aren't handling a member of a class template
>> +       there is no need to examine the parameters.  */
>> +    last_level_to_check = template_class_depth (current_class_type) 
>> + 1;
>>    else
>>      msg = G_("default argument for template parameter for class 
>> enclosing %qD");
>
> Why not handle this below, with the other code that sets 
> last_level_to_check?
First, sorry for late replying (a few days of vacations)...

In general, the rationale behind changing that earlier conditional was 
restricting it to the specific case at issue and avoid affecting other 
default-related diagnostic. That said, the patch was subtly wrong 
anyway, because relied on msg remaining zero for the second call of 
check_default_tmpl_args for defarg20.C, thus the testcase was correctly 
accepted but with a zeroed default.

Today, it occurred to me that maybe we can even more directly avoid 
emitting a meaningless "default argument for template parameter for 
class enclosing" for an enclosing class which isn't a template. Thus the 
below, which definitely passes the testsuite and also complexified 
variants (deeper nestings) of the new testcases. Does it make sense to you?

Thanks,
Paolo.

//////////////////////////////

Comments

Jason Merrill Oct. 5, 2015, 5:10 p.m. UTC | #1
On 10/05/2015 12:50 PM, Paolo Carlini wrote:
> +  else if (!current_class_type || CLASSTYPE_IS_TEMPLATE (current_class_type))
> +    msg = G_("default argument for template parameter for class enclosing %qD");

Why would this be right when !current_class_type?

Jason
diff mbox

Patch

Index: cp/pt.c
===================================================================
--- cp/pt.c	(revision 228467)
+++ cp/pt.c	(working copy)
@@ -4940,8 +4940,15 @@  check_default_tmpl_args (tree decl, tree parms, bo
   else if (is_partial)
     msg = G_("default template arguments may not be used in "
 	     "partial specializations");
+  else if (!current_class_type || CLASSTYPE_IS_TEMPLATE (current_class_type))
+    msg = G_("default argument for template parameter for class enclosing %qD");
   else
-    msg = G_("default argument for template parameter for class enclosing %qD");
+    /* Per [temp.param]/9, "A default template-argument shall not be
+       specified in the template-parameter-lists of the definition of
+       a member of a class template that appears outside of the member's
+       class.", thus if we aren't handling a member of a class template
+       there is no need to examine the parameters.  */
+    return true;
 
   if (current_class_type && TYPE_BEING_DEFINED (current_class_type))
     /* If we're inside a class definition, there's no need to
Index: testsuite/g++.dg/template/defarg19.C
===================================================================
--- testsuite/g++.dg/template/defarg19.C	(revision 0)
+++ testsuite/g++.dg/template/defarg19.C	(working copy)
@@ -0,0 +1,15 @@ 
+// PR c++/53856
+
+template<typename T>
+struct A
+{
+  struct B;
+};
+
+template<typename T = int>
+struct A<T>::B  // { dg-error "default argument" }
+{
+  int i;
+};
+
+A<int>::B b = { };
Index: testsuite/g++.dg/template/defarg20.C
===================================================================
--- testsuite/g++.dg/template/defarg20.C	(revision 0)
+++ testsuite/g++.dg/template/defarg20.C	(working copy)
@@ -0,0 +1,15 @@ 
+// PR c++/53856
+
+struct A
+{
+  template<typename T>
+  struct B;
+};
+
+template<typename T = int>
+struct A::B
+{
+  int i;
+};
+
+A::B<int> b = { };