diff mbox

PR c++/80544 strip cv-quals from cast results

Message ID 20170525100700.GU12306@redhat.com
State New
Headers show

Commit Message

Jonathan Wakely May 25, 2017, 10:07 a.m. UTC
On 25/05/17 10:05 +0200, Andreas Schwab wrote:
>../../gcc/ada/gcc-interface/utils2.c: In function 'int compare_elmt_bitpos(const void*, const void*)':
>../../gcc/ada/gcc-interface/utils2.c:1937:73: error: type qualifiers ignored on cast result type [-Werror=ignored-qualifiers]
>   const constructor_elt * const elmt1 = (const constructor_elt * const) rt1;
>                                                                         ^~~
>../../gcc/ada/gcc-interface/utils2.c:1938:73: error: type qualifiers ignored on cast result type [-Werror=ignored-qualifiers]
>   const constructor_elt * const elmt2 = (const constructor_elt * const) rt2;

I'm testing this obvious fix.

Comments

Jonathan Wakely May 25, 2017, 2:02 p.m. UTC | #1
On 25/05/17 11:07 +0100, Jonathan Wakely wrote:
>On 25/05/17 10:05 +0200, Andreas Schwab wrote:
>>../../gcc/ada/gcc-interface/utils2.c: In function 'int compare_elmt_bitpos(const void*, const void*)':
>>../../gcc/ada/gcc-interface/utils2.c:1937:73: error: type qualifiers ignored on cast result type [-Werror=ignored-qualifiers]
>>  const constructor_elt * const elmt1 = (const constructor_elt * const) rt1;
>>                                                                        ^~~
>>../../gcc/ada/gcc-interface/utils2.c:1938:73: error: type qualifiers ignored on cast result type [-Werror=ignored-qualifiers]
>>  const constructor_elt * const elmt2 = (const constructor_elt * const) rt2;
>
>I'm testing this obvious fix.

Committed as r248458 because it gets bootstrap past the error above,
although now Ada fails for me with:

/home/jwakely/src/gcc/bootstrap/./gcc/xgcc -B/home/jwakely/src/gcc/bootstrap/./gcc/ -B/usr/local/x86_64-pc-linux-gnu/bin/ -B/usr/local/x86_64-pc-linux-gnu/lib/ -isystem /usr/local/x86_64-pc-linux-gnu/include -isystem /usr/local/x86_64-pc-linux-gnu/sys-include    -c -g -O2 -m32 -fpic  -W -Wall -gnatpg -nostdinc -m32  s-regpat.adb -o s-regpat.o

raised STORAGE_ERROR : stack overflow or erroneous memory access
../gcc-interface/Makefile:296: recipe for target 's-regpat.o' failed


>diff --git a/gcc/ada/gcc-interface/utils2.c b/gcc/ada/gcc-interface/utils2.c
>index fc6f1b8..cd37791 100644
>--- a/gcc/ada/gcc-interface/utils2.c
>+++ b/gcc/ada/gcc-interface/utils2.c
>@@ -1934,8 +1934,8 @@ build_call_raise_range (int msg, Node_Id gnat_node, char kind,
> static int
> compare_elmt_bitpos (const PTR rt1, const PTR rt2)
> {
>-  const constructor_elt * const elmt1 = (const constructor_elt * const) rt1;
>-  const constructor_elt * const elmt2 = (const constructor_elt * const) rt2;
>+  const constructor_elt * const elmt1 = (const constructor_elt *) rt1;
>+  const constructor_elt * const elmt2 = (const constructor_elt *) rt2;
>   const_tree const field1 = elmt1->index;
>   const_tree const field2 = elmt2->index;
>   const int ret
Jakub Jelinek May 25, 2017, 2:11 p.m. UTC | #2
On Thu, May 25, 2017 at 03:02:42PM +0100, Jonathan Wakely wrote:
> On 25/05/17 11:07 +0100, Jonathan Wakely wrote:
> > On 25/05/17 10:05 +0200, Andreas Schwab wrote:
> > > ../../gcc/ada/gcc-interface/utils2.c: In function 'int compare_elmt_bitpos(const void*, const void*)':
> > > ../../gcc/ada/gcc-interface/utils2.c:1937:73: error: type qualifiers ignored on cast result type [-Werror=ignored-qualifiers]
> > >  const constructor_elt * const elmt1 = (const constructor_elt * const) rt1;
> > >                                                                        ^~~
> > > ../../gcc/ada/gcc-interface/utils2.c:1938:73: error: type qualifiers ignored on cast result type [-Werror=ignored-qualifiers]
> > >  const constructor_elt * const elmt2 = (const constructor_elt * const) rt2;
> > 
> > I'm testing this obvious fix.
> 
> Committed as r248458 because it gets bootstrap past the error above,
> although now Ada fails for me with:
> 
> /home/jwakely/src/gcc/bootstrap/./gcc/xgcc -B/home/jwakely/src/gcc/bootstrap/./gcc/ -B/usr/local/x86_64-pc-linux-gnu/bin/ -B/usr/local/x86_64-pc-linux-gnu/lib/ -isystem /usr/local/x86_64-pc-linux-gnu/include -isystem /usr/local/x86_64-pc-linux-gnu/sys-include    -c -g -O2 -m32 -fpic  -W -Wall -gnatpg -nostdinc -m32  s-regpat.adb -o s-regpat.o
> 
> raised STORAGE_ERROR : stack overflow or erroneous memory access
> ../gcc-interface/Makefile:296: recipe for target 's-regpat.o' failed
> 
> 
> > diff --git a/gcc/ada/gcc-interface/utils2.c b/gcc/ada/gcc-interface/utils2.c
> > index fc6f1b8..cd37791 100644
> > --- a/gcc/ada/gcc-interface/utils2.c
> > +++ b/gcc/ada/gcc-interface/utils2.c
> > @@ -1934,8 +1934,8 @@ build_call_raise_range (int msg, Node_Id gnat_node, char kind,
> > static int
> > compare_elmt_bitpos (const PTR rt1, const PTR rt2)
> > {
> > -  const constructor_elt * const elmt1 = (const constructor_elt * const) rt1;
> > -  const constructor_elt * const elmt2 = (const constructor_elt * const) rt2;
> > +  const constructor_elt * const elmt1 = (const constructor_elt *) rt1;
> > +  const constructor_elt * const elmt2 = (const constructor_elt *) rt2;
> >   const_tree const field1 = elmt1->index;
> >   const_tree const field2 = elmt2->index;
> >   const int ret

So, what can one do with typeof or similar to avoid the warning?

void
foo (const void *p)
{
  const int *const q = (const int *const) p;
  typeof (q) r = (typeof (q)) p;
  (void) q;
  (void) r;
}

AFAIK typeof doesn't strip the toplevel qualifiers and I see current trunk
warns even about the cast in r initialization.  Similarly to what has been
noted recently in another (C) PR, it would be nice if we had toplevel cv
stripping variant of typeof or some special builtin that could wrap
typeof or some type and could be used in places where typeof can,
  __strip_cv (typeof (q)) = (__strip_cv (typeof (q))) p;
or
  typeof (q) = (__strip_cv (typeof (q))) p;
or
  __strip_cv (const int *const) z;
where the last one would be effectively
  const int *z;

	Jakub
Jakub Jelinek May 25, 2017, 2:14 p.m. UTC | #3
On Thu, May 25, 2017 at 04:11:19PM +0200, Jakub Jelinek wrote:
> So, what can one do with typeof or similar to avoid the warning?
> 
> void
> foo (const void *p)
> {
>   const int *const q = (const int *const) p;
>   typeof (q) r = (typeof (q)) p;
>   (void) q;
>   (void) r;
> }
> 
> AFAIK typeof doesn't strip the toplevel qualifiers and I see current trunk
> warns even about the cast in r initialization.  Similarly to what has been
> noted recently in another (C) PR, it would be nice if we had toplevel cv
> stripping variant of typeof or some special builtin that could wrap
> typeof or some type and could be used in places where typeof can,
>   __strip_cv (typeof (q)) = (__strip_cv (typeof (q))) p;
> or
>   typeof (q) = (__strip_cv (typeof (q))) p;
> or
>   __strip_cv (const int *const) z;
> where the last one would be effectively
>   const int *z;

I guess in C++ one can use
  typeof (q) r = (remove_cv <typeof (q)>::type) p;
or something similar, but in C there is nothing like that.

	Jakub
Marek Polacek May 25, 2017, 2:23 p.m. UTC | #4
On Thu, May 25, 2017 at 04:11:19PM +0200, Jakub Jelinek wrote:
> On Thu, May 25, 2017 at 03:02:42PM +0100, Jonathan Wakely wrote:
> > On 25/05/17 11:07 +0100, Jonathan Wakely wrote:
> > > On 25/05/17 10:05 +0200, Andreas Schwab wrote:
> > > > ../../gcc/ada/gcc-interface/utils2.c: In function 'int compare_elmt_bitpos(const void*, const void*)':
> > > > ../../gcc/ada/gcc-interface/utils2.c:1937:73: error: type qualifiers ignored on cast result type [-Werror=ignored-qualifiers]
> > > >  const constructor_elt * const elmt1 = (const constructor_elt * const) rt1;
> > > >                                                                        ^~~
> > > > ../../gcc/ada/gcc-interface/utils2.c:1938:73: error: type qualifiers ignored on cast result type [-Werror=ignored-qualifiers]
> > > >  const constructor_elt * const elmt2 = (const constructor_elt * const) rt2;
> > > 
> > > I'm testing this obvious fix.
> > 
> > Committed as r248458 because it gets bootstrap past the error above,
> > although now Ada fails for me with:
> > 
> > /home/jwakely/src/gcc/bootstrap/./gcc/xgcc -B/home/jwakely/src/gcc/bootstrap/./gcc/ -B/usr/local/x86_64-pc-linux-gnu/bin/ -B/usr/local/x86_64-pc-linux-gnu/lib/ -isystem /usr/local/x86_64-pc-linux-gnu/include -isystem /usr/local/x86_64-pc-linux-gnu/sys-include    -c -g -O2 -m32 -fpic  -W -Wall -gnatpg -nostdinc -m32  s-regpat.adb -o s-regpat.o
> > 
> > raised STORAGE_ERROR : stack overflow or erroneous memory access
> > ../gcc-interface/Makefile:296: recipe for target 's-regpat.o' failed
> > 
> > 
> > > diff --git a/gcc/ada/gcc-interface/utils2.c b/gcc/ada/gcc-interface/utils2.c
> > > index fc6f1b8..cd37791 100644
> > > --- a/gcc/ada/gcc-interface/utils2.c
> > > +++ b/gcc/ada/gcc-interface/utils2.c
> > > @@ -1934,8 +1934,8 @@ build_call_raise_range (int msg, Node_Id gnat_node, char kind,
> > > static int
> > > compare_elmt_bitpos (const PTR rt1, const PTR rt2)
> > > {
> > > -  const constructor_elt * const elmt1 = (const constructor_elt * const) rt1;
> > > -  const constructor_elt * const elmt2 = (const constructor_elt * const) rt2;
> > > +  const constructor_elt * const elmt1 = (const constructor_elt *) rt1;
> > > +  const constructor_elt * const elmt2 = (const constructor_elt *) rt2;
> > >   const_tree const field1 = elmt1->index;
> > >   const_tree const field2 = elmt2->index;
> > >   const int ret
> 
> So, what can one do with typeof or similar to avoid the warning?
> 
> void
> foo (const void *p)
> {
>   const int *const q = (const int *const) p;
>   typeof (q) r = (typeof (q)) p;
>   (void) q;
>   (void) r;
> }
> 
> AFAIK typeof doesn't strip the toplevel qualifiers and I see current trunk
> warns even about the cast in r initialization.  Similarly to what has been
> noted recently in another (C) PR, it would be nice if we had toplevel cv
> stripping variant of typeof or some special builtin that could wrap
> typeof or some type and could be used in places where typeof can,
>   __strip_cv (typeof (q)) = (__strip_cv (typeof (q))) p;
> or
>   typeof (q) = (__strip_cv (typeof (q))) p;
> or
>   __strip_cv (const int *const) z;
> where the last one would be effectively
>   const int *z;

I remember trying to implement the stripping version of __typeof; I even had
a prototype patch that I'm of course not finding right now, but I'd be happy to
work on this again.

Ok, I at least found the PR:
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65455
and
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=39985
Also there's
https://gcc.gnu.org/ml/gcc-patches/2016-02/msg00268.html

Let me know if I should get back to it.

	Marek
Jonathan Wakely May 25, 2017, 2:52 p.m. UTC | #5
On 25/05/17 16:11 +0200, Jakub Jelinek wrote:
>On Thu, May 25, 2017 at 03:02:42PM +0100, Jonathan Wakely wrote:
>> On 25/05/17 11:07 +0100, Jonathan Wakely wrote:
>> > On 25/05/17 10:05 +0200, Andreas Schwab wrote:
>> > > ../../gcc/ada/gcc-interface/utils2.c: In function 'int compare_elmt_bitpos(const void*, const void*)':
>> > > ../../gcc/ada/gcc-interface/utils2.c:1937:73: error: type qualifiers ignored on cast result type [-Werror=ignored-qualifiers]
>> > >  const constructor_elt * const elmt1 = (const constructor_elt * const) rt1;
>> > >                                                                        ^~~
>> > > ../../gcc/ada/gcc-interface/utils2.c:1938:73: error: type qualifiers ignored on cast result type [-Werror=ignored-qualifiers]
>> > >  const constructor_elt * const elmt2 = (const constructor_elt * const) rt2;
>> >
>> > I'm testing this obvious fix.
>>
>> Committed as r248458 because it gets bootstrap past the error above,
>> although now Ada fails for me with:
>>
>> /home/jwakely/src/gcc/bootstrap/./gcc/xgcc -B/home/jwakely/src/gcc/bootstrap/./gcc/ -B/usr/local/x86_64-pc-linux-gnu/bin/ -B/usr/local/x86_64-pc-linux-gnu/lib/ -isystem /usr/local/x86_64-pc-linux-gnu/include -isystem /usr/local/x86_64-pc-linux-gnu/sys-include    -c -g -O2 -m32 -fpic  -W -Wall -gnatpg -nostdinc -m32  s-regpat.adb -o s-regpat.o
>>
>> raised STORAGE_ERROR : stack overflow or erroneous memory access
>> ../gcc-interface/Makefile:296: recipe for target 's-regpat.o' failed
>>
>>
>> > diff --git a/gcc/ada/gcc-interface/utils2.c b/gcc/ada/gcc-interface/utils2.c
>> > index fc6f1b8..cd37791 100644
>> > --- a/gcc/ada/gcc-interface/utils2.c
>> > +++ b/gcc/ada/gcc-interface/utils2.c
>> > @@ -1934,8 +1934,8 @@ build_call_raise_range (int msg, Node_Id gnat_node, char kind,
>> > static int
>> > compare_elmt_bitpos (const PTR rt1, const PTR rt2)
>> > {
>> > -  const constructor_elt * const elmt1 = (const constructor_elt * const) rt1;
>> > -  const constructor_elt * const elmt2 = (const constructor_elt * const) rt2;
>> > +  const constructor_elt * const elmt1 = (const constructor_elt *) rt1;
>> > +  const constructor_elt * const elmt2 = (const constructor_elt *) rt2;
>> >   const_tree const field1 = elmt1->index;
>> >   const_tree const field2 = elmt2->index;
>> >   const int ret
>
>So, what can one do with typeof or similar to avoid the warning?
>
>void
>foo (const void *p)
>{
>  const int *const q = (const int *const) p;
>  typeof (q) r = (typeof (q)) p;
>  (void) q;
>  (void) r;
>}

I'd probably write that like this instead:

void
foo (const void *p)
{
  typedef const int* ptr_type;
  ptr_type const q = (ptr_type) p;
  ptr_type const r = (ptr_type) p;
  (void) q;
  (void) r;
}

It names the type only once, not twice as in your example, and doesn't
need to use typeof to refer to that type again.

The variables p and q are defined const, which is what's wanted. The
cast is to ptr_type, not ptr_type const.
Jakub Jelinek May 25, 2017, 2:56 p.m. UTC | #6
On Thu, May 25, 2017 at 03:52:47PM +0100, Jonathan Wakely wrote:
> I'd probably write that like this instead:
> 
> void
> foo (const void *p)
> {
>  typedef const int* ptr_type;
>  ptr_type const q = (ptr_type) p;
>  ptr_type const r = (ptr_type) p;
>  (void) q;
>  (void) r;
> }
> 
> It names the type only once, not twice as in your example, and doesn't
> need to use typeof to refer to that type again.

That was over-simplified, I meant cases where you actually don't know the
exact type, just use typeof to create a variable of such a type and
then want to cast something to that type.

	Jakub
Jonathan Wakely May 25, 2017, 3:43 p.m. UTC | #7
On 25/05/17 16:56 +0200, Jakub Jelinek wrote:
>On Thu, May 25, 2017 at 03:52:47PM +0100, Jonathan Wakely wrote:
>> I'd probably write that like this instead:
>>
>> void
>> foo (const void *p)
>> {
>>  typedef const int* ptr_type;
>>  ptr_type const q = (ptr_type) p;
>>  ptr_type const r = (ptr_type) p;
>>  (void) q;
>>  (void) r;
>> }
>>
>> It names the type only once, not twice as in your example, and doesn't
>> need to use typeof to refer to that type again.
>
>That was over-simplified, I meant cases where you actually don't know the
>exact type, just use typeof to create a variable of such a type and
>then want to cast something to that type.

The most obvious case I can think of where you don't know the type
would be the result of some expression (maybe involving overloaded
operators, or a call to an overloaded function).  In that case:

  typeof (expr) const q = (typeof (expr)) p;

Again, add the const to the variable definition, but not the cast.

or using a typedef again for clarity and to avoid the repetition:

  typedef typeof (expr) the_type;
  the_type const q = (the_type) p;

If the result of the expression is a scalar type then it won't be
const-qualified, so the_type isn't either, and the cast won't warn.

If the result of the expression is a class-type then it can be
const-qualified, and so the_type is also const-qualified, but the
warning isn't issued in such case.

All the realistic case I can think of expr won't be simply a variable
(because if you have a variable then it was already declared with some
type and you can refer to that type directly) so the original problem
where typeof(q) deduces a const-qualified type won't happen.

template<typename T> void f (const T& t, const void* p) {
  // no need for typeof(t) because we can just use T
  T* const q = (T*)p;
  T* const r = (T*)p;
}

There's this case, which will warn if the type is a pointer or other
scalar:

  auto const q = some_function (p);
  typeof (q) r = (typeof (q)) p

But what you really care about is typeof (some_function (p)) not
typeof (q), which is just the 'expr' case above:

  typedef typeof (some_function(p)) ptr_type;
  ptr_type const q = some_function (p);
  ptr_type const r = (ptr_type)p;

The warning is avoidable by using typeof on the expression that
determines the type, not on a variable that has a const-qualified
version of the type.
diff mbox

Patch

diff --git a/gcc/ada/gcc-interface/utils2.c b/gcc/ada/gcc-interface/utils2.c
index fc6f1b8..cd37791 100644
--- a/gcc/ada/gcc-interface/utils2.c
+++ b/gcc/ada/gcc-interface/utils2.c
@@ -1934,8 +1934,8 @@  build_call_raise_range (int msg, Node_Id gnat_node, char kind,
 static int
 compare_elmt_bitpos (const PTR rt1, const PTR rt2)
 {
-  const constructor_elt * const elmt1 = (const constructor_elt * const) rt1;
-  const constructor_elt * const elmt2 = (const constructor_elt * const) rt2;
+  const constructor_elt * const elmt1 = (const constructor_elt *) rt1;
+  const constructor_elt * const elmt2 = (const constructor_elt *) rt2;
   const_tree const field1 = elmt1->index;
   const_tree const field2 = elmt2->index;
   const int ret