Hi,

this is in fact a Regression in the 4_8-branch too.

For the testcase, when we try to produce at instantiation time the warning about the unused parameter we re-enter the diagnostic routines because cp_convert_to_pointer doesn't get, as it should, a tf_none - the propagation breaks between convert_default_arg and tsubst_default_argument - and maybe_warn_zero_as_null_pointer_constant is called. Propagating fixes the issue.

Thanks,
Paolo.

//////////////////////
/cp
2013-07-25  Paolo Carlini  <paolo.carl...@oracle.com>

        PR c++/57981
        * decl.c (check_default_argument): Take a tsubst_flags_t parameter.
        (grokparms): Adjust.
        * parser.c (cp_parser_late_parse_one_default_arg): Likewise.
        * cvt.c (cp_convert_to_pointer, ocp_convert): Likewise.
        * pt.c (tsubst_default_argument, tsubst_default_arguments): Take
        a tsubst_flags_t parameter.
        (tsubst_decl): Adjust.
        * call.c (convert_default_arg): Likewise.
        * cp-tree.h (check_default_argument, tsubst_default_argument,
        maybe_warn_zero_as_null_pointer_constant): Update declarations.

/testsuite
2013-07-25  Paolo Carlini  <paolo.carl...@oracle.com>

        PR c++/57981
        * g++.dg/cpp0x/pr57981.C: New.
Index: cp/call.c
===================================================================
--- cp/call.c   (revision 201239)
+++ cp/call.c   (working copy)
@@ -6439,7 +6439,7 @@ convert_default_arg (tree type, tree arg, tree fn,
   push_defarg_context (fn);
 
   if (fn && DECL_TEMPLATE_INFO (fn))
-    arg = tsubst_default_argument (fn, type, arg);
+    arg = tsubst_default_argument (fn, type, arg, complain);
 
   /* Due to:
 
Index: cp/cp-tree.h
===================================================================
--- cp/cp-tree.h        (revision 201239)
+++ cp/cp-tree.h        (working copy)
@@ -5222,7 +5222,7 @@ extern tree static_fn_type                        (tree);
 extern void revert_static_member_fn            (tree);
 extern void fixup_anonymous_aggr               (tree);
 extern tree compute_array_index_type           (tree, tree, tsubst_flags_t);
-extern tree check_default_argument             (tree, tree);
+extern tree check_default_argument             (tree, tree, tsubst_flags_t);
 typedef int (*walk_namespaces_fn)              (tree, void *);
 extern int walk_namespaces                     (walk_namespaces_fn,
                                                 void *);
@@ -5504,7 +5504,8 @@ extern tree maybe_process_partial_specialization (
 extern tree most_specialized_instantiation     (tree);
 extern void print_candidates                   (tree);
 extern void instantiate_pending_templates      (int);
-extern tree tsubst_default_argument            (tree, tree, tree);
+extern tree tsubst_default_argument            (tree, tree, tree,
+                                                tsubst_flags_t);
 extern tree tsubst (tree, tree, tsubst_flags_t, tree);
 extern tree tsubst_copy_and_build              (tree, tree, tsubst_flags_t,
                                                 tree, bool, bool);
Index: cp/decl.c
===================================================================
--- cp/decl.c   (revision 201239)
+++ cp/decl.c   (working copy)
@@ -10883,7 +10883,7 @@ local_variable_p_walkfn (tree *tp, int *walk_subtr
    DECL, if there is no DECL available.  */
 
 tree
-check_default_argument (tree decl, tree arg)
+check_default_argument (tree decl, tree arg, tsubst_flags_t complain)
 {
   tree var;
   tree decl_type;
@@ -10915,13 +10915,14 @@ tree
      A default argument expression is implicitly converted to the
      parameter type.  */
   ++cp_unevaluated_operand;
-  perform_implicit_conversion_flags (decl_type, arg, tf_warning_or_error,
+  perform_implicit_conversion_flags (decl_type, arg, complain,
                                     LOOKUP_IMPLICIT);
   --cp_unevaluated_operand;
 
   if (warn_zero_as_null_pointer_constant
       && TYPE_PTR_OR_PTRMEM_P (decl_type)
       && null_ptr_cst_p (arg)
+      && (complain & tf_warning)
       && maybe_warn_zero_as_null_pointer_constant (arg, input_location))
     return nullptr_node;
 
@@ -10935,10 +10936,14 @@ tree
   var = cp_walk_tree_without_duplicates (&arg, local_variable_p_walkfn, NULL);
   if (var)
     {
-      if (DECL_NAME (var) == this_identifier)
-       permerror (input_location, "default argument %qE uses %qD", arg, var);
-      else
-       error ("default argument %qE uses local variable %qD", arg, var);
+      if (complain & tf_warning_or_error)
+       {
+         if (DECL_NAME (var) == this_identifier)
+           permerror (input_location, "default argument %qE uses %qD",
+                      arg, var);
+         else
+           error ("default argument %qE uses local variable %qD", arg, var);
+       }
       return error_mark_node;
     }
 
@@ -11089,7 +11094,7 @@ grokparms (tree parmlist, tree *parms)
          if (any_error)
            init = NULL_TREE;
          else if (init && !processing_template_decl)
-           init = check_default_argument (decl, init);
+           init = check_default_argument (decl, init, tf_warning_or_error);
        }
 
       DECL_CHAIN (decl) = decls;
Index: cp/parser.c
===================================================================
--- cp/parser.c (revision 201239)
+++ cp/parser.c (working copy)
@@ -22996,7 +22999,8 @@ cp_parser_late_parse_one_default_arg (cp_parser *p
       /* In a non-template class, check conversions now.  In a template,
         we'll wait and instantiate these as needed.  */
       if (TREE_CODE (decl) == PARM_DECL)
-       parsed_arg = check_default_argument (parmtype, parsed_arg);
+       parsed_arg = check_default_argument (parmtype, parsed_arg,
+                                            tf_warning_or_error);
       else
        {
          int flags = LOOKUP_IMPLICIT;
Index: cp/pt.c
===================================================================
--- cp/pt.c     (revision 201239)
+++ cp/pt.c     (working copy)
@@ -184,7 +184,7 @@ static int coerce_template_template_parms (tree, t
                                           tree, tree);
 static bool template_template_parm_bindings_ok_p (tree, tree);
 static int template_args_equal (tree, tree);
-static void tsubst_default_arguments (tree);
+static void tsubst_default_arguments (tree, tsubst_flags_t);
 static tree for_each_template_parm_r (tree *, int *, void *);
 static tree copy_default_args_to_explicit_spec_1 (tree, tree);
 static void copy_default_args_to_explicit_spec (tree);
@@ -9875,7 +9875,7 @@ tsubst_aggr_type (tree t,
    FN), which has the indicated TYPE.  */
 
 tree
-tsubst_default_argument (tree fn, tree type, tree arg)
+tsubst_default_argument (tree fn, tree type, tree arg, tsubst_flags_t complain)
 {
   tree saved_class_ptr = NULL_TREE;
   tree saved_class_ref = NULL_TREE;
@@ -9915,7 +9915,7 @@ tree
      stack.  */
   ++function_depth;
   arg = tsubst_expr (arg, DECL_TI_ARGS (fn),
-                    tf_warning_or_error, NULL_TREE,
+                    complain, NULL_TREE,
                     /*integral_constant_expression_p=*/false);
   --function_depth;
   pop_deferring_access_checks();
@@ -9927,12 +9927,13 @@ tree
       cp_function_chain->x_current_class_ref = saved_class_ref;
     }
 
-  if (errorcount+sorrycount > errs)
+  if (errorcount+sorrycount > errs
+      && (complain & tf_warning_or_error))
     inform (input_location,
            "  when instantiating default argument for call to %D", fn);
 
   /* Make sure the default argument is reasonable.  */
-  arg = check_default_argument (type, arg);
+  arg = check_default_argument (type, arg, complain);
 
   pop_access_scope (fn);
 
@@ -9942,7 +9943,7 @@ tree
 /* Substitute into all the default arguments for FN.  */
 
 static void
-tsubst_default_arguments (tree fn)
+tsubst_default_arguments (tree fn, tsubst_flags_t complain)
 {
   tree arg;
   tree tmpl_args;
@@ -9963,7 +9964,8 @@ static void
     if (TREE_PURPOSE (arg))
       TREE_PURPOSE (arg) = tsubst_default_argument (fn,
                                                    TREE_VALUE (arg),
-                                                   TREE_PURPOSE (arg));
+                                                   TREE_PURPOSE (arg),
+                                                   complain);
 }
 
 /* Substitute the ARGS into the T, which is a _DECL.  Return the
@@ -10323,7 +10325,7 @@ tsubst_decl (tree t, tree args, tsubst_flags_t com
            if (!member
                && !PRIMARY_TEMPLATE_P (gen_tmpl)
                && !uses_template_parms (argvec))
-             tsubst_default_arguments (r);
+             tsubst_default_arguments (r, complain);
          }
        else
          DECL_TEMPLATE_INFO (r) = NULL_TREE;
Index: testsuite/g++.dg/cpp0x/pr57981.C
===================================================================
--- testsuite/g++.dg/cpp0x/pr57981.C    (revision 0)
+++ testsuite/g++.dg/cpp0x/pr57981.C    (working copy)
@@ -0,0 +1,17 @@
+// { dg-options "-std=c++11 -Wall -Wextra" }
+
+template<class T>
+void f(T t, void* = 0)  // { dg-warning "unused parameter" }
+{
+}
+
+template<class T>
+auto g(T t) -> decltype(f(t))
+{
+  f(t);
+}
+
+int main()
+{
+  g(0);
+}

Reply via email to