On Thu, Mar 08, 2018 at 04:20:40PM -0500, Jason Merrill wrote:
> On Thu, Mar 8, 2018 at 1:08 PM, Jakub Jelinek <ja...@redhat.com> wrote:
> > 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.
> 
> I notice that convert_arg_to_ellipsis generates a pointer-typed
> expression, whereas convert_for_arg_passing generates a reference.
> Does correcting that inconsistency help?

No (though I think it is a good idea anyway).
With this patch the original testcase reports:
pr84076.C:7:16: warning: format ‘%s’ expects argument of type ‘char*’, but 
argument 2 has type ‘std::__cxx11::string&’ {aka 
‘std::__cxx11::basic_string<char>&’} [-Wformat=]
where the user expects that without the & characters and without the patch
it has * instead of &.
With the patch I've posted it is:
pr84076.C:7:16: warning: format ‘%s’ expects argument of type ‘char*’, but 
argument 2 has type ‘std::__cxx11::string’ {aka 
‘std::__cxx11::basic_string<char>’} [-Wformat=]

Similarly, the testcase included in the patch with just your patch:
pr84076.C: In function ‘void foo()’:
pr84076.C:13:21: warning: format ‘%s’ expects argument of type ‘char*’, but 
argument 2 has type ‘S&’ [-Wformat=]
   __builtin_printf ("%s\n", s); // { dg-warning "format '%s' expects argument 
of type 'char\\*', but argument 2 has type 'S'" }
                     ^~~~~~
pr84076.C:14:21: warning: format ‘%s’ expects argument of type ‘char*’, but 
argument 2 has type ‘T&’ [-Wformat=]
   __builtin_printf ("%s\n", t); // { dg-warning "format '%s' expects argument 
of type 'char\\*', but argument 2 has type 'T'" }
                     ^~~~~~
pr84076.C:15:21: warning: format ‘%s’ expects argument of type ‘char*’, but 
argument 2 has type ‘S*’ [-Wformat=]
   __builtin_printf ("%s\n", &s);// { dg-warning "format '%s' expects argument 
of type 'char\\*', but argument 2 has type 'S\\*'" }
                     ^~~~~~  ~~
pr84076.C:16:21: warning: format ‘%s’ expects argument of type ‘char*’, but 
argument 2 has type ‘T*’ [-Wformat=]
   __builtin_printf ("%s\n", &t);// { dg-warning "format '%s' expects argument 
of type 'char\\*', but argument 2 has type 'T\\*'" }
                     ^~~~~~  ~~
and with both patches:
pr84076.C: In function ‘void foo()’:
pr84076.C:13:21: warning: format ‘%s’ expects argument of type ‘char*’, but 
argument 2 has type ‘S’ [-Wformat=]
   __builtin_printf ("%s\n", s); // { dg-warning "format '%s' expects argument 
of type 'char\\*', but argument 2 has type 'S'" }
                     ^~~~~~  ~
pr84076.C:14:21: warning: format ‘%s’ expects argument of type ‘char*’, but 
argument 2 has type ‘T’ [-Wformat=]
   __builtin_printf ("%s\n", t); // { dg-warning "format '%s' expects argument 
of type 'char\\*', but argument 2 has type 'T'" }
                     ^~~~~~  ~
pr84076.C:15:21: warning: format ‘%s’ expects argument of type ‘char*’, but 
argument 2 has type ‘S*’ [-Wformat=]
   __builtin_printf ("%s\n", &s);// { dg-warning "format '%s' expects argument 
of type 'char\\*', but argument 2 has type 'S\\*'" }
                     ^~~~~~  ~~
pr84076.C:16:21: warning: format ‘%s’ expects argument of type ‘char*’, but 
argument 2 has type ‘T*’ [-Wformat=]
   __builtin_printf ("%s\n", &t);// { dg-warning "format '%s' expects argument 
of type 'char\\*', but argument 2 has type 'T\\*'" }
                     ^~~~~~  ~~

> diff --git a/gcc/cp/call.c b/gcc/cp/call.c
> index f83d51f3457..617ce18f8cd 100644
> --- a/gcc/cp/call.c
> +++ b/gcc/cp/call.c
> @@ -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.  */


        Jakub

Reply via email to