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.

//////////////////////////////
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 = { };

Reply via email to