This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[C++ PATCH] For -Wformat purposes use ellipsis args before class to pointer to class conversion (PR c++/84076)


Hi!

The reporter complains that -Wformat incorrectly reports std::string* passed
to "%s" format rather than std::string, which is what the user did.

This transformation of non-trivial copy init or dtor classes in ellipsis is
done by convert_arg_to_ellipsis; that function does many changes and all
but this one look desirable for the -Wnonnull/-Wformat/-Wsentinel/-Wrestrict
warnings.  We prepare a special argument vector in any case, so this patch
just arranges to undo what convert_arg_to_ellipsis did for the classes.
I think -Wnonnull shouldn't care, because when passing such a class by
value, it will be non-NULL (and -Wnonnull looks only for literal NULLs
anyway), -Wrestrict only cares about named arguments and -Wsentinel only
cares about NULL arguments passed to ellipsis.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

2018-03-08  Jakub Jelinek  <jakub@redhat.com>

	PR c++/84076
	* call.c (build_over_call): For purposes of check_function_arguments,
	undo convert_arg_to_ellipsis passing of classes with non-trivial
	copy ctor or dtor by invisible reference.

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

--- gcc/cp/call.c.jj	2018-03-07 22:51:58.698478669 +0100
+++ gcc/cp/call.c	2018-03-08 10:58:58.157373982 +0100
@@ -7967,6 +7967,8 @@ build_over_call (struct z_candidate *can
     }
 
   /* Ellipsis */
+  int ellipsis_first = j;
+  unsigned ellipsis_bias = arg_index - j;
   int magic = magic_varargs_p (fn);
   for (; arg_index < vec_safe_length (args); ++arg_index)
     {
@@ -8014,7 +8016,22 @@ build_over_call (struct z_candidate *can
       tree *fargs = (!nargs ? argarray
 			    : (tree *) alloca (nargs * sizeof (tree)));
       for (j = 0; j < nargs; j++)
-	fargs[j] = maybe_constant_value (argarray[j]);
+	{
+	  /* For the purposes of check_function_arguments, undo the implicit
+	     passing of classes with non-trivial copy ctor or dtor in ellipsis
+	     by invisible reference.  */
+	  if (j >= ellipsis_first && POINTER_TYPE_P (TREE_TYPE (argarray[j])))
+	    {
+	      tree orig_type = TREE_TYPE ((*args)[ellipsis_bias + j]);
+	      if (type_has_nontrivial_copy_init (orig_type)
+		  || TYPE_HAS_NONTRIVIAL_DESTRUCTOR (orig_type))
+		{
+		  fargs[j] = (*args)[ellipsis_bias + j];
+		  continue;
+		}
+	    }
+	  fargs[j] = maybe_constant_value (argarray[j]);
+	}
 
       warned_p = check_function_arguments (input_location, fn, TREE_TYPE (fn),
 					   nargs, fargs, NULL);
--- gcc/testsuite/g++.dg/warn/Wformat-2.C.jj	2018-03-08 11:05:27.269422301 +0100
+++ gcc/testsuite/g++.dg/warn/Wformat-2.C	2018-03-08 11:04:52.915418031 +0100
@@ -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\\*'" }
+}

	Jakub


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]