re PR c++/84076 (Warning about objects through POD mistakenly claims the object is...
authorJason Merrill <jason@redhat.com>
Fri, 9 Mar 2018 20:39:14 +0000 (21:39 +0100)
committerJakub Jelinek <jakub@gcc.gnu.org>
Fri, 9 Mar 2018 20:39:14 +0000 (21:39 +0100)
PR c++/84076
* call.c (convert_arg_to_ellipsis): Instead of cp_build_addr_expr
build ADDR_EXPR with REFERENCE_TYPE.
(build_over_call): For purposes of check_function_arguments, if
argarray[j] is ADDR_EXPR with REFERENCE_TYPE created above, use
its operand rather than the argument itself.

* g++.dg/warn/Wformat-2.C: New test.

From-SVN: r258397

gcc/cp/ChangeLog
gcc/cp/call.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/warn/Wformat-2.C [new file with mode: 0644]

index ae980fd..29121ce 100644 (file)
@@ -1,3 +1,13 @@
+2018-03-09  Jason Merrill  <jason@redhat.com>
+           Jakub Jelinek  <jakub@redhat.com>
+
+       PR c++/84076
+       * call.c (convert_arg_to_ellipsis): Instead of cp_build_addr_expr
+       build ADDR_EXPR with REFERENCE_TYPE.
+       (build_over_call): For purposes of check_function_arguments, if
+       argarray[j] is ADDR_EXPR with REFERENCE_TYPE created above, use
+       its operand rather than the argument itself.
+
 2018-03-09  Jakub Jelinek  <jakub@redhat.com>
 
        PR c++/84724
index fd6528f..17cd1c4 100644 (file)
@@ -7209,7 +7209,7 @@ convert_arg_to_ellipsis (tree arg, tsubst_flags_t complain)
                     "passing objects of non-trivially-copyable "
                     "type %q#T through %<...%> is conditionally supported",
                     arg_type);
-         return cp_build_addr_expr (arg, complain);
+         return build1 (ADDR_EXPR, build_reference_type (arg_type), arg);
        }
       /* Build up a real lvalue-to-rvalue conversion in case the
         copy constructor is trivial but not callable.  */
@@ -8018,7 +8018,15 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
       tree *fargs = (!nargs ? argarray
                            : (tree *) alloca (nargs * sizeof (tree)));
       for (j = 0; j < nargs; j++)
-       fargs[j] = maybe_constant_value (argarray[j]);
+       {
+         /* For -Wformat undo the implicit passing by hidden reference
+            done by convert_arg_to_ellipsis.  */
+         if (TREE_CODE (argarray[j]) == ADDR_EXPR
+             && TREE_CODE (TREE_TYPE (argarray[j])) == REFERENCE_TYPE)
+           fargs[j] = TREE_OPERAND (argarray[j], 0);
+         else
+           fargs[j] = maybe_constant_value (argarray[j]);
+       }
 
       warned_p = check_function_arguments (input_location, fn, TREE_TYPE (fn),
                                           nargs, fargs, NULL);
index 3b3f44f..a8ef381 100644 (file)
@@ -1,5 +1,8 @@
 2018-03-09  Jakub Jelinek  <jakub@redhat.com>
 
+       PR c++/84076
+       * g++.dg/warn/Wformat-2.C: New test.
+
        PR c++/84767
        * g++.dg/ext/vla18.C: New test.
 
diff --git a/gcc/testsuite/g++.dg/warn/Wformat-2.C b/gcc/testsuite/g++.dg/warn/Wformat-2.C
new file mode 100644 (file)
index 0000000..ff8b54b
--- /dev/null
@@ -0,0 +1,17 @@
+// PR c++/84076
+// { dg-do compile }
+// { dg-options "-Wformat" }
+
+struct S { ~S (); };
+struct T { T (); T (const T &); };
+
+void
+foo ()
+{
+  S s;
+  T t;
+  __builtin_printf ("%s\n", s);        // { dg-warning "format '%s' expects argument of type 'char\\*', but argument 2 has type 'S'" }
+  __builtin_printf ("%s\n", t);        // { dg-warning "format '%s' expects argument of type 'char\\*', but argument 2 has type 'T'" }
+  __builtin_printf ("%s\n", &s);// { dg-warning "format '%s' expects argument of type 'char\\*', but argument 2 has type 'S\\*'" }
+  __builtin_printf ("%s\n", &t);// { dg-warning "format '%s' expects argument of type 'char\\*', but argument 2 has type 'T\\*'" }
+}