public inbox for gcc@gcc.gnu.org
 help / color / mirror / Atom feed
* -Wcast-qual and casting away
@ 2009-05-21 11:50 Ian Lance Taylor
  2009-05-21 11:58 ` Richard Guenther
                   ` (4 more replies)
  0 siblings, 5 replies; 13+ messages in thread
From: Ian Lance Taylor @ 2009-05-21 11:50 UTC (permalink / raw)
  To: gcc

Consider this C/C++ program:

extern void **f1();
void f2(const char *p) { *(const void **)f1() = p; }

If I compile this program with g++ -Wcast-qual, I get this:

foo2.cc:2: warning: cast from type ‘void**’ to type ‘const void**’ casts away qualifiers

If I compile this program with gcc -Wcast-qual, I do not get any
warning.

Let's overlook the fact that the text of the g++ warning does not make
any sense--I am certainly not casting anything away.  The warning is
conceptually plausible for the same reason that you can't assign a
char** variable to a const char** variable without a cast.  At least, I
think one could make a argument that that is so.  But it's not a *very*
strong argument, as -Wcast-qual is documented to warn about cases where
a type qualifier is removed, and that is manifestly not happening here.
-Wcast-qual is useful to catch certain programming errors; I don't think
anybody adding a const qualifier is actually making a mistake.

All that aside, I can't think of any reason that the C and C++ frontends
should be different in this regard.  Does anybody want to make an
argument for which of these choices we should adopt?

1) Keep things the same: the C++ frontend warns, the C frontend doesn't.
   Consistency is overrated.

2) Change the C frontend to also warn about this case, albeit with a
   better message.

3) Change the C++ frontend to not warn about this case.

Of course in all cases the frontends should continue to warn about a
cast from const void** to void**.

Ian

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: -Wcast-qual and casting away
  2009-05-21 11:50 -Wcast-qual and casting away Ian Lance Taylor
@ 2009-05-21 11:58 ` Richard Guenther
  2009-05-22  0:20   ` Gabriel Dos Reis
  2009-05-21 12:09 ` Andreas Schwab
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 13+ messages in thread
From: Richard Guenther @ 2009-05-21 11:58 UTC (permalink / raw)
  To: Ian Lance Taylor; +Cc: gcc

On Thu, May 21, 2009 at 7:10 AM, Ian Lance Taylor <iant@google.com> wrote:
> Consider this C/C++ program:
>
> extern void **f1();
> void f2(const char *p) { *(const void **)f1() = p; }
>
> If I compile this program with g++ -Wcast-qual, I get this:
>
> foo2.cc:2: warning: cast from type ‘void**’ to type ‘const void**’ casts away qualifiers
>
> If I compile this program with gcc -Wcast-qual, I do not get any
> warning.
>
> Let's overlook the fact that the text of the g++ warning does not make
> any sense--I am certainly not casting anything away.  The warning is
> conceptually plausible for the same reason that you can't assign a
> char** variable to a const char** variable without a cast.  At least, I
> think one could make a argument that that is so.  But it's not a *very*
> strong argument, as -Wcast-qual is documented to warn about cases where
> a type qualifier is removed, and that is manifestly not happening here.
> -Wcast-qual is useful to catch certain programming errors; I don't think
> anybody adding a const qualifier is actually making a mistake.
>
> All that aside, I can't think of any reason that the C and C++ frontends
> should be different in this regard.  Does anybody want to make an
> argument for which of these choices we should adopt?
>
> 1) Keep things the same: the C++ frontend warns, the C frontend doesn't.
>   Consistency is overrated.
>
> 2) Change the C frontend to also warn about this case, albeit with a
>   better message.
>
> 3) Change the C++ frontend to not warn about this case.
>
> Of course in all cases the frontends should continue to warn about a
> cast from const void** to void**.

As the C++ warning doesn't make any sense I vote for 3).

Richard.

> Ian
>

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: -Wcast-qual and casting away
  2009-05-21 11:50 -Wcast-qual and casting away Ian Lance Taylor
  2009-05-21 11:58 ` Richard Guenther
@ 2009-05-21 12:09 ` Andreas Schwab
  2009-05-21 12:50   ` Richard Guenther
  2009-05-21 12:38 ` Joseph S. Myers
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 13+ messages in thread
From: Andreas Schwab @ 2009-05-21 12:09 UTC (permalink / raw)
  To: Ian Lance Taylor; +Cc: gcc

Ian Lance Taylor <iant@google.com> writes:

> Consider this C/C++ program:
>
> extern void **f1();
> void f2(const char *p) { *(const void **)f1() = p; }
>
> If I compile this program with g++ -Wcast-qual, I get this:
>
> foo2.cc:2: warning: cast from type ‘void**’ to type ‘const void**’ casts away qualifiers

In a sense this warning is actually correct: this is storing a const
char * into a void * object, which is where the qualifier is lost.  IMHO
having a warning for this questionable operation is a good thing.

Andreas.

-- 
Andreas Schwab, schwab@linux-m68k.org
GPG Key fingerprint = 58CA 54C7 6D53 942B 1756  01D3 44D5 214B 8276 4ED5
"And now for something completely different."

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: -Wcast-qual and casting away
  2009-05-21 11:50 -Wcast-qual and casting away Ian Lance Taylor
  2009-05-21 11:58 ` Richard Guenther
  2009-05-21 12:09 ` Andreas Schwab
@ 2009-05-21 12:38 ` Joseph S. Myers
  2009-05-21 17:36   ` Ian Lance Taylor
  2009-05-21 15:26 ` Dave Korn
  2009-05-22  0:16 ` Gabriel Dos Reis
  4 siblings, 1 reply; 13+ messages in thread
From: Joseph S. Myers @ 2009-05-21 12:38 UTC (permalink / raw)
  To: Ian Lance Taylor; +Cc: gcc

On Wed, 20 May 2009, Ian Lance Taylor wrote:

> All that aside, I can't think of any reason that the C and C++ frontends
> should be different in this regard.  Does anybody want to make an

There's the fairly obvious reason that C and C++ have different rules on 
implicit conversions involving const, so const at higher levels of 
indirection is irrelevant in C in a way that it is not in C++.  (Adoption 
of the C++ rules was considered and rejected for C99.)

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: -Wcast-qual and casting away
  2009-05-21 12:09 ` Andreas Schwab
@ 2009-05-21 12:50   ` Richard Guenther
  2009-05-21 15:13     ` Andreas Schwab
                       ` (2 more replies)
  0 siblings, 3 replies; 13+ messages in thread
From: Richard Guenther @ 2009-05-21 12:50 UTC (permalink / raw)
  To: Andreas Schwab; +Cc: Ian Lance Taylor, gcc

On Thu, May 21, 2009 at 1:50 PM, Andreas Schwab <schwab@linux-m68k.org> wrote:
> Ian Lance Taylor <iant@google.com> writes:
>
>> Consider this C/C++ program:
>>
>> extern void **f1();
>> void f2(const char *p) { *(const void **)f1() = p; }
>>
>> If I compile this program with g++ -Wcast-qual, I get this:
>>
>> foo2.cc:2: warning: cast from type ‘void**’ to type ‘const void**’ casts away qualifiers
>
> In a sense this warning is actually correct: this is storing a const
> char * into a void * object, which is where the qualifier is lost.  IMHO
> having a warning for this questionable operation is a good thing.

I don't think so.

extern char **f1();
void f(char *p)
{
  *(const char **)f1() = p;
}

warns the same. typeof(*(const char **)) should still be const char *.

For

extern const char **f1();
void f(char *p)
{
  *(char **)f1() = p;
}

it warns with

t.C: In function ‘void f(char*)’:
t.C:4: warning: cast from type ‘const char**’ to type ‘char**’ casts
away constness

which makes sense.

Richard.

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: -Wcast-qual and casting away
  2009-05-21 12:50   ` Richard Guenther
@ 2009-05-21 15:13     ` Andreas Schwab
  2009-05-21 15:22     ` Sebastian Redl
  2009-05-21 22:48     ` Ian Lance Taylor
  2 siblings, 0 replies; 13+ messages in thread
From: Andreas Schwab @ 2009-05-21 15:13 UTC (permalink / raw)
  To: Richard Guenther; +Cc: Ian Lance Taylor, gcc

Richard Guenther <richard.guenther@gmail.com> writes:

> For
>
> extern const char **f1();
> void f(char *p)
> {
>   *(char **)f1() = p;
> }
>
> it warns with
>
> t.C: In function ‘void f(char*)’:
> t.C:4: warning: cast from type ‘const char**’ to type ‘char**’ casts
> away constness
>
> which makes sense.

This is actually a safe operation, you can even store safely into
**(char **)f1() afterwards.

Andreas.

-- 
Andreas Schwab, schwab@linux-m68k.org
GPG Key fingerprint = 58CA 54C7 6D53 942B 1756  01D3 44D5 214B 8276 4ED5
"And now for something completely different."

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: -Wcast-qual and casting away
  2009-05-21 12:50   ` Richard Guenther
  2009-05-21 15:13     ` Andreas Schwab
@ 2009-05-21 15:22     ` Sebastian Redl
  2009-05-21 22:48     ` Ian Lance Taylor
  2 siblings, 0 replies; 13+ messages in thread
From: Sebastian Redl @ 2009-05-21 15:22 UTC (permalink / raw)
  To: Richard Guenther; +Cc: Andreas Schwab, Ian Lance Taylor, gcc

Richard Guenther wrote:
> On Thu, May 21, 2009 at 1:50 PM, Andreas Schwab <schwab@linux-m68k.org> wrote:
>   
>> Ian Lance Taylor <iant@google.com> writes:
>>
>>     
>>> Consider this C/C++ program:
>>>
>>> extern void **f1();
>>> void f2(const char *p) { *(const void **)f1() = p; }
>>>
>>> If I compile this program with g++ -Wcast-qual, I get this:
>>>
>>> foo2.cc:2: warning: cast from type ‘void**’ to type ‘const void**’ casts away qualifiers
>>>       
>> In a sense this warning is actually correct: this is storing a const
>> char * into a void * object, which is where the qualifier is lost.  IMHO
>> having a warning for this questionable operation is a good thing.
>>     
>
> I don't think so.
>
> extern char **f1();
> void f(char *p)
> {
>   *(const char **)f1() = p;
> }
>
> warns the same. typeof(*(const char **)) should still be const char *.
>   
It seems the rules for the warning follow the same rules for whether
such qualifier changes are allowed in implicit conversions (or named
casts other than const_cast).

Let's say char** -> const char** is allowed silently. Then the program
below is silently violating const correctness:
char* pc;
char** ppc = &pc;
const char** cppc = ppc; // Silently allowed?
const char cc = 0;
*ppc = &cc; // Silently allowed, pc now points to cc
*pc = 1; // Silently allowed, but changes cc

The conversion T** -> const T** is unsafe. That's all there is to it.
The warning is correct.
Cast to T const* const* instead.

Sebastian

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: -Wcast-qual and casting away
  2009-05-21 11:50 -Wcast-qual and casting away Ian Lance Taylor
                   ` (2 preceding siblings ...)
  2009-05-21 12:38 ` Joseph S. Myers
@ 2009-05-21 15:26 ` Dave Korn
  2009-05-22  0:16 ` Gabriel Dos Reis
  4 siblings, 0 replies; 13+ messages in thread
From: Dave Korn @ 2009-05-21 15:26 UTC (permalink / raw)
  To: Ian Lance Taylor; +Cc: gcc

Ian Lance Taylor wrote:
> Consider this C/C++ program:
> 
> extern void **f1();
> void f2(const char *p) { *(const void **)f1() = p; }
> 
> If I compile this program with g++ -Wcast-qual, I get this:
> 
> foo2.cc:2: warning: cast from type ‘void**’ to type ‘const void**’ casts away qualifiers
> 
> If I compile this program with gcc -Wcast-qual, I do not get any
> warning.

> 2) Change the C frontend to also warn about this case, albeit with a
>    better message.

> Of course in all cases the frontends should continue to warn about a
> cast from const void** to void**.

  Well, they should warn about this case also then.

extern void **f1();
void f2(const char *p) { *(const void **)f1() = p; }

void *x;

void **f1()
{
  return &x
}

void f2(char *foo, int n)
{
  memcpy (x, foo, n); // BOOM!
}

  This looks like a disguised way of casting a const char* to a (non-const)
void* to me, isn't it?  Sure, the warning is being tripped by the cast rather
than the conversion that the cast is hiding, it needs to be improved, but I'm
glad we got at least some noise from such a dubious construction.

    cheers,
      DaveK

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: -Wcast-qual and casting away
  2009-05-21 12:38 ` Joseph S. Myers
@ 2009-05-21 17:36   ` Ian Lance Taylor
  0 siblings, 0 replies; 13+ messages in thread
From: Ian Lance Taylor @ 2009-05-21 17:36 UTC (permalink / raw)
  To: Joseph S. Myers; +Cc: gcc

"Joseph S. Myers" <joseph@codesourcery.com> writes:

> On Wed, 20 May 2009, Ian Lance Taylor wrote:
>
>> All that aside, I can't think of any reason that the C and C++ frontends
>> should be different in this regard.  Does anybody want to make an
>
> There's the fairly obvious reason that C and C++ have different rules on 
> implicit conversions involving const, so const at higher levels of 
> indirection is irrelevant in C in a way that it is not in C++.  (Adoption 
> of the C++ rules was considered and rejected for C99.)

Fair enough, but I don't see any particular reason these rather esoteric
rules should affect the -Wcast-qual option.

Ian

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: -Wcast-qual and casting away
  2009-05-21 12:50   ` Richard Guenther
  2009-05-21 15:13     ` Andreas Schwab
  2009-05-21 15:22     ` Sebastian Redl
@ 2009-05-21 22:48     ` Ian Lance Taylor
  2009-05-22  1:01       ` Gabriel Dos Reis
  2 siblings, 1 reply; 13+ messages in thread
From: Ian Lance Taylor @ 2009-05-21 22:48 UTC (permalink / raw)
  To: Richard Guenther; +Cc: Andreas Schwab, gcc

Richard Guenther <richard.guenther@gmail.com> writes:

> On Thu, May 21, 2009 at 1:50 PM, Andreas Schwab <schwab@linux-m68k.org> wrote:
>> Ian Lance Taylor <iant@google.com> writes:
>>
>>> Consider this C/C++ program:
>>>
>>> extern void **f1();
>>> void f2(const char *p) { *(const void **)f1() = p; }
>>>
>>> If I compile this program with g++ -Wcast-qual, I get this:
>>>
>>> foo2.cc:2: warning: cast from type ‘void**’ to type ‘const void**’ casts away qualifiers
>>
>> In a sense this warning is actually correct: this is storing a const
>> char * into a void * object, which is where the qualifier is lost.  IMHO
>> having a warning for this questionable operation is a good thing.
>
> I don't think so.
>
> extern char **f1();
> void f(char *p)
> {
>   *(const char **)f1() = p;
> }
>
> warns the same. typeof(*(const char **)) should still be const char *.
>
> For
>
> extern const char **f1();
> void f(char *p)
> {
>   *(char **)f1() = p;
> }
>
> it warns with
>
> t.C: In function ‘void f(char*)’:
> t.C:4: warning: cast from type ‘const char**’ to type ‘char**’ casts
> away constness
>
> which makes sense.

Let's not focus too much on the operation (the indirection and the
assignment).  The warning is about the cast itself.  Should we issue
that warning or not?  Others have explained the cases where the cast can
lead to unsafe code.

The indirection + assignment operation is easy to do in all cases by
moving the cast to the other side.

Ian

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: -Wcast-qual and casting away
  2009-05-21 11:50 -Wcast-qual and casting away Ian Lance Taylor
                   ` (3 preceding siblings ...)
  2009-05-21 15:26 ` Dave Korn
@ 2009-05-22  0:16 ` Gabriel Dos Reis
  4 siblings, 0 replies; 13+ messages in thread
From: Gabriel Dos Reis @ 2009-05-22  0:16 UTC (permalink / raw)
  To: Ian Lance Taylor; +Cc: gcc

On Thu, May 21, 2009 at 12:10 AM, Ian Lance Taylor <iant@google.com> wrote:
> Consider this C/C++ program:
>
> extern void **f1();
> void f2(const char *p) { *(const void **)f1() = p; }
>
> If I compile this program with g++ -Wcast-qual, I get this:
>
> foo2.cc:2: warning: cast from type ‘void**’ to type ‘const void**’ casts away qualifiers
>
> If I compile this program with gcc -Wcast-qual, I do not get any
> warning.
>
> Let's overlook the fact that the text of the g++ warning does not make
> any sense--I am certainly not casting anything away.  The warning is
> conceptually plausible for the same reason that you can't assign a
> char** variable to a const char** variable without a cast.  At least, I
> think one could make a argument that that is so.  But it's not a *very*
> strong argument, as -Wcast-qual is documented to warn about cases where
> a type qualifier is removed, and that is manifestly not happening here.
> -Wcast-qual is useful to catch certain programming errors; I don't think
> anybody adding a const qualifier is actually making a mistake.

In fact, the contrary is true.  The warning speaks the truth.
The implicit conversion is unsafe and the cast is explicitly
by-passing that const-safety built into the type system.

-- Gaby

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: -Wcast-qual and casting away
  2009-05-21 11:58 ` Richard Guenther
@ 2009-05-22  0:20   ` Gabriel Dos Reis
  0 siblings, 0 replies; 13+ messages in thread
From: Gabriel Dos Reis @ 2009-05-22  0:20 UTC (permalink / raw)
  To: Richard Guenther; +Cc: Ian Lance Taylor, gcc

On Thu, May 21, 2009 at 5:20 AM, Richard Guenther
<richard.guenther@gmail.com> wrote:
> On Thu, May 21, 2009 at 7:10 AM, Ian Lance Taylor <iant@google.com> wrote:
>> Consider this C/C++ program:
>>
>> extern void **f1();
>> void f2(const char *p) { *(const void **)f1() = p; }
>>
>> If I compile this program with g++ -Wcast-qual, I get this:
>>
>> foo2.cc:2: warning: cast from type ‘void**’ to type ‘const void**’ casts away qualifiers
>>
>> If I compile this program with gcc -Wcast-qual, I do not get any
>> warning.
>>
>> Let's overlook the fact that the text of the g++ warning does not make
>> any sense--I am certainly not casting anything away.  The warning is
>> conceptually plausible for the same reason that you can't assign a
>> char** variable to a const char** variable without a cast.  At least, I
>> think one could make a argument that that is so.  But it's not a *very*
>> strong argument, as -Wcast-qual is documented to warn about cases where
>> a type qualifier is removed, and that is manifestly not happening here.
>> -Wcast-qual is useful to catch certain programming errors; I don't think
>> anybody adding a const qualifier is actually making a mistake.
>>
>> All that aside, I can't think of any reason that the C and C++ frontends
>> should be different in this regard.  Does anybody want to make an
>> argument for which of these choices we should adopt?
>>
>> 1) Keep things the same: the C++ frontend warns, the C frontend doesn't.
>>   Consistency is overrated.
>>
>> 2) Change the C frontend to also warn about this case, albeit with a
>>   better message.
>>
>> 3) Change the C++ frontend to not warn about this case.
>>
>> Of course in all cases the frontends should continue to warn about a
>> cast from const void** to void**.
>
> As the C++ warning doesn't make any sense I vote for 3).

Why do you think it the warning does not make sense?

The only you can go from void** to const void** is that you actually
remove the const in the middle of const void* const *.  That is
precisely what the cast is doing -- so the warning is legitimate.

-- Gaby

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: -Wcast-qual and casting away
  2009-05-21 22:48     ` Ian Lance Taylor
@ 2009-05-22  1:01       ` Gabriel Dos Reis
  0 siblings, 0 replies; 13+ messages in thread
From: Gabriel Dos Reis @ 2009-05-22  1:01 UTC (permalink / raw)
  To: Ian Lance Taylor; +Cc: Richard Guenther, Andreas Schwab, gcc

On Thu, May 21, 2009 at 11:11 AM, Ian Lance Taylor <iant@google.com> wrote:
> Richard Guenther <richard.guenther@gmail.com> writes:
>
>> On Thu, May 21, 2009 at 1:50 PM, Andreas Schwab <schwab@linux-m68k.org> wrote:
>>> Ian Lance Taylor <iant@google.com> writes:
>>>
>>>> Consider this C/C++ program:
>>>>
>>>> extern void **f1();
>>>> void f2(const char *p) { *(const void **)f1() = p; }
>>>>
>>>> If I compile this program with g++ -Wcast-qual, I get this:
>>>>
>>>> foo2.cc:2: warning: cast from type ‘void**’ to type ‘const void**’ casts away qualifiers
>>>
>>> In a sense this warning is actually correct: this is storing a const
>>> char * into a void * object, which is where the qualifier is lost.  IMHO
>>> having a warning for this questionable operation is a good thing.
>>
>> I don't think so.
>>
>> extern char **f1();
>> void f(char *p)
>> {
>>   *(const char **)f1() = p;
>> }
>>
>> warns the same. typeof(*(const char **)) should still be const char *.
>>
>> For
>>
>> extern const char **f1();
>> void f(char *p)
>> {
>>   *(char **)f1() = p;
>> }
>>
>> it warns with
>>
>> t.C: In function ‘void f(char*)’:
>> t.C:4: warning: cast from type ‘const char**’ to type ‘char**’ casts
>> away constness
>>
>> which makes sense.
>
> Let's not focus too much on the operation (the indirection and the
> assignment).  The warning is about the cast itself.  Should we issue
> that warning or not?  Others have explained the cases where the cast can
> lead to unsafe code.

The particular cast in question is not a safe operation.  Should we warn
about it when -Wcast-qual, I think so -- that is one of the purposes of
the switch.

-- Gaby

^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2009-05-21 17:36 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-05-21 11:50 -Wcast-qual and casting away Ian Lance Taylor
2009-05-21 11:58 ` Richard Guenther
2009-05-22  0:20   ` Gabriel Dos Reis
2009-05-21 12:09 ` Andreas Schwab
2009-05-21 12:50   ` Richard Guenther
2009-05-21 15:13     ` Andreas Schwab
2009-05-21 15:22     ` Sebastian Redl
2009-05-21 22:48     ` Ian Lance Taylor
2009-05-22  1:01       ` Gabriel Dos Reis
2009-05-21 12:38 ` Joseph S. Myers
2009-05-21 17:36   ` Ian Lance Taylor
2009-05-21 15:26 ` Dave Korn
2009-05-22  0:16 ` Gabriel Dos Reis

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).