public inbox for gcc@gcc.gnu.org
 help / color / mirror / Atom feed
* Compiling GCC With a C++ Compiler (g++)
@ 2004-10-11  9:53 Ranjit Mathew
  2004-10-12 10:06 ` Ranjit Mathew
  0 siblings, 1 reply; 63+ messages in thread
From: Ranjit Mathew @ 2004-10-11  9:53 UTC (permalink / raw)
  To: gcc

Hi,

  If I try compiling bits that include "gcc/tree.h" with
g++, I get:

/home/ranmath/src/gcc/gcc/gcc/tree.h:2504: error: member 'tree_string tree_node::string' with copy assignment operator not allowed in union

The definition of tree_string is:

  struct tree_string GTY(())
  {
    struct tree_common common;
    int length;
    const char str[1];
  };

If the "const" is removed from above, the compilation
proceeds.

There were a flurry of patches to make GCC compilable
with a C++ compiler in the recent past and I thought
it was now done... Didn't anyone else run into this?
(Apart from Tom, who suggested the fix above.)

Is this a bug? If yes, is it in the C++ compiler or
in the definition of tree_string?

Thanks,
Ranjit.

-- 
Ranjit Mathew          Email: rmathew AT gmail DOT com

Bangalore, INDIA.      Web: http://ranjitmathew.tripod.com/

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

* Re: Compiling GCC With a C++ Compiler (g++)
  2004-10-11  9:53 Compiling GCC With a C++ Compiler (g++) Ranjit Mathew
@ 2004-10-12 10:06 ` Ranjit Mathew
  2004-10-12 13:17   ` Gabriel Dos Reis
  2004-10-12 21:15   ` Geoffrey Keating
  0 siblings, 2 replies; 63+ messages in thread
From: Ranjit Mathew @ 2004-10-12 10:06 UTC (permalink / raw)
  To: GCC; +Cc: gkeating

Ranjit Mathew wrote:
> The definition of tree_string is:
> 
>   struct tree_string GTY(())
>   {
>     struct tree_common common;
>     int length;
>     const char str[1];
>   };
> 
> If the "const" is removed from above, the compilation
> proceeds.

The "const char *pointer" -> "const char str[1]" change
was done by geoffk as a part of fixing pch/13361.

We now want to store the string in the node itself,
rather than merely pointing to it.

However, I still think that the "const" is
misleading/incorrect. In build_string() in tree.c,
we cast it to (char *) anyways before memcpy-ing the
desired string into it.

Would it be wrong to remove it? (And thus re-enable
compiling this bit of GCC with a C++ compiler like
g++.)

Thanks,
Ranjit.

-- 
Ranjit Mathew          Email: rmathew AT gmail DOT com

Bangalore, INDIA.      Web: http://ranjitmathew.tripod.com/

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

* Re: Compiling GCC With a C++ Compiler (g++)
  2004-10-12 10:06 ` Ranjit Mathew
@ 2004-10-12 13:17   ` Gabriel Dos Reis
  2004-10-12 21:15   ` Geoffrey Keating
  1 sibling, 0 replies; 63+ messages in thread
From: Gabriel Dos Reis @ 2004-10-12 13:17 UTC (permalink / raw)
  To: Ranjit Mathew; +Cc: GCC, gkeating

Ranjit Mathew <rmathew@gmail.com> writes:

| Ranjit Mathew wrote:
| > The definition of tree_string is:
| > 
| >   struct tree_string GTY(())
| >   {
| >     struct tree_common common;
| >     int length;
| >     const char str[1];
| >   };
| > 
| > If the "const" is removed from above, the compilation
| > proceeds.
| 
| The "const char *pointer" -> "const char str[1]" change
| was done by geoffk as a part of fixing pch/13361.
| 
| We now want to store the string in the node itself,
| rather than merely pointing to it.
| 
| However, I still think that the "const" is
| misleading/incorrect. In build_string() in tree.c,
| we cast it to (char *) anyways before memcpy-ing the
| desired string into it.

You're right in your analysis.

| Would it be wrong to remove it? (And thus re-enable
| compiling this bit of GCC with a C++ compiler like
| g++.)

No, it would not.

-- Gaby

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

* Re: Compiling GCC With a C++ Compiler (g++)
  2004-10-12 10:06 ` Ranjit Mathew
  2004-10-12 13:17   ` Gabriel Dos Reis
@ 2004-10-12 21:15   ` Geoffrey Keating
  2004-10-12 23:00     ` Gabriel Dos Reis
  1 sibling, 1 reply; 63+ messages in thread
From: Geoffrey Keating @ 2004-10-12 21:15 UTC (permalink / raw)
  To: Ranjit Mathew; +Cc: GCC

[-- Attachment #1: Type: text/plain, Size: 1025 bytes --]


On 12/10/2004, at 12:38 AM, Ranjit Mathew wrote:

> Ranjit Mathew wrote:
>> The definition of tree_string is:
>>
>>   struct tree_string GTY(())
>>   {
>>     struct tree_common common;
>>     int length;
>>     const char str[1];
>>   };
>>
>> If the "const" is removed from above, the compilation
>> proceeds.
>
> The "const char *pointer" -> "const char str[1]" change
> was done by geoffk as a part of fixing pch/13361.
>
> We now want to store the string in the node itself,
> rather than merely pointing to it.
>
> However, I still think that the "const" is
> misleading/incorrect. In build_string() in tree.c,
> we cast it to (char *) anyways before memcpy-ing the
> desired string into it.
>
> Would it be wrong to remove it? (And thus re-enable
> compiling this bit of GCC with a C++ compiler like
> g++.)

The 'const' is there to indicate that the string should not be changed 
once the STRING_CST is created; STRING_CSTs may be shared.

Why is C++ complaining about this?  It looks like a reasonable 
construct.


[-- Attachment #2: smime.p7s --]
[-- Type: application/pkcs7-signature, Size: 2408 bytes --]

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

* Re: Compiling GCC With a C++ Compiler (g++)
  2004-10-12 21:15   ` Geoffrey Keating
@ 2004-10-12 23:00     ` Gabriel Dos Reis
  2004-10-12 23:23       ` Zack Weinberg
  0 siblings, 1 reply; 63+ messages in thread
From: Gabriel Dos Reis @ 2004-10-12 23:00 UTC (permalink / raw)
  To: Geoffrey Keating; +Cc: Ranjit Mathew, GCC

Geoffrey Keating <geoffk@apple.com> writes:

| On 12/10/2004, at 12:38 AM, Ranjit Mathew wrote:
| 
| > Ranjit Mathew wrote:
| >> The definition of tree_string is:
| >>
| >>   struct tree_string GTY(())
| >>   {
| >>     struct tree_common common;
| >>     int length;
| >>     const char str[1];
| >>   };
| >>
| >> If the "const" is removed from above, the compilation
| >> proceeds.
| >
| > The "const char *pointer" -> "const char str[1]" change
| > was done by geoffk as a part of fixing pch/13361.
| >
| > We now want to store the string in the node itself,
| > rather than merely pointing to it.
| >
| > However, I still think that the "const" is
| > misleading/incorrect. In build_string() in tree.c,
| > we cast it to (char *) anyways before memcpy-ing the
| > desired string into it.
| >
| > Would it be wrong to remove it? (And thus re-enable
| > compiling this bit of GCC with a C++ compiler like
| > g++.)
| 
| The 'const' is there to indicate that the string should not be changed
| once the STRING_CST is created;

And how do you create it?

| STRING_CSTs may be shared.

Sharing is orthogonal to being marked "const".

| 
| Why is C++ complaining about this?

Because, if you mark a data member as const, then you have to
initialize it somehow at object contruction time -- either through
brace-enclosed initializer or real constructors.  But, now, you go on
putting it in a union, and that union does not even happen to be the
first member.  On the only way you can put a data in that slot is to
assign to it!  That does not look like a reasonable construct. 

-- Gaby

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

* Re: Compiling GCC With a C++ Compiler (g++)
  2004-10-12 23:00     ` Gabriel Dos Reis
@ 2004-10-12 23:23       ` Zack Weinberg
  2004-10-13  2:53         ` Phil Edwards
  2004-10-13  5:49         ` Gabriel Dos Reis
  0 siblings, 2 replies; 63+ messages in thread
From: Zack Weinberg @ 2004-10-12 23:23 UTC (permalink / raw)
  To: Gabriel Dos Reis; +Cc: Geoffrey Keating, Ranjit Mathew, GCC

Gabriel Dos Reis <gdr@cs.tamu.edu> writes:

> Geoffrey Keating <geoffk@apple.com> writes:
> | The 'const' is there to indicate that the string should not be changed
> | once the STRING_CST is created;
>
> And how do you create it?

By casting away the const, as is done in build_string.  Or by
constructing the data in memory before giving it the type with the
const qualifier.

How else do you propose to enforce write-once semantics on a data
structure that is, in fact, write-once?  I am definitely with Geoff
here - this should be allowed (or, to rephrase, if C++ has no
construct which allows what we want to do here, that is a language
deficiency).

zw

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

* Re: Compiling GCC With a C++ Compiler (g++)
  2004-10-12 23:23       ` Zack Weinberg
@ 2004-10-13  2:53         ` Phil Edwards
  2004-10-13  6:24           ` Gabriel Dos Reis
  2004-10-13  9:23           ` Ranjit Mathew
  2004-10-13  5:49         ` Gabriel Dos Reis
  1 sibling, 2 replies; 63+ messages in thread
From: Phil Edwards @ 2004-10-13  2:53 UTC (permalink / raw)
  To: Zack Weinberg; +Cc: Gabriel Dos Reis, Geoffrey Keating, Ranjit Mathew, gcc

On Tue, Oct 12, 2004 at 03:57:56PM -0700, Zack Weinberg wrote:
> Gabriel Dos Reis <gdr@cs.tamu.edu> writes:
> 
> > Geoffrey Keating <geoffk@apple.com> writes:
> > | The 'const' is there to indicate that the string should not be changed
> > | once the STRING_CST is created;
> >
> > And how do you create it?
> 
> By casting away the const, as is done in build_string.  Or by
> constructing the data in memory before giving it the type with the
> const qualifier.

The normal creation process is to do the second approach of the ones
you listed.  The difference is that for C++, that can only be done in one
particular place.  Since member init-lists aren't available for STRING_CST,
we have to cast away the const in build_string -- which essentially plays
the role of a C++ constructor.

The const should stay; C is not C++, and the way in which write-once
constructs are created is just plain /different/ at the source level.
Until we can agree that we should be able to use C++ in the compiler, this
thrashing around trying to make the source acceptable in both languages
is just going to produce heat and noise.


> How else do you propose to enforce write-once semantics on a data
> structure that is, in fact, write-once?  I am definitely with Geoff
> here - this should be allowed (or, to rephrase, if C++ has no
> construct which allows what we want to do here, that is a language
> deficiency).

It does, but only for member functions.  So we can't go there.


Phil

-- 
Behind everything some further thing is found, forever; thus the tree behind
the bird, stone beneath soil, the sun behind Urth.  Behind our efforts, let
there be found our efforts.
              - Ascian saying, as related by Loyal to the Group of Seventeen

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

* Re: Compiling GCC With a C++ Compiler (g++)
  2004-10-12 23:23       ` Zack Weinberg
  2004-10-13  2:53         ` Phil Edwards
@ 2004-10-13  5:49         ` Gabriel Dos Reis
  2004-10-13  9:19           ` Zack Weinberg
  2004-10-13 20:39           ` Geoffrey Keating
  1 sibling, 2 replies; 63+ messages in thread
From: Gabriel Dos Reis @ 2004-10-13  5:49 UTC (permalink / raw)
  To: Zack Weinberg; +Cc: Geoffrey Keating, Ranjit Mathew, GCC

Zack Weinberg <zack@codesourcery.com> writes:

| Gabriel Dos Reis <gdr@cs.tamu.edu> writes:
| 
| > Geoffrey Keating <geoffk@apple.com> writes:
| > | The 'const' is there to indicate that the string should not be changed
| > | once the STRING_CST is created;
| >
| > And how do you create it?
| 
| By casting away the const, as is done in build_string.  Or by
| constructing the data in memory before giving it the type with the
| const qualifier.

In the message I sent, I listed:

   Because, if you mark a data member as const, then you have to
   initialize it somehow at object contruction time -- either through
   brace-enclosed initializer or real constructors.  But, now, you go on
   putting it in a union, and that union does not even happen to be the
   first member.

Constructing the data in memory before giving it the type with the const
qualifier, is morally what C++ constructors do.

The code in build_string

  memset (s, 0, sizeof (struct tree_common));
  TREE_SET_CODE (s, STRING_CST);
  TREE_STRING_LENGTH (s) = len;
  memcpy ((char *) TREE_STRING_POINTER (s), str, len);
  ((char *) TREE_STRING_POINTER (s))[len] = '\0';

is trying to do similar thing, but it is undefined behaviour.

       [#5] If an attempt is made to modify an object defined  with
       a  const-qualified  type  through use of an lvalue with non-
       const-qualified type, the  behavior  is  undefined. 

| How else do you propose to enforce write-once semantics on a data
| structure that is, in fact, write-once?

Notice that the declaration was "const char *pointer" before Geoff's
change. 

| I am definitely with Geoff  here - this should be allowed (or, to

I don't think this is an issue of being "with somebody" as opposed to
writing a code with defined meaning.

| rephrase, if C++ has no  construct which allows what we want to do
| here, that is a language  deficiency).

C++ allows several ways out of this, some may or may not be applicable
to C.  Definitely, the const-casting away is undefined behaviour.
My own rule of thumb is that we one starts fiddling with bytes and
type punning and trickery, something is wrong it is time to think at
least twice about it.

-- Gaby

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

* Re: Compiling GCC With a C++ Compiler (g++)
  2004-10-13  2:53         ` Phil Edwards
@ 2004-10-13  6:24           ` Gabriel Dos Reis
  2004-10-13 10:57             ` Andreas Schwab
                               ` (2 more replies)
  2004-10-13  9:23           ` Ranjit Mathew
  1 sibling, 3 replies; 63+ messages in thread
From: Gabriel Dos Reis @ 2004-10-13  6:24 UTC (permalink / raw)
  To: Phil Edwards; +Cc: Zack Weinberg, Geoffrey Keating, Ranjit Mathew, gcc

Phil Edwards <phil@codesourcery.com> writes:

[...]

| particular place.  Since member init-lists aren't available for STRING_CST,
| we have to cast away the const in build_string

which is undefined behaviour by C rules  (and C++ too).

| The const should stay; C is not C++, and the way in which write-once

Most certainly C is not C++, and nobody is arguing otherwise.
However, there is a large and good intersection of both languages
where useful programs can be expressed through constructs with defined
meaning. 

Taking explicit steps to put in hackery that 

  (1) is undefined behaviour;
  (2) break works to make the compiler compilable with C++ (which was
     agreed upon) is both unproductive and <bip censored>.

-- Gaby

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

* Re: Compiling GCC With a C++ Compiler (g++)
  2004-10-13  5:49         ` Gabriel Dos Reis
@ 2004-10-13  9:19           ` Zack Weinberg
  2004-10-13 13:45             ` Gabriel Dos Reis
  2004-10-13 20:39           ` Geoffrey Keating
  1 sibling, 1 reply; 63+ messages in thread
From: Zack Weinberg @ 2004-10-13  9:19 UTC (permalink / raw)
  To: Gabriel Dos Reis; +Cc: Geoffrey Keating, Ranjit Mathew, GCC

Gabriel Dos Reis <gdr@cs.tamu.edu> writes:

> Zack Weinberg <zack@codesourcery.com> writes:
> | Gabriel Dos Reis <gdr@cs.tamu.edu> writes:
> | > And how do you create it?
> | 
> | By casting away the const, as is done in build_string.  Or by
> | constructing the data in memory before giving it the type with the
> | const qualifier.
>
> Constructing the data in memory before giving it the type with the const
> qualifier, is morally what C++ constructors do.

Yes.  However, a C++ constructor cannot be used here because that's
not part of the intersection of C and C++.  A way needs to be found to
declare and initialize the structure without losing the const and
without leaving the intersection of C and C++.

If the declaration were not ill-formed in C++, then we could find a
variant of the build_string code

>   memset (s, 0, sizeof (struct tree_common));
>   TREE_SET_CODE (s, STRING_CST);
>   TREE_STRING_LENGTH (s) = len;
>   memcpy ((char *) TREE_STRING_POINTER (s), str, len);
>   ((char *) TREE_STRING_POINTER (s))[len] = '\0';

that wasn't undefined behavior, and make everybody happy.  For
instance, I think this is well-defined in both C and C++
[GATHER_STATISTICS logic left out for clarity]

tree
build_string (int len, const char *str)
{
  char *sc = ggc_alloc (sizeof (struct tree_string) + len);
  tree s = (tree) sc;

  memset (s, 0, sizeof (struct tree_common));
  TREE_SET_CODE (s, STRING_CST);
  TREE_STRING_LENGTH (s) = len;

  sc += offsetof (struct tree_string, str);
  memcpy (sc, str, len);
  sc[len] = '\0';

  return s;
}

However, we need a way to write the structure declaration too.  You
would know better than me how that might be accomplished.  (Remember,
only the intersection of C and C++ can be used.)

zw

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

* Re: Compiling GCC With a C++ Compiler (g++)
  2004-10-13  2:53         ` Phil Edwards
  2004-10-13  6:24           ` Gabriel Dos Reis
@ 2004-10-13  9:23           ` Ranjit Mathew
  2004-10-13 13:09             ` Ranjit Mathew
  2004-10-13 13:29             ` Gabriel Dos Reis
  1 sibling, 2 replies; 63+ messages in thread
From: Ranjit Mathew @ 2004-10-13  9:23 UTC (permalink / raw)
  To: Phil Edwards; +Cc: Geoffrey Keating, gcc

On Tue, 12 Oct 2004 19:13:10 -0400, Phil Edwards <phil@codesourcery.com> wrote:
> 
> Until we can agree that we should be able to use C++ in the compiler, this
> thrashing around trying to make the source acceptable in both languages
> is just going to produce heat and noise.

Note that the issue is not about using C++ constructs
in the compiler, but being able to bootstrap using a C++
compiler (thus using only those constructs in GCC that
are kosher in both C and C++).

I thought we had agreed to that:

http://gcc.gnu.org/ml/gcc/2004-07/msg00601.html

In July of this year, there were a flurry of patches
from Bernardo Innocenti and Gabriel Dos Reis allowing
GCC to be bootstrapped using a C++ compiler:

http://gcc.gnu.org/ml/gcc-patches/2004-07/authors.html#02252
http://gcc.gnu.org/ml/gcc-patches/2004-07/authors.html#02300

We shouldn't be undoing their hard work if we can
help it.

In this particular case, we can probably resolve this 
issue by removing "const" from tree_string but adding
"(const char *)" to the definition of TREE_STRING_POINTER
so that for "properly behaving" clients of a STRING_CST,
it is still a constant.

Ranjit.

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

* Re: Compiling GCC With a C++ Compiler (g++)
  2004-10-13  6:24           ` Gabriel Dos Reis
@ 2004-10-13 10:57             ` Andreas Schwab
  2004-10-13 13:16               ` Gabriel Dos Reis
  2004-10-13 11:47             ` Dave Korn
  2004-10-13 20:58             ` Phil Edwards
  2 siblings, 1 reply; 63+ messages in thread
From: Andreas Schwab @ 2004-10-13 10:57 UTC (permalink / raw)
  To: Gabriel Dos Reis
  Cc: Phil Edwards, Zack Weinberg, Geoffrey Keating, Ranjit Mathew, gcc

Gabriel Dos Reis <gdr@cs.tamu.edu> writes:

> Phil Edwards <phil@codesourcery.com> writes:
>
> [...]
>
> | particular place.  Since member init-lists aren't available for STRING_CST,
> | we have to cast away the const in build_string
>
> which is undefined behaviour by C rules  (and C++ too).

Only if the underlying object is really read-only, which it isn't.

Andreas.

-- 
Andreas Schwab, SuSE Labs, schwab@suse.de
SuSE Linux AG, Maxfeldstraße 5, 90409 Nürnberg, Germany
Key fingerprint = 58CA 54C7 6D53 942B 1756  01D3 44D5 214B 8276 4ED5
"And now for something completely different."

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

* RE: Compiling GCC With a C++ Compiler (g++)
  2004-10-13  6:24           ` Gabriel Dos Reis
  2004-10-13 10:57             ` Andreas Schwab
@ 2004-10-13 11:47             ` Dave Korn
  2004-10-13 12:24               ` Andreas Schwab
  2004-10-13 20:58             ` Phil Edwards
  2 siblings, 1 reply; 63+ messages in thread
From: Dave Korn @ 2004-10-13 11:47 UTC (permalink / raw)
  To: 'Gabriel Dos Reis', 'Phil Edwards'
  Cc: 'Zack Weinberg', 'Geoffrey Keating',
	'Ranjit Mathew',
	gcc

> -----Original Message-----
> From: gcc-owner On Behalf Of Gabriel Dos Reis
> Sent: 13 October 2004 04:47

> Phil Edwards writes:
> 
> [...]
> 
> | particular place.  Since member init-lists aren't available 
> for STRING_CST,
> | we have to cast away the const in build_string
> 
> which is undefined behaviour by C rules  (and C++ too).

  I'll bet alias analysis just loves it too.  Wouldn't using tricks like
this lead to a situation in the future (if and) when there's full IPA in gcc
and it can't bootstrap itself reliably any more?

> | The const should stay; C is not C++, and the way in which write-once
> 
> Most certainly C is not C++, and nobody is arguing otherwise.
> However, there is a large and good intersection of both languages
> where useful programs can be expressed through constructs with defined
> meaning. 
> 
> Taking explicit steps to put in hackery that 
> 
>   (1) is undefined behaviour;
>   (2) break works to make the compiler compilable with C++ (which was
>      agreed upon) is both unproductive and <bip censored>.

  Deeply agree.  There are other ways to enforce the desired semantics and
they're to do with good software engineering methodology.

  The entire situation is eerily isomorphic to the thing about
RTX_UNCHANGING_P and stuff that does change but only once..... !


    cheers, 
      DaveK
-- 
Can't think of a witty .sigline today....

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

* Re: Compiling GCC With a C++ Compiler (g++)
  2004-10-13 11:47             ` Dave Korn
@ 2004-10-13 12:24               ` Andreas Schwab
  2004-10-13 13:29                 ` Gabriel Dos Reis
  2004-10-13 19:41                 ` Matt Austern
  0 siblings, 2 replies; 63+ messages in thread
From: Andreas Schwab @ 2004-10-13 12:24 UTC (permalink / raw)
  To: Dave Korn
  Cc: 'Gabriel Dos Reis', 'Phil Edwards',
	'Zack Weinberg', 'Geoffrey Keating',
	'Ranjit Mathew',
	gcc

"Dave Korn" <dk@artimi.com> writes:

>> -----Original Message-----
>> From: gcc-owner On Behalf Of Gabriel Dos Reis
>> Sent: 13 October 2004 04:47
>
>> Phil Edwards writes:
>> 
>> [...]
>> 
>> | particular place.  Since member init-lists aren't available 
>> for STRING_CST,
>> | we have to cast away the const in build_string
>> 
>> which is undefined behaviour by C rules  (and C++ too).
>
>   I'll bet alias analysis just loves it too.  Wouldn't using tricks like
> this lead to a situation in the future (if and) when there's full IPA in gcc
> and it can't bootstrap itself reliably any more?

In C you are always allowed to cast away const and write through the
resulting lvalue as long as the underlying object is not read-only.

Andreas.

-- 
Andreas Schwab, SuSE Labs, schwab@suse.de
SuSE Linux AG, Maxfeldstraße 5, 90409 Nürnberg, Germany
Key fingerprint = 58CA 54C7 6D53 942B 1756  01D3 44D5 214B 8276 4ED5
"And now for something completely different."

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

* Re: Compiling GCC With a C++ Compiler (g++)
  2004-10-13  9:23           ` Ranjit Mathew
@ 2004-10-13 13:09             ` Ranjit Mathew
  2004-10-13 19:13               ` Richard Henderson
  2004-10-13 13:29             ` Gabriel Dos Reis
  1 sibling, 1 reply; 63+ messages in thread
From: Ranjit Mathew @ 2004-10-13 13:09 UTC (permalink / raw)
  To: gcc

On Wed, 13 Oct 2004 11:19:24 +0530, Ranjit Mathew <rmathew@gmail.com> wrote:
> 
> In this particular case, we can probably resolve this
> issue by removing "const" from tree_string but adding
> "(const char *)" to the definition of TREE_STRING_POINTER
> so that for "properly behaving" clients of a STRING_CST,
> it is still a constant.

Like so:

Index: tree.h
===================================================================
--- tree.h      2004-10-13 11:34:28.000000000 +0530
+++ tree.h      2004-10-13 12:22:45.000000000 +0530
@@ -1060,13 +1060,14 @@ struct tree_real_cst GTY(())

 /* In a STRING_CST */
 #define TREE_STRING_LENGTH(NODE) (STRING_CST_CHECK (NODE)->string.length)
-#define TREE_STRING_POINTER(NODE) (STRING_CST_CHECK (NODE)->string.str)
+#define TREE_STRING_POINTER(NODE) \
+  ((const char *)(STRING_CST_CHECK (NODE)->string.str))

 struct tree_string GTY(())
 {
   struct tree_common common;
   int length;
-  const char str[1];
+  char str[1];
 };

 /* In a COMPLEX_CST node.  */

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

* Re: Compiling GCC With a C++ Compiler (g++)
  2004-10-13 10:57             ` Andreas Schwab
@ 2004-10-13 13:16               ` Gabriel Dos Reis
  2004-10-13 13:56                 ` Andreas Schwab
  0 siblings, 1 reply; 63+ messages in thread
From: Gabriel Dos Reis @ 2004-10-13 13:16 UTC (permalink / raw)
  To: Andreas Schwab
  Cc: Phil Edwards, Zack Weinberg, Geoffrey Keating, Ranjit Mathew, gcc

Andreas Schwab <schwab@suse.de> writes:

| Gabriel Dos Reis <gdr@cs.tamu.edu> writes:
| 
| > Phil Edwards <phil@codesourcery.com> writes:
| >
| > [...]
| >
| > | particular place.  Since member init-lists aren't available for STRING_CST,
| > | we have to cast away the const in build_string
| >
| > which is undefined behaviour by C rules  (and C++ too).
| 
| Only if the underlying object is really read-only, which it isn't.

I'm talking about the subobject for the string.  It does not matter
whether the whole object is not declared with const, the point at
issue here is the field that is declared const. 

-- Gaby

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

* Re: Compiling GCC With a C++ Compiler (g++)
  2004-10-13  9:23           ` Ranjit Mathew
  2004-10-13 13:09             ` Ranjit Mathew
@ 2004-10-13 13:29             ` Gabriel Dos Reis
  1 sibling, 0 replies; 63+ messages in thread
From: Gabriel Dos Reis @ 2004-10-13 13:29 UTC (permalink / raw)
  To: Ranjit Mathew; +Cc: Phil Edwards, Geoffrey Keating, gcc

Ranjit Mathew <rmathew@gmail.com> writes:

| In this particular case, we can probably resolve this 
| issue by removing "const" from tree_string but adding
| "(const char *)" to the definition of TREE_STRING_POINTER
| so that for "properly behaving" clients of a STRING_CST,
| it is still a constant.

That is the immediat way I would solve this.  What we want to prevent
is accidental modification.  So the "(const char*)" belongs to the
accessor.  This tree_string is going to be put in a union where a
priori we do not know which is going to be accessed; so the
const cannot belong to the object.  However, we can make sure that
anybody who access that field have the illusion of non-modyfiability.

-- Gaby

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

* Re: Compiling GCC With a C++ Compiler (g++)
  2004-10-13 12:24               ` Andreas Schwab
@ 2004-10-13 13:29                 ` Gabriel Dos Reis
  2004-10-13 14:10                   ` Andreas Schwab
  2004-10-13 19:41                 ` Matt Austern
  1 sibling, 1 reply; 63+ messages in thread
From: Gabriel Dos Reis @ 2004-10-13 13:29 UTC (permalink / raw)
  To: Andreas Schwab
  Cc: Dave Korn, 'Phil Edwards', 'Zack Weinberg',
	'Geoffrey Keating', 'Ranjit Mathew',
	gcc

Andreas Schwab <schwab@suse.de> writes:

| "Dave Korn" <dk@artimi.com> writes:
| 
| >> -----Original Message-----
| >> From: gcc-owner On Behalf Of Gabriel Dos Reis
| >> Sent: 13 October 2004 04:47
| >
| >> Phil Edwards writes:
| >> 
| >> [...]
| >> 
| >> | particular place.  Since member init-lists aren't available 
| >> for STRING_CST,
| >> | we have to cast away the const in build_string
| >> 
| >> which is undefined behaviour by C rules  (and C++ too).
| >
| >   I'll bet alias analysis just loves it too.  Wouldn't using tricks like
| > this lead to a situation in the future (if and) when there's full IPA in gcc
| > and it can't bootstrap itself reliably any more?
| 
| In C you are always allowed to cast away const and write through the
| resulting lvalue as long as the underlying object is not read-only.

That is not true.  
If you can a strcture with const-qualified field, you can modify any
part, except that field.  (I'm talking of C here).

-- Gaby

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

* Re: Compiling GCC With a C++ Compiler (g++)
  2004-10-13  9:19           ` Zack Weinberg
@ 2004-10-13 13:45             ` Gabriel Dos Reis
  0 siblings, 0 replies; 63+ messages in thread
From: Gabriel Dos Reis @ 2004-10-13 13:45 UTC (permalink / raw)
  To: Zack Weinberg; +Cc: Geoffrey Keating, Ranjit Mathew, GCC

Zack Weinberg <zack@codesourcery.com> writes:

[...]

| However, we need a way to write the structure declaration too.  You
| would know better than me how that might be accomplished.  (Remember,
| only the intersection of C and C++ can be used.)


What we want to achieve is that any "unauthorized" person who accesses
the string  cannot modify it.  We can't put the const in the
structure; but we can put "(const char *)" in front of the string
accessor, to pretend it is nonmodifiable.  The patch sent by Ranjit
does a good job.

-- Gaby

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

* Re: Compiling GCC With a C++ Compiler (g++)
  2004-10-13 13:16               ` Gabriel Dos Reis
@ 2004-10-13 13:56                 ` Andreas Schwab
  2004-10-13 14:22                   ` Gabriel Dos Reis
  0 siblings, 1 reply; 63+ messages in thread
From: Andreas Schwab @ 2004-10-13 13:56 UTC (permalink / raw)
  To: Gabriel Dos Reis
  Cc: Phil Edwards, Zack Weinberg, Geoffrey Keating, Ranjit Mathew, gcc

Gabriel Dos Reis <gdr@cs.tamu.edu> writes:

> Andreas Schwab <schwab@suse.de> writes:
>
> | Gabriel Dos Reis <gdr@cs.tamu.edu> writes:
> | 
> | > Phil Edwards <phil@codesourcery.com> writes:
> | >
> | > [...]
> | >
> | > | particular place.  Since member init-lists aren't available for STRING_CST,
> | > | we have to cast away the const in build_string
> | >
> | > which is undefined behaviour by C rules  (and C++ too).
> | 
> | Only if the underlying object is really read-only, which it isn't.
>
> I'm talking about the subobject for the string.

The subobject is still part of a wholly writable object (as returned by
ggc_alloc_tree).

Andreas.

-- 
Andreas Schwab, SuSE Labs, schwab@suse.de
SuSE Linux AG, Maxfeldstraße 5, 90409 Nürnberg, Germany
Key fingerprint = 58CA 54C7 6D53 942B 1756  01D3 44D5 214B 8276 4ED5
"And now for something completely different."

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

* Re: Compiling GCC With a C++ Compiler (g++)
  2004-10-13 13:29                 ` Gabriel Dos Reis
@ 2004-10-13 14:10                   ` Andreas Schwab
  2004-10-13 14:30                     ` Dave Korn
                                       ` (2 more replies)
  0 siblings, 3 replies; 63+ messages in thread
From: Andreas Schwab @ 2004-10-13 14:10 UTC (permalink / raw)
  To: Gabriel Dos Reis
  Cc: Dave Korn, 'Phil Edwards', 'Zack Weinberg',
	'Geoffrey Keating', 'Ranjit Mathew',
	gcc

Gabriel Dos Reis <gdr@cs.tamu.edu> writes:

> If you can a strcture with const-qualified field, you can modify any
> part, except that field.  (I'm talking of C here).

Yes, I'm also talking about C.  And in C you can have const qualified
lvalues that ultimatively denote modifiable objects.  I can't see how it
makes a difference that in this case it is declared as an array, since the
underlying object is clearly writable.

Andreas.

-- 
Andreas Schwab, SuSE Labs, schwab@suse.de
SuSE Linux AG, Maxfeldstraße 5, 90409 Nürnberg, Germany
Key fingerprint = 58CA 54C7 6D53 942B 1756  01D3 44D5 214B 8276 4ED5
"And now for something completely different."

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

* Re: Compiling GCC With a C++ Compiler (g++)
  2004-10-13 13:56                 ` Andreas Schwab
@ 2004-10-13 14:22                   ` Gabriel Dos Reis
  2004-10-13 15:06                     ` Andreas Schwab
  0 siblings, 1 reply; 63+ messages in thread
From: Gabriel Dos Reis @ 2004-10-13 14:22 UTC (permalink / raw)
  To: Andreas Schwab
  Cc: Phil Edwards, Zack Weinberg, Geoffrey Keating, Ranjit Mathew, gcc

Andreas Schwab <schwab@suse.de> writes:

| Gabriel Dos Reis <gdr@cs.tamu.edu> writes:
| 
| > Andreas Schwab <schwab@suse.de> writes:
| >
| > | Gabriel Dos Reis <gdr@cs.tamu.edu> writes:
| > | 
| > | > Phil Edwards <phil@codesourcery.com> writes:
| > | >
| > | > [...]
| > | >
| > | > | particular place.  Since member init-lists aren't available for STRING_CST,
| > | > | we have to cast away the const in build_string
| > | >
| > | > which is undefined behaviour by C rules  (and C++ too).
| > | 
| > | Only if the underlying object is really read-only, which it isn't.
| >
| > I'm talking about the subobject for the string.
| 
| The subobject is still part of a wholly writable object (as returned by
| ggc_alloc_tree).

The fact that the subboject is part of a "whole writebale" object does
not make the subobject suddenly writable.
Looking more closely the language in 6.3.2.1.

       [#1]  An  lvalue  is an expression with an object type or an
       incomplete  type  other  than void;53) if an lvalue does not
       designate an object when it is evaluated,  the  behavior  is
       undefined.   When  an  object  is  said to have a particular
       type, the type is specified by the lvalue used to  designate
       the  object.  A modifiable lvalue is an lvalue that does not
       have array type, does not have an incomplete type, does  not
       have  a  const-qualified  type,  and if it is a structure or
       union, does not have any member (including, recursively, any
       member  or  element  of  all contained aggregates or unions)
       with a const-qualified type.


This language makes any lvalue whose type is whole tree_string
non-modifiable (this rule is very different from C++).  So Geoff's
change introduces undefined behaviour at many places, not just for the
string subobject part. 

-- Gaby

Interestingly, while this appear in the section on "restrict", it
gives you food for thought

       6.7.3.1  Formal definition of restrict

       [#1] Let D be a declaration of an ordinary  identifier  that
       provides  a  means of designating an object P as a restrict-
       qualified pointer to type T.

       [...]

       [#4] During each execution of B, let L be  any  lvalue  that
       has  &L based on P.  If L is used to access the value of the
       object X that it designates, and X is also modified (by  any
       means),  then  the following requirements apply: T shall not
       be const-qualified. [...]

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

* RE: Compiling GCC With a C++ Compiler (g++)
  2004-10-13 14:10                   ` Andreas Schwab
@ 2004-10-13 14:30                     ` Dave Korn
  2004-10-13 14:50                       ` Dave Korn
  2004-10-13 15:04                       ` Joseph S. Myers
  2004-10-13 14:53                     ` Gabriel Dos Reis
  2004-10-13 15:46                     ` Gabriel Dos Reis
  2 siblings, 2 replies; 63+ messages in thread
From: Dave Korn @ 2004-10-13 14:30 UTC (permalink / raw)
  To: 'Andreas Schwab', 'Gabriel Dos Reis'
  Cc: 'Phil Edwards', 'Zack Weinberg',
	'Geoffrey Keating', 'Ranjit Mathew',
	gcc

> -----Original Message-----
> From: Andreas Schwab 
> Sent: 13 October 2004 14:27

> Gabriel Dos Reis writes:
> 
> > If you can a strcture with const-qualified field, you can modify any
> > part, except that field.  (I'm talking of C here).
> 
> Yes, I'm also talking about C.  And in C you can have const qualified
> lvalues that ultimatively denote modifiable objects.  I can't 
> see how it
> makes a difference that in this case it is declared as an 
> array, since the
> underlying object is clearly writable.

  Yes, but it's more complex than just whether the memory area pointed to is
writeable or not.

  If you pass a pointer to a struct as an argument to a function, and there
is a field in the struct that is declared const, the compiler is liable to
assume that the value of that field cannot be modified by the called
function and cache it in registers or stack slots across the function call,
or perhaps make assumptions about known values in the field, that would
become invalid if the callee casts away the constness and modifies the
field.  

  This is a real bug and I've had it happen to me in real-world code[*].

    cheers, 
      DaveK
[*] Well, a variation of it: no struct involved, just a const variable.
-- 
Can't think of a witty .sigline today....

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

* RE: Compiling GCC With a C++ Compiler (g++)
  2004-10-13 14:30                     ` Dave Korn
@ 2004-10-13 14:50                       ` Dave Korn
  2004-10-13 18:25                         ` Andreas Schwab
  2004-10-13 15:04                       ` Joseph S. Myers
  1 sibling, 1 reply; 63+ messages in thread
From: Dave Korn @ 2004-10-13 14:50 UTC (permalink / raw)
  To: 'Dave Korn', 'Andreas Schwab',
	'Gabriel Dos Reis'
  Cc: 'Phil Edwards', 'Zack Weinberg',
	'Geoffrey Keating', 'Ranjit Mathew',
	gcc

> -----Original Message-----
> From: gcc-owner On Behalf Of Dave Korn
> Sent: 13 October 2004 14:45

>   If you pass a pointer to a struct as an argument to a 
> function, and there
> is a field in the struct that is declared const, the compiler 
> is liable to
> assume that the value of that field cannot be modified by the called
> function and cache it in registers or stack slots across the 
> function call,
> or perhaps make assumptions about known values in the field, 
> that would
> become invalid if the callee casts away the constness and modifies the
> field.  
> 
>   This is a real bug and I've had it happen to me in 
> real-world code[*].

... which I eventually worked around in an even more horrible way.

  The problem was in refactoring a huge amount of legacy code that used a
vast number of global variables.  To try and modularise and data-hide it
somewhat I wanted them all to become local to a single module, with accessor
functions visible to the rest of the application.  So I declared them all
"extern CONST" in a header file.  When a client module wanted to include the
header file, it got CONST defined as "const", but when the same header was
included by the module that instantiated the variables, CONST was defined to
nothing.  This allowed me to simulate protected class member variables, but
had the aforementioned consequence on the optimiser.

  The workaround was to declare them volatile as well as const to the client
modules.  Evil, I know, but it did the job; and in some sense, it's valid to
represent those variables to the rest of the application as
read-only-but-unpredictably-changing, a bit like a hardware register.

    cheers, 
      DaveK
-- 
Can't think of a witty .sigline today....

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

* Re: Compiling GCC With a C++ Compiler (g++)
  2004-10-13 14:10                   ` Andreas Schwab
  2004-10-13 14:30                     ` Dave Korn
@ 2004-10-13 14:53                     ` Gabriel Dos Reis
  2004-10-13 15:46                     ` Gabriel Dos Reis
  2 siblings, 0 replies; 63+ messages in thread
From: Gabriel Dos Reis @ 2004-10-13 14:53 UTC (permalink / raw)
  To: Andreas Schwab
  Cc: Dave Korn, 'Phil Edwards', 'Zack Weinberg',
	'Geoffrey Keating', 'Ranjit Mathew',
	gcc

Andreas Schwab <schwab@suse.de> writes:

| Gabriel Dos Reis <gdr@cs.tamu.edu> writes:
| 
| > If you can a strcture with const-qualified field, you can modify any
| > part, except that field.  (I'm talking of C here).
| 
| Yes, I'm also talking about C.  And in C you can have const qualified
| lvalues that ultimatively denote modifiable objects.

But, in the tree_string case, it is not a modifiable object.  See the
language I quoted in the other message.

| I can't see how it
| makes a difference that in this case it is declared as an array, since the
| underlying object is clearly writable.

It is not the fact that the field is declared an array, it is the fact
it is declared an array of *const* T.

Notice, Geoff made the following justification:

  The 'const' is there to indicate that the string should not be changed
  once the STRING_CST is created; STRING_CSTs may be shared.

but you can't have it both way: it can't be modifiable and
nonmodifiable.  C says that if any member is const-qualified, the
whole stuff becomes non-modifiable.  That put a several restriction on
how you can construct it.  Either through brace-enclosed
initializer-list or fiddlinig with bytes before giving the tree_string
type. 

Plus, this apply to the tree_node union too.  I believe we have
reached a point where the change is clearly a bug.

-- Gaby

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

* RE: Compiling GCC With a C++ Compiler (g++)
  2004-10-13 14:30                     ` Dave Korn
  2004-10-13 14:50                       ` Dave Korn
@ 2004-10-13 15:04                       ` Joseph S. Myers
  2004-10-13 17:01                         ` Dave Korn
  1 sibling, 1 reply; 63+ messages in thread
From: Joseph S. Myers @ 2004-10-13 15:04 UTC (permalink / raw)
  To: Dave Korn
  Cc: 'Andreas Schwab', 'Gabriel Dos Reis',
	'Phil Edwards', 'Zack Weinberg',
	'Geoffrey Keating', 'Ranjit Mathew',
	gcc

On Wed, 13 Oct 2004, Dave Korn wrote:

>   If you pass a pointer to a struct as an argument to a function, and there
> is a field in the struct that is declared const, the compiler is liable to
> assume that the value of that field cannot be modified by the called
> function and cache it in registers or stack slots across the function call,
> or perhaps make assumptions about known values in the field, that would
> become invalid if the callee casts away the constness and modifies the
> field.  

Wrong.  Even with "restrict" you can't make such assumptions in the caller 
unless you can see the definition of the function (whether the parameter 
is declared with "restrict" may differ between function declarations and 
the definition) and know that the function has no other access to that 
object (it might not use the restricted pointer argument at all, and 
access and modify the object through some other pointer it has access to).  
Without "restrict" the only relevant undefined behavior is if the object 
is *defined* with qualified type (6.7.3#5).  This can apply with static or 
automatic storage duration declarations such as

  struct { const char x } y = { z };

but cannot apply to an object of allocated storage duration.

> [*] Well, a variation of it: no struct involved, just a const variable.

If the variable is declared const

  const int y;

then indeed it can't be modified.  But if you do

  const int *y = malloc(sizeof(const int));

then you can modify *(int *)y.  (Strictly, the conversion from const int * 
to int * isn't guaranteed to preserve the value of the pointer, but as int 
* and const int * have the same representation and alignment requirements 
the called function could copy the value using memcpy.)

-- 
Joseph S. Myers               http://www.srcf.ucam.org/~jsm28/gcc/
    jsm@polyomino.org.uk (personal mail)
    joseph@codesourcery.com (CodeSourcery mail)
    jsm28@gcc.gnu.org (Bugzilla assignments and CCs)

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

* Re: Compiling GCC With a C++ Compiler (g++)
  2004-10-13 14:22                   ` Gabriel Dos Reis
@ 2004-10-13 15:06                     ` Andreas Schwab
  2004-10-13 15:22                       ` Gabriel Dos Reis
  0 siblings, 1 reply; 63+ messages in thread
From: Andreas Schwab @ 2004-10-13 15:06 UTC (permalink / raw)
  To: Gabriel Dos Reis
  Cc: Phil Edwards, Zack Weinberg, Geoffrey Keating, Ranjit Mathew, gcc

Gabriel Dos Reis <gdr@cs.tamu.edu> writes:

> The fact that the subboject is part of a "whole writebale" object does
> not make the subobject suddenly writable.

But it is writable in the first place.  Just because a const-qualified
lvalue is used in some places does not make the object suddenly read-only.

> Looking more closely the language in 6.3.2.1.
>
>        [#1]  An  lvalue  is an expression with an object type or an
>        incomplete  type  other  than void;53) if an lvalue does not
>        designate an object when it is evaluated,  the  behavior  is
>        undefined.   When  an  object  is  said to have a particular
>        type, the type is specified by the lvalue used to  designate
>        the  object.  A modifiable lvalue is an lvalue that does not
>        have array type, does not have an incomplete type, does  not
>        have  a  const-qualified  type,  and if it is a structure or
>        union, does not have any member (including, recursively, any
>        member  or  element  of  all contained aggregates or unions)
>        with a const-qualified type.
>
>
> This language makes any lvalue whose type is whole tree_string
> non-modifiable (this rule is very different from C++).

... through that const-qualified lvalue.  But you can create a different
lvalue (by casting) through which you can modify the object.

> Interestingly, while this appear in the section on "restrict", it
> gives you food for thought

I don't see any restrict qualification here.

Andreas.

-- 
Andreas Schwab, SuSE Labs, schwab@suse.de
SuSE Linux AG, Maxfeldstraße 5, 90409 Nürnberg, Germany
Key fingerprint = 58CA 54C7 6D53 942B 1756  01D3 44D5 214B 8276 4ED5
"And now for something completely different."

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

* Re: Compiling GCC With a C++ Compiler (g++)
  2004-10-13 15:06                     ` Andreas Schwab
@ 2004-10-13 15:22                       ` Gabriel Dos Reis
  2004-10-13 15:33                         ` Andreas Schwab
  0 siblings, 1 reply; 63+ messages in thread
From: Gabriel Dos Reis @ 2004-10-13 15:22 UTC (permalink / raw)
  To: Andreas Schwab
  Cc: Phil Edwards, Zack Weinberg, Geoffrey Keating, Ranjit Mathew, gcc

Andreas Schwab <schwab@suse.de> writes:

| Gabriel Dos Reis <gdr@cs.tamu.edu> writes:
| 
| > The fact that the subboject is part of a "whole writebale" object does
| > not make the subobject suddenly writable.
| 
| But it is writable in the first place.  Just because a const-qualified
| lvalue is used in some places does not make the object suddenly read-only.


Sure, Look at the language I quote below.

| > Looking more closely the language in 6.3.2.1.
| >
| >        [#1]  An  lvalue  is an expression with an object type or an
| >        incomplete  type  other  than void;53) if an lvalue does not
| >        designate an object when it is evaluated,  the  behavior  is
| >        undefined.   When  an  object  is  said to have a particular
| >        type, the type is specified by the lvalue used to  designate
| >        the  object.  A modifiable lvalue is an lvalue that does not
| >        have array type, does not have an incomplete type, does  not
| >        have  a  const-qualified  type,  and if it is a structure or
| >        union, does not have any member (including, recursively, any
| >        member  or  element  of  all contained aggregates or unions)
| >        with a const-qualified type.
| >
| >
| > This language makes any lvalue whose type is whole tree_string
| > non-modifiable (this rule is very different from C++).
| 
| ... through that const-qualified lvalue.  But you can create a different
| lvalue (by casting) through which you can modify the object.

Look at the current implementation of build_string

    tree
    build_string (int len, const char *str)
    {
      tree s;
      size_t length;

      length = len + sizeof (struct tree_string);

    #ifdef GATHER_STATISTICS
      tree_node_counts[(int) c_kind]++;
      tree_node_sizes[(int) c_kind] += length;
    #endif  

      s = ggc_alloc_tree (length);

      memset (s, 0, sizeof (struct tree_common));
      TREE_SET_CODE (s, STRING_CST);
      TREE_STRING_LENGTH (s) = len;
      memcpy ((char *) TREE_STRING_POINTER (s), str, len);
      ((char *) TREE_STRING_POINTER (s))[len] = '\0';

      return s;
    }

The lvalue "s" is just nonmodifiable aoocording to the above language.

And the situation get worse as tree_string is also a member of
tree_node, and therefore this change affects all other uses of the
union tree_node that modify its value.

| 
| > Interestingly, while this appear in the section on "restrict", it
| > gives you food for thought
| 
| I don't see any restrict qualification here.

Which is probably why I do not give it as the main justification of
why Geoff's change introduces undefined behaviour?

We need to bring the header back to the intersection of C and C++.

-- Gaby

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

* Re: Compiling GCC With a C++ Compiler (g++)
  2004-10-13 15:22                       ` Gabriel Dos Reis
@ 2004-10-13 15:33                         ` Andreas Schwab
  2004-10-13 18:20                           ` Gabriel Dos Reis
  0 siblings, 1 reply; 63+ messages in thread
From: Andreas Schwab @ 2004-10-13 15:33 UTC (permalink / raw)
  To: Gabriel Dos Reis
  Cc: Phil Edwards, Zack Weinberg, Geoffrey Keating, Ranjit Mathew, gcc

Gabriel Dos Reis <gdr@cs.tamu.edu> writes:

> Look at the current implementation of build_string
>
>     tree
>     build_string (int len, const char *str)
>     {
>       tree s;
>       size_t length;
[...]
>       s = ggc_alloc_tree (length);
>
[...]
>
>       return s;
>     }
>
> The lvalue "s" is just nonmodifiable aoocording to the above language.

(You probably mean "*s", since s is not const qualified).  But the object
returned by ggc_alloc_tree _is_ modfiable.  And this is what matters here.
Just like

  const int *foo() { return malloc (sizeof (int)); }

returns a pointer to a modfiable object, although the lvalue *foo() isn't.

Andreas.

-- 
Andreas Schwab, SuSE Labs, schwab@suse.de
SuSE Linux AG, Maxfeldstraße 5, 90409 Nürnberg, Germany
Key fingerprint = 58CA 54C7 6D53 942B 1756  01D3 44D5 214B 8276 4ED5
"And now for something completely different."

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

* Re: Compiling GCC With a C++ Compiler (g++)
  2004-10-13 14:10                   ` Andreas Schwab
  2004-10-13 14:30                     ` Dave Korn
  2004-10-13 14:53                     ` Gabriel Dos Reis
@ 2004-10-13 15:46                     ` Gabriel Dos Reis
  2 siblings, 0 replies; 63+ messages in thread
From: Gabriel Dos Reis @ 2004-10-13 15:46 UTC (permalink / raw)
  To: Andreas Schwab
  Cc: Dave Korn, 'Phil Edwards', 'Zack Weinberg',
	'Geoffrey Keating', 'Ranjit Mathew',
	gcc

Andreas Schwab <schwab@suse.de> writes:

| Gabriel Dos Reis <gdr@cs.tamu.edu> writes:
| 
| > If you can a strcture with const-qualified field, you can modify any
| > part, except that field.  (I'm talking of C here).
| 
| Yes, I'm also talking about C.  And in C you can have const qualified
| lvalues that ultimatively denote modifiable objects.

I forgot to acknowledge that, you have similar situations in C++ too.

When you get

     const int* p;

*p is nonmodifiable, not that does not mean that the real object
behind  *p is actually nonmodifiable. 

But that is not the situation we have here.

-- Gaby

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

* RE: Compiling GCC With a C++ Compiler (g++)
  2004-10-13 15:04                       ` Joseph S. Myers
@ 2004-10-13 17:01                         ` Dave Korn
  2004-10-13 21:16                           ` Geoffrey Keating
  0 siblings, 1 reply; 63+ messages in thread
From: Dave Korn @ 2004-10-13 17:01 UTC (permalink / raw)
  To: 'Joseph S. Myers'
  Cc: 'Andreas Schwab', 'Gabriel Dos Reis',
	'Phil Edwards', 'Zack Weinberg',
	'Geoffrey Keating', 'Ranjit Mathew',
	gcc

> -----Original Message-----
> From: Joseph S. Myers  
> Sent: 13 October 2004 15:10

> Without "restrict" the only relevant undefined behavior is if 
> the object 
> is *defined* with qualified type (6.7.3#5).  This can apply 
> with static or 
> automatic storage duration declarations such as
> 
>   struct { const char x } y = { z };
> 
> but cannot apply to an object of allocated storage duration.

  Huh?  Are you saying that in:

typedef struct { const char x } AA;

AA *py1, py2;
AA y1 = { z };

  py1 = malloc (sizeof *py2);
  py2 = &y1;

it is valid to say

  *(char *)(&py1->x) = '?';

but not valid to say

  *(char *)(&py2->x) = '?';

?  I think I may have reached the point at which I am starting to
boggle.....


    cheers, 
      DaveK
-- 
Can't think of a witty .sigline today....

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

* Re: Compiling GCC With a C++ Compiler (g++)
  2004-10-13 15:33                         ` Andreas Schwab
@ 2004-10-13 18:20                           ` Gabriel Dos Reis
  2004-10-13 19:09                             ` Andreas Schwab
  0 siblings, 1 reply; 63+ messages in thread
From: Gabriel Dos Reis @ 2004-10-13 18:20 UTC (permalink / raw)
  To: Andreas Schwab
  Cc: Phil Edwards, Zack Weinberg, Geoffrey Keating, Ranjit Mathew, gcc

Andreas Schwab <schwab@suse.de> writes:

| Gabriel Dos Reis <gdr@cs.tamu.edu> writes:
| 
| > Look at the current implementation of build_string
| >
| >     tree
| >     build_string (int len, const char *str)
| >     {
| >       tree s;
| >       size_t length;
| [...]
| >       s = ggc_alloc_tree (length);
| >
| [...]
| >
| >       return s;
| >     }
| >
| > The lvalue "s" is just nonmodifiable aoocording to the above language.
| 
| (You probably mean "*s", since s is not const qualified). 

Yes.

| But the object
| returned by ggc_alloc_tree _is_ modfiable.  And this is what matters here.
| Just like
| 
|   const int *foo() { return malloc (sizeof (int)); }
| 
| returns a pointer to a modfiable object, although the lvalue *foo() isn't.

You left too much out of my message.  As I'm in hurry to get
something else done, I'll return back to you later, but in the
meantime, let me point out one thing:

   Assume you can modify *s, then you still don't get anything useful
   from Geoff's change, because the string could be modified anyway.
   Therefore the "const" is there only to damage work done in the
   direction of being able to compile GCC source with a C++ compiler.

-- Gaby

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

* Re: Compiling GCC With a C++ Compiler (g++)
  2004-10-13 14:50                       ` Dave Korn
@ 2004-10-13 18:25                         ` Andreas Schwab
  0 siblings, 0 replies; 63+ messages in thread
From: Andreas Schwab @ 2004-10-13 18:25 UTC (permalink / raw)
  To: Dave Korn
  Cc: 'Gabriel Dos Reis', 'Phil Edwards',
	'Zack Weinberg', 'Geoffrey Keating',
	'Ranjit Mathew',
	gcc

"Dave Korn" <dk@artimi.com> writes:

>   The problem was in refactoring a huge amount of legacy code that used a
> vast number of global variables.  To try and modularise and data-hide it
> somewhat I wanted them all to become local to a single module, with accessor
> functions visible to the rest of the application.  So I declared them all
> "extern CONST" in a header file.  When a client module wanted to include the
> header file, it got CONST defined as "const", but when the same header was
> included by the module that instantiated the variables, CONST was defined to
> nothing.  This allowed me to simulate protected class member variables, but
> had the aforementioned consequence on the optimiser.

IMHO this is a rather different situation.  Since the declaration says
const the compiler can assume that the definition also says const (since
they must match), and that the object is really read-only.

On some platforms such a program may even fail to compile because the
method to access read-only objects may be incompatible that of writable
objects.

Andreas.

-- 
Andreas Schwab, SuSE Labs, schwab@suse.de
SuSE Linux AG, Maxfeldstraße 5, 90409 Nürnberg, Germany
Key fingerprint = 58CA 54C7 6D53 942B 1756  01D3 44D5 214B 8276 4ED5
"And now for something completely different."

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

* Re: Compiling GCC With a C++ Compiler (g++)
  2004-10-13 18:20                           ` Gabriel Dos Reis
@ 2004-10-13 19:09                             ` Andreas Schwab
  0 siblings, 0 replies; 63+ messages in thread
From: Andreas Schwab @ 2004-10-13 19:09 UTC (permalink / raw)
  To: Gabriel Dos Reis
  Cc: Phil Edwards, Zack Weinberg, Geoffrey Keating, Ranjit Mathew, gcc

Gabriel Dos Reis <gdr@cs.tamu.edu> writes:

>    Assume you can modify *s, then you still don't get anything useful
>    from Geoff's change, because the string could be modified anyway.
>    Therefore the "const" is there only to damage work done in the
>    direction of being able to compile GCC source with a C++ compiler.

If C++ has a stricter meaning for const than C then we need to adhere to
this stricter meaning when we want to compile with a C++ compiler.  But
that isn't the point I tried to make, I was only disputing the claim that
Geoff's change introduces undefined behaviour in C.

Andreas.

-- 
Andreas Schwab, SuSE Labs, schwab@suse.de
SuSE Linux AG, Maxfeldstraße 5, 90409 Nürnberg, Germany
Key fingerprint = 58CA 54C7 6D53 942B 1756  01D3 44D5 214B 8276 4ED5
"And now for something completely different."

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

* Re: Compiling GCC With a C++ Compiler (g++)
  2004-10-13 13:09             ` Ranjit Mathew
@ 2004-10-13 19:13               ` Richard Henderson
  2004-10-13 21:55                 ` Gabriel Dos Reis
  0 siblings, 1 reply; 63+ messages in thread
From: Richard Henderson @ 2004-10-13 19:13 UTC (permalink / raw)
  To: Ranjit Mathew; +Cc: gcc

On Wed, Oct 13, 2004 at 06:05:57PM +0530, Ranjit Mathew wrote:
>  #define TREE_STRING_LENGTH(NODE) (STRING_CST_CHECK (NODE)->string.length)
> -#define TREE_STRING_POINTER(NODE) (STRING_CST_CHECK (NODE)->string.str)
> +#define TREE_STRING_POINTER(NODE) \
> +  ((const char *)(STRING_CST_CHECK (NODE)->string.str))
> 
>  struct tree_string GTY(())
>  {
>    struct tree_common common;
>    int length;
> -  const char str[1];
> +  char str[1];

This is ok.


r~

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

* Re: Compiling GCC With a C++ Compiler (g++)
  2004-10-13 12:24               ` Andreas Schwab
  2004-10-13 13:29                 ` Gabriel Dos Reis
@ 2004-10-13 19:41                 ` Matt Austern
  2004-10-13 20:29                   ` Andreas Schwab
  1 sibling, 1 reply; 63+ messages in thread
From: Matt Austern @ 2004-10-13 19:41 UTC (permalink / raw)
  To: Andreas Schwab
  Cc: 'Gabriel Dos Reis', 'Zack Weinberg',
	'Ranjit Mathew', 'Phil Edwards',
	gcc, Dave Korn, 'Geoffrey Keating'

On Oct 13, 2004, at 3:09 AM, Andreas Schwab wrote:

> "Dave Korn" <dk@artimi.com> writes:
>
>>> -----Original Message-----
>>> From: gcc-owner On Behalf Of Gabriel Dos Reis
>>> Sent: 13 October 2004 04:47
>>
>>> Phil Edwards writes:
>>>
>>> [...]
>>>
>>> | particular place.  Since member init-lists aren't available
>>> for STRING_CST,
>>> | we have to cast away the const in build_string
>>>
>>> which is undefined behaviour by C rules  (and C++ too).
>>
>>   I'll bet alias analysis just loves it too.  Wouldn't using tricks 
>> like
>> this lead to a situation in the future (if and) when there's full IPA 
>> in gcc
>> and it can't bootstrap itself reliably any more?
>
> In C you are always allowed to cast away const and write through the
> resulting lvalue as long as the underlying object is not read-only.

I think this discussion is probably best conducted using precisely the 
wording in the C standard.  I don't believe the phrase "read-only" is 
defined in that standard.  Here's my analysis.

Clause 6.7.3/5 says "If an attempt is made to modify an object defined 
with a const-qualified type through use of an lvalue with 
non-const-qualified type, the behavior is undefined."

Clause 6.2.5/25 says what a const-qualified type is: "Each unqualified 
type has several qualified versions of its type, corresponding to the 
combinations of one, two, or all three of the const, volatile, and 
restrict qualifiers."

In this case we're dealing with a structure one of whose fields has a 
const-qualified type.  So the only remaining question is whether a 
single field can be an object.  The answer is yes: clause 3.14 defines 
object, and the definition is very general: a "region of data storage 
in the execution environment, the contents of which can represent 
values."

So I believe that this is undefined behavior in C.  We can probably get 
away with it, but it would also probably be better to find a way of 
doing this that doesn't invoke undefined behavior.

			--Matt

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

* Re: Compiling GCC With a C++ Compiler (g++)
  2004-10-13 19:41                 ` Matt Austern
@ 2004-10-13 20:29                   ` Andreas Schwab
  2004-10-13 20:41                     ` Matt Austern
  0 siblings, 1 reply; 63+ messages in thread
From: Andreas Schwab @ 2004-10-13 20:29 UTC (permalink / raw)
  To: Matt Austern
  Cc: 'Gabriel Dos Reis', 'Zack Weinberg',
	'Ranjit Mathew', 'Phil Edwards',
	gcc, Dave Korn, 'Geoffrey Keating'

Matt Austern <austern@apple.com> writes:

> I think this discussion is probably best conducted using precisely the
> wording in the C standard.  I don't believe the phrase "read-only" is
> defined in that standard.  Here's my analysis.
>
> Clause 6.7.3/5 says "If an attempt is made to modify an object defined
> with a const-qualified type through use of an lvalue with
> non-const-qualified type, the behavior is undefined."

Do we have an "object defined with a const-qualified type" in the first
place?  I don't think we have.  The object in question is obtained by the
equivalent of malloc() (called ggc_alloc_stat here) which returns a
modifiable object with a non-qualified type.

Andreas.

-- 
Andreas Schwab, SuSE Labs, schwab@suse.de
SuSE Linux AG, Maxfeldstraße 5, 90409 Nürnberg, Germany
Key fingerprint = 58CA 54C7 6D53 942B 1756  01D3 44D5 214B 8276 4ED5
"And now for something completely different."

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

* Re: Compiling GCC With a C++ Compiler (g++)
  2004-10-13  5:49         ` Gabriel Dos Reis
  2004-10-13  9:19           ` Zack Weinberg
@ 2004-10-13 20:39           ` Geoffrey Keating
  2004-10-13 21:45             ` Gabriel Dos Reis
  1 sibling, 1 reply; 63+ messages in thread
From: Geoffrey Keating @ 2004-10-13 20:39 UTC (permalink / raw)
  To: Gabriel Dos Reis; +Cc: GCC, Ranjit Mathew, Zack Weinberg

[-- Attachment #1: Type: text/plain, Size: 850 bytes --]


On 12/10/2004, at 8:42 PM, Gabriel Dos Reis wrote:

> The code in build_string
>
>   memset (s, 0, sizeof (struct tree_common));
>   TREE_SET_CODE (s, STRING_CST);
>   TREE_STRING_LENGTH (s) = len;
>   memcpy ((char *) TREE_STRING_POINTER (s), str, len);
>   ((char *) TREE_STRING_POINTER (s))[len] = '\0';
>
> is trying to do similar thing, but it is undefined behaviour.
>
>        [#5] If an attempt is made to modify an object defined  with
>        a  const-qualified  type  through use of an lvalue with non-
>        const-qualified type, the  behavior  is  undefined.

The object here is '*s', which was not defined with a const-qualified 
type.  It's not defined with any type at all, it was allocated through 
malloc which is not a typed interface.  (It would be different if it 
was allocated through 'new', but we do not have new in C.)

[-- Attachment #2: smime.p7s --]
[-- Type: application/pkcs7-signature, Size: 2408 bytes --]

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

* Re: Compiling GCC With a C++ Compiler (g++)
  2004-10-13 20:29                   ` Andreas Schwab
@ 2004-10-13 20:41                     ` Matt Austern
  0 siblings, 0 replies; 63+ messages in thread
From: Matt Austern @ 2004-10-13 20:41 UTC (permalink / raw)
  To: Andreas Schwab
  Cc: 'Gabriel Dos Reis', 'Zack Weinberg',
	'Ranjit Mathew', 'Phil Edwards',
	gcc, Dave Korn, 'Geoffrey Keating'


On Oct 13, 2004, at 12:09 PM, Andreas Schwab wrote:

> Matt Austern <austern@apple.com> writes:
>
>> I think this discussion is probably best conducted using precisely the
>> wording in the C standard.  I don't believe the phrase "read-only" is
>> defined in that standard.  Here's my analysis.
>>
>> Clause 6.7.3/5 says "If an attempt is made to modify an object defined
>> with a const-qualified type through use of an lvalue with
>> non-const-qualified type, the behavior is undefined."
>
> Do we have an "object defined with a const-qualified type" in the first
> place?  I don't think we have.  The object in question is obtained by 
> the
> equivalent of malloc() (called ggc_alloc_stat here) which returns a
> modifiable object with a non-qualified type.

You're right, sorry.

			--Matt

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

* Re: Compiling GCC With a C++ Compiler (g++)
  2004-10-13  6:24           ` Gabriel Dos Reis
  2004-10-13 10:57             ` Andreas Schwab
  2004-10-13 11:47             ` Dave Korn
@ 2004-10-13 20:58             ` Phil Edwards
  2 siblings, 0 replies; 63+ messages in thread
From: Phil Edwards @ 2004-10-13 20:58 UTC (permalink / raw)
  To: Gabriel Dos Reis; +Cc: gcc

On Tue, Oct 12, 2004 at 10:47:06PM -0500, Gabriel Dos Reis wrote:
> Phil Edwards <phil@codesourcery.com> writes:
> 
> | The const should stay; C is not C++, and the way in which write-once
> 
> Most certainly C is not C++, and nobody is arguing otherwise.
> However, there is a large and good intersection of both languages
> where useful programs can be expressed through constructs with defined
> meaning. 

I'm not going to get involved in this discussion again, at least not until
we've agreed to throw out C as the implementation language.  I'll agree to
any patch which will get me out of the Cc: list of this eternal thread.  :-(


-- 
Behind everything some further thing is found, forever; thus the tree behind
the bird, stone beneath soil, the sun behind Urth.  Behind our efforts, let
there be found our efforts.
              - Ascian saying, as related by Loyal to the Group of Seventeen

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

* Re: Compiling GCC With a C++ Compiler (g++)
  2004-10-13 17:01                         ` Dave Korn
@ 2004-10-13 21:16                           ` Geoffrey Keating
  2004-10-14 13:26                             ` Dave Korn
  0 siblings, 1 reply; 63+ messages in thread
From: Geoffrey Keating @ 2004-10-13 21:16 UTC (permalink / raw)
  To: Dave Korn
  Cc: 'Joseph S. Myers', 'Zack Weinberg',
	'Ranjit Mathew', 'Phil Edwards',
	gcc, 'Andreas Schwab', 'Gabriel Dos Reis'

[-- Attachment #1: Type: text/plain, Size: 913 bytes --]


On 13/10/2004, at 8:23 AM, Dave Korn wrote:

>> -----Original Message-----
>> From: Joseph S. Myers
>> Sent: 13 October 2004 15:10
>
>> Without "restrict" the only relevant undefined behavior is if
>> the object
>> is *defined* with qualified type (6.7.3#5).  This can apply
>> with static or
>> automatic storage duration declarations such as
>>
>>   struct { const char x } y = { z };
>>
>> but cannot apply to an object of allocated storage duration.
>
>   Huh?  Are you saying that in:
>
> typedef struct { const char x } AA;
>
> AA *py1, py2;
> AA y1 = { z };
>
>   py1 = malloc (sizeof *py2);
>   py2 = &y1;
>
> it is valid to say
>
>   *(char *)(&py1->x) = '?';
>
> but not valid to say
>
>   *(char *)(&py2->x) = '?';

Yes, that sounds right.

As a simpler example, given

static const int x = 3;
static int y = 4;

it is valid to say

*(int *)(const int *)&y = 4;

but not

*(int *)(const int *)&x = 4;

[-- Attachment #2: smime.p7s --]
[-- Type: application/pkcs7-signature, Size: 2408 bytes --]

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

* Re: Compiling GCC With a C++ Compiler (g++)
  2004-10-13 20:39           ` Geoffrey Keating
@ 2004-10-13 21:45             ` Gabriel Dos Reis
  2004-10-13 22:15               ` Geoffrey Keating
  0 siblings, 1 reply; 63+ messages in thread
From: Gabriel Dos Reis @ 2004-10-13 21:45 UTC (permalink / raw)
  To: Geoffrey Keating; +Cc: GCC, Ranjit Mathew, Zack Weinberg

Geoffrey Keating <geoffk@apple.com> writes:

| On 12/10/2004, at 8:42 PM, Gabriel Dos Reis wrote:
| 
| > The code in build_string
| >
| >   memset (s, 0, sizeof (struct tree_common));
| >   TREE_SET_CODE (s, STRING_CST);
| >   TREE_STRING_LENGTH (s) = len;
| >   memcpy ((char *) TREE_STRING_POINTER (s), str, len);
| >   ((char *) TREE_STRING_POINTER (s))[len] = '\0';
| >
| > is trying to do similar thing, but it is undefined behaviour.
| >
| >        [#5] If an attempt is made to modify an object defined  with
| >        a  const-qualified  type  through use of an lvalue with non-
| >        const-qualified type, the  behavior  is  undefined.
| 
| The object here is '*s', which was not defined with a const-qualified
| type.  It's not defined with any type at all, it was allocated through
| malloc which is not a typed interface.  (It would be different if it
| was allocated through 'new', but we do not have new in C.)

The undefined behaviour comes from different sources.
Consider the following:

   typedef struct {
      int fu;
      const int bhar;
   } S;

   void f(S *p)
   {
       (*p).fu = 90;            // #1
   }

Do you believe line #1 is valid in face of

       [#1]  An  lvalue  is an expression with an object type or an
       incomplete  type  other  than void;53) if an lvalue does not
       designate an object when it is evaluated,  the  behavior  is
       undefined.   When  an  object  is  said to have a particular
       type, the type is specified by the lvalue used to  designate
       the  object.  A modifiable lvalue is an lvalue that does not
       have array type, does not have an incomplete type, does  not
       have  a  const-qualified  type,  and if it is a structure or
       union, does not have any member (including, recursively, any
       member  or  element  of  all contained aggregates or unions)
       with a const-qualified type.

?

Notice that here, it is not a question of where the object pointed to 
by *p comes from.  

Next question is for

   void g(S *p)
   {
       p->fu = 90;
   }

-- Gaby

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

* Re: Compiling GCC With a C++ Compiler (g++)
  2004-10-13 19:13               ` Richard Henderson
@ 2004-10-13 21:55                 ` Gabriel Dos Reis
  0 siblings, 0 replies; 63+ messages in thread
From: Gabriel Dos Reis @ 2004-10-13 21:55 UTC (permalink / raw)
  To: Richard Henderson; +Cc: Ranjit Mathew, gcc

Richard Henderson <rth@redhat.com> writes:

| On Wed, Oct 13, 2004 at 06:05:57PM +0530, Ranjit Mathew wrote:
| >  #define TREE_STRING_LENGTH(NODE) (STRING_CST_CHECK (NODE)->string.length)
| > -#define TREE_STRING_POINTER(NODE) (STRING_CST_CHECK (NODE)->string.str)
| > +#define TREE_STRING_POINTER(NODE) \
| > +  ((const char *)(STRING_CST_CHECK (NODE)->string.str))
| > 
| >  struct tree_string GTY(())
| >  {
| >    struct tree_common common;
| >    int length;
| > -  const char str[1];
| > +  char str[1];
| 
| This is ok.

Thanks.

-- Gaby

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

* Re: Compiling GCC With a C++ Compiler (g++)
  2004-10-13 21:45             ` Gabriel Dos Reis
@ 2004-10-13 22:15               ` Geoffrey Keating
  2004-10-13 22:24                 ` Gabriel Dos Reis
  0 siblings, 1 reply; 63+ messages in thread
From: Geoffrey Keating @ 2004-10-13 22:15 UTC (permalink / raw)
  To: Gabriel Dos Reis; +Cc: GCC, Ranjit Mathew, Zack Weinberg

[-- Attachment #1: Type: text/plain, Size: 2474 bytes --]


On 13/10/2004, at 1:39 PM, Gabriel Dos Reis wrote:

> Geoffrey Keating <geoffk@apple.com> writes:
>
> | On 12/10/2004, at 8:42 PM, Gabriel Dos Reis wrote:
> |
> | > The code in build_string
> | >
> | >   memset (s, 0, sizeof (struct tree_common));
> | >   TREE_SET_CODE (s, STRING_CST);
> | >   TREE_STRING_LENGTH (s) = len;
> | >   memcpy ((char *) TREE_STRING_POINTER (s), str, len);
> | >   ((char *) TREE_STRING_POINTER (s))[len] = '\0';
> | >
> | > is trying to do similar thing, but it is undefined behaviour.
> | >
> | >        [#5] If an attempt is made to modify an object defined  with
> | >        a  const-qualified  type  through use of an lvalue with non-
> | >        const-qualified type, the  behavior  is  undefined.
> |
> | The object here is '*s', which was not defined with a const-qualified
> | type.  It's not defined with any type at all, it was allocated 
> through
> | malloc which is not a typed interface.  (It would be different if it
> | was allocated through 'new', but we do not have new in C.)
>
> The undefined behaviour comes from different sources.
> Consider the following:
>
>    typedef struct {
>       int fu;
>       const int bhar;
>    } S;
>
>    void f(S *p)
>    {
>        (*p).fu = 90;            // #1
>    }
>
> Do you believe line #1 is valid in face of
>
>        [#1]  An  lvalue  is an expression with an object type or an
>        incomplete  type  other  than void;53) if an lvalue does not
>        designate an object when it is evaluated,  the  behavior  is
>        undefined.   When  an  object  is  said to have a particular
>        type, the type is specified by the lvalue used to  designate
>        the  object.  A modifiable lvalue is an lvalue that does not
>        have array type, does not have an incomplete type, does  not
>        have  a  const-qualified  type,  and if it is a structure or
>        union, does not have any member (including, recursively, any
>        member  or  element  of  all contained aggregates or unions)
>        with a const-qualified type.
>
> ?

Yes.  The lvalue here is '(*p).fu', which has type 'int' and therefore 
is a modifiable lvalue.

Note that '*p' is not a modifiable lvalue, but all of '*p' is not being 
modified here.

> Notice that here, it is not a question of where the object pointed to
> by *p comes from.
>
> Next question is for
>
>    void g(S *p)
>    {
>        p->fu = 90;
>    }

Yes.  Same reasoning.

-- 
Geoff Keating <geoffk@apple.com>


[-- Attachment #2: smime.p7s --]
[-- Type: application/pkcs7-signature, Size: 2361 bytes --]

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

* Re: Compiling GCC With a C++ Compiler (g++)
  2004-10-13 22:15               ` Geoffrey Keating
@ 2004-10-13 22:24                 ` Gabriel Dos Reis
  2004-10-13 22:53                   ` Joseph S. Myers
  2004-10-13 23:19                   ` Geoffrey Keating
  0 siblings, 2 replies; 63+ messages in thread
From: Gabriel Dos Reis @ 2004-10-13 22:24 UTC (permalink / raw)
  To: Geoffrey Keating; +Cc: GCC, Ranjit Mathew, Zack Weinberg

Geoffrey Keating <geoffk@apple.com> writes:

| On 13/10/2004, at 1:39 PM, Gabriel Dos Reis wrote:
| 
| > Geoffrey Keating <geoffk@apple.com> writes:
| >
| > | On 12/10/2004, at 8:42 PM, Gabriel Dos Reis wrote:
| > |
| > | > The code in build_string
| > | >
| > | >   memset (s, 0, sizeof (struct tree_common));
| > | >   TREE_SET_CODE (s, STRING_CST);
| > | >   TREE_STRING_LENGTH (s) = len;
| > | >   memcpy ((char *) TREE_STRING_POINTER (s), str, len);
| > | >   ((char *) TREE_STRING_POINTER (s))[len] = '\0';
| > | >
| > | > is trying to do similar thing, but it is undefined behaviour.
| > | >
| > | >        [#5] If an attempt is made to modify an object defined  with
| > | >        a  const-qualified  type  through use of an lvalue with non-
| > | >        const-qualified type, the  behavior  is  undefined.
| > |
| > | The object here is '*s', which was not defined with a const-qualified
| > | type.  It's not defined with any type at all, it was allocated
| > through
| > | malloc which is not a typed interface.  (It would be different if it
| > | was allocated through 'new', but we do not have new in C.)
| >
| > The undefined behaviour comes from different sources.
| > Consider the following:
| >
| >    typedef struct {
| >       int fu;
| >       const int bhar;
| >    } S;
| >
| >    void f(S *p)
| >    {
| >        (*p).fu = 90;            // #1
| >    }
| >
| > Do you believe line #1 is valid in face of
| >
| >        [#1]  An  lvalue  is an expression with an object type or an
| >        incomplete  type  other  than void;53) if an lvalue does not
| >        designate an object when it is evaluated,  the  behavior  is
| >        undefined.   When  an  object  is  said to have a particular
| >        type, the type is specified by the lvalue used to  designate
| >        the  object.  A modifiable lvalue is an lvalue that does not
| >        have array type, does not have an incomplete type, does  not
| >        have  a  const-qualified  type,  and if it is a structure or
| >        union, does not have any member (including, recursively, any
| >        member  or  element  of  all contained aggregates or unions)
| >        with a const-qualified type.
| >
| > ?
| 
| Yes.  The lvalue here is '(*p).fu', which has type 'int' and therefore
| is a modifiable lvalue.

No.  The lvalue *p, of type S, is not modifiable.

| Note that '*p' is not a modifiable lvalue, but all of '*p' is not
| being modified here.

I guess this is where our disagreement lies: It does not matter
whether the lvalue is used to modify a small part of the whole object.

-- Gaby

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

* Re: Compiling GCC With a C++ Compiler (g++)
  2004-10-13 22:24                 ` Gabriel Dos Reis
@ 2004-10-13 22:53                   ` Joseph S. Myers
  2004-10-13 23:19                   ` Geoffrey Keating
  1 sibling, 0 replies; 63+ messages in thread
From: Joseph S. Myers @ 2004-10-13 22:53 UTC (permalink / raw)
  To: Gabriel Dos Reis; +Cc: Geoffrey Keating, GCC, Ranjit Mathew, Zack Weinberg

On Wed, 13 Oct 2004, Gabriel Dos Reis wrote:

> | Yes.  The lvalue here is '(*p).fu', which has type 'int' and therefore
> | is a modifiable lvalue.
> 
> No.  The lvalue *p, of type S, is not modifiable.

But the requirement for a modifiable lvalue is the constraint in 6.5.16#1, 
"An assignment operator shall have a modifiable lvalue as its left 
operand.".  The left operand if (*p).fu.  (*p).fu is a modifiable lvalue.  
A modifiable lvalue may well have operands which are not modifiable 
lvalues; this is irrelevant as long as the operand of the assignment 
operator is a modifiable lvalue, which it is.

-- 
Joseph S. Myers               http://www.srcf.ucam.org/~jsm28/gcc/
    jsm@polyomino.org.uk (personal mail)
    joseph@codesourcery.com (CodeSourcery mail)
    jsm28@gcc.gnu.org (Bugzilla assignments and CCs)

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

* Re: Compiling GCC With a C++ Compiler (g++)
  2004-10-13 22:24                 ` Gabriel Dos Reis
  2004-10-13 22:53                   ` Joseph S. Myers
@ 2004-10-13 23:19                   ` Geoffrey Keating
  2004-10-14  0:21                     ` Gabriel Dos Reis
  1 sibling, 1 reply; 63+ messages in thread
From: Geoffrey Keating @ 2004-10-13 23:19 UTC (permalink / raw)
  To: Gabriel Dos Reis; +Cc: GCC, Ranjit Mathew, Zack Weinberg

[-- Attachment #1: Type: text/plain, Size: 3052 bytes --]


On 13/10/2004, at 2:54 PM, Gabriel Dos Reis wrote:

> Geoffrey Keating <geoffk@apple.com> writes:
>
> | On 13/10/2004, at 1:39 PM, Gabriel Dos Reis wrote:
> |
> | > Geoffrey Keating <geoffk@apple.com> writes:
> | >
> | > | On 12/10/2004, at 8:42 PM, Gabriel Dos Reis wrote:
> | > |
> | > | > The code in build_string
> | > | >
> | > | >   memset (s, 0, sizeof (struct tree_common));
> | > | >   TREE_SET_CODE (s, STRING_CST);
> | > | >   TREE_STRING_LENGTH (s) = len;
> | > | >   memcpy ((char *) TREE_STRING_POINTER (s), str, len);
> | > | >   ((char *) TREE_STRING_POINTER (s))[len] = '\0';
> | > | >
> | > | > is trying to do similar thing, but it is undefined behaviour.
> | > | >
> | > | >        [#5] If an attempt is made to modify an object defined  
> with
> | > | >        a  const-qualified  type  through use of an lvalue with 
> non-
> | > | >        const-qualified type, the  behavior  is  undefined.
> | > |
> | > | The object here is '*s', which was not defined with a 
> const-qualified
> | > | type.  It's not defined with any type at all, it was allocated
> | > through
> | > | malloc which is not a typed interface.  (It would be different 
> if it
> | > | was allocated through 'new', but we do not have new in C.)
> | >
> | > The undefined behaviour comes from different sources.
> | > Consider the following:
> | >
> | >    typedef struct {
> | >       int fu;
> | >       const int bhar;
> | >    } S;
> | >
> | >    void f(S *p)
> | >    {
> | >        (*p).fu = 90;            // #1
> | >    }
> | >
> | > Do you believe line #1 is valid in face of
> | >
> | >        [#1]  An  lvalue  is an expression with an object type or an
> | >        incomplete  type  other  than void;53) if an lvalue does not
> | >        designate an object when it is evaluated,  the  behavior  is
> | >        undefined.   When  an  object  is  said to have a particular
> | >        type, the type is specified by the lvalue used to  designate
> | >        the  object.  A modifiable lvalue is an lvalue that does not
> | >        have array type, does not have an incomplete type, does  not
> | >        have  a  const-qualified  type,  and if it is a structure or
> | >        union, does not have any member (including, recursively, any
> | >        member  or  element  of  all contained aggregates or unions)
> | >        with a const-qualified type.
> | >
> | > ?
> |
> | Yes.  The lvalue here is '(*p).fu', which has type 'int' and 
> therefore
> | is a modifiable lvalue.
>
> No.  The lvalue *p, of type S, is not modifiable.

There is nothing in the standard that says the left-hand argument to 
'.' must be modifiable.  Generally, only left-hand arguments to '=' 
(and similar things, like '++') must be modifiable lvalues.

> | Note that '*p' is not a modifiable lvalue, but all of '*p' is not
> | being modified here.
>
> I guess this is where our disagreement lies: It does not matter
> whether the lvalue is used to modify a small part of the whole object.

I don't believe the word 'object' appears in the relevant constraints.

[-- Attachment #2: smime.p7s --]
[-- Type: application/pkcs7-signature, Size: 2408 bytes --]

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

* Re: Compiling GCC With a C++ Compiler (g++)
  2004-10-13 23:19                   ` Geoffrey Keating
@ 2004-10-14  0:21                     ` Gabriel Dos Reis
  2004-10-14  6:04                       ` Andreas Schwab
  0 siblings, 1 reply; 63+ messages in thread
From: Gabriel Dos Reis @ 2004-10-14  0:21 UTC (permalink / raw)
  To: Geoffrey Keating; +Cc: GCC, Ranjit Mathew, Zack Weinberg

Geoffrey Keating <geoffk@apple.com> writes:

| > | Note that '*p' is not a modifiable lvalue, but all of '*p' is not
| > | being modified here.
| >
| > I guess this is where our disagreement lies: It does not matter
| > whether the lvalue is used to modify a small part of the whole object.
| 
| I don't believe the word 'object' appears in the relevant constraints.

Gosh, scratch "object" if that bothers you.

  It does not matter whether the lvalue is used to modify a small part
  of or the  whole *p.

-- Gaby

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

* Re: Compiling GCC With a C++ Compiler (g++)
  2004-10-14  0:21                     ` Gabriel Dos Reis
@ 2004-10-14  6:04                       ` Andreas Schwab
  2004-10-14  7:10                         ` Gabriel Dos Reis
  0 siblings, 1 reply; 63+ messages in thread
From: Andreas Schwab @ 2004-10-14  6:04 UTC (permalink / raw)
  To: Gabriel Dos Reis; +Cc: Geoffrey Keating, GCC

Gabriel Dos Reis <gdr@cs.tamu.edu> writes:

> Gosh, scratch "object" if that bothers you.
>
>   It does not matter whether the lvalue is used to modify a small part
>   of or the  whole *p.

Where does the standard state that qualifying a struct member makes the
whole struct qualified?

Andreas.

-- 
Andreas Schwab, SuSE Labs, schwab@suse.de
SuSE Linux AG, Maxfeldstraße 5, 90409 Nürnberg, Germany
Key fingerprint = 58CA 54C7 6D53 942B 1756  01D3 44D5 214B 8276 4ED5
"And now for something completely different."

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

* Re: Compiling GCC With a C++ Compiler (g++)
  2004-10-14  6:04                       ` Andreas Schwab
@ 2004-10-14  7:10                         ` Gabriel Dos Reis
  2004-10-14 11:29                           ` Andreas Schwab
  0 siblings, 1 reply; 63+ messages in thread
From: Gabriel Dos Reis @ 2004-10-14  7:10 UTC (permalink / raw)
  To: Andreas Schwab; +Cc: Geoffrey Keating, GCC

Andreas Schwab <schwab@suse.de> writes:

| Gabriel Dos Reis <gdr@cs.tamu.edu> writes:
| 
| > Gosh, scratch "object" if that bothers you.
| >
| >   It does not matter whether the lvalue is used to modify a small part
| >   of or the  whole *p.
| 
| Where does the standard state that qualifying a struct member makes the
| whole struct qualified?

I said *nonmodifiable*.  

And the standard quote is the one you left out.

-- Gaby

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

* Re: Compiling GCC With a C++ Compiler (g++)
  2004-10-14  7:10                         ` Gabriel Dos Reis
@ 2004-10-14 11:29                           ` Andreas Schwab
  2004-10-14 13:06                             ` Gabriel Dos Reis
  0 siblings, 1 reply; 63+ messages in thread
From: Andreas Schwab @ 2004-10-14 11:29 UTC (permalink / raw)
  To: Gabriel Dos Reis; +Cc: Geoffrey Keating, GCC

Gabriel Dos Reis <gdr@cs.tamu.edu> writes:

> Andreas Schwab <schwab@suse.de> writes:
>
> | Gabriel Dos Reis <gdr@cs.tamu.edu> writes:
> | 
> | > Gosh, scratch "object" if that bothers you.
> | >
> | >   It does not matter whether the lvalue is used to modify a small part
> | >   of or the  whole *p.
> | 
> | Where does the standard state that qualifying a struct member makes the
> | whole struct qualified?
>
> I said *nonmodifiable*.  

And non-modifiable comes from qualifying with const.

> And the standard quote is the one you left out.

Which does not answer my question anyway.

Andreas.

-- 
Andreas Schwab, SuSE Labs, schwab@suse.de
SuSE Linux AG, Maxfeldstraße 5, 90409 Nürnberg, Germany
Key fingerprint = 58CA 54C7 6D53 942B 1756  01D3 44D5 214B 8276 4ED5
"And now for something completely different."

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

* Re: Compiling GCC With a C++ Compiler (g++)
  2004-10-14 11:29                           ` Andreas Schwab
@ 2004-10-14 13:06                             ` Gabriel Dos Reis
  2004-10-14 18:37                               ` Andreas Schwab
  0 siblings, 1 reply; 63+ messages in thread
From: Gabriel Dos Reis @ 2004-10-14 13:06 UTC (permalink / raw)
  To: Andreas Schwab; +Cc: Geoffrey Keating, GCC

Andreas Schwab <schwab@suse.de> writes:

| Gabriel Dos Reis <gdr@cs.tamu.edu> writes:
| 
| > Andreas Schwab <schwab@suse.de> writes:
| >
| > | Gabriel Dos Reis <gdr@cs.tamu.edu> writes:
| > | 
| > | > Gosh, scratch "object" if that bothers you.
| > | >
| > | >   It does not matter whether the lvalue is used to modify a small part
| > | >   of or the  whole *p.
| > | 
| > | Where does the standard state that qualifying a struct member makes the
| > | whole struct qualified?
| >
| > I said *nonmodifiable*.  
| 
| And non-modifiable comes from qualifying with const.

and other sources.

| > And the standard quote is the one you left out.
| 
| Which does not answer my question anyway.

You asked where the standard says that qualifying a struct member
member makes the whole struct qualified?  I told you I did not say
something like that.  What I said and what the C standard says is that
if an lvalue of type structure type has a member that is
const-qualified, then the lvalue is nonmodifiable -- it just suffices
that -one- member is const-qualified.

If you're making the assumption that nonmodifiability necessarily
implies that the whole thing is const-qualified, then you're wrong and
I'm not surprised you're not satisfied with what the standard says.

-- Gaby

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

* RE: Compiling GCC With a C++ Compiler (g++)
  2004-10-13 21:16                           ` Geoffrey Keating
@ 2004-10-14 13:26                             ` Dave Korn
  2004-10-14 13:32                               ` Gabriel Dos Reis
                                                 ` (2 more replies)
  0 siblings, 3 replies; 63+ messages in thread
From: Dave Korn @ 2004-10-14 13:26 UTC (permalink / raw)
  To: 'Geoffrey Keating'
  Cc: 'Joseph S. Myers', 'Zack Weinberg',
	'Ranjit Mathew', gcc, 'Andreas Schwab',
	'Gabriel Dos Reis'


[ Phil Edwards snecked from Cc: line in accordance with his wish to escape
"this eternal thread"! ]

> -----Original Message-----
> From: Geoffrey Keating 
> Sent: 13 October 2004 20:42

> On 13/10/2004, at 8:23 AM, Dave Korn wrote:

> >   Huh?  Are you saying that in:
> >
> > typedef struct { const char x } AA;
> >
> > AA *py1, py2;
> > AA y1 = { z };
> >
> >   py1 = malloc (sizeof *py2);
> >   py2 = &y1;
> >
> > it is valid to say
> >
> >   *(char *)(&py1->x) = '?';
> >
> > but not valid to say
> >
> >   *(char *)(&py2->x) = '?';
> 
> Yes, that sounds right.


  Wow, we really seem to me to be entering the realm of the bizarre here.
What about this function: is it valid, conformant C?

void fubar (const char *x)
{
    *(char *)x = '?';
}

  Is it not implicit from what you've just told me that the answer to the
question of whether or not that function is valid conformant C depends on
whether the value of the pointer you pass into it was originally derived
from a call to malloc (valid) or by taking the address-of a local or static
variable (not valid)?  Does this still make sense?  It's making my mind
boggle in several directions at once.

    cheers, 
      DaveK
-- 
Can't think of a witty .sigline today....
 


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

* Re: Compiling GCC With a C++ Compiler (g++)
  2004-10-14 13:26                             ` Dave Korn
@ 2004-10-14 13:32                               ` Gabriel Dos Reis
  2004-10-14 18:40                                 ` Andreas Schwab
  2004-10-14 20:33                                 ` Geoffrey Keating
  2004-10-14 20:19                               ` Geoffrey Keating
  2004-10-15 12:03                               ` Kai Henningsen
  2 siblings, 2 replies; 63+ messages in thread
From: Gabriel Dos Reis @ 2004-10-14 13:32 UTC (permalink / raw)
  To: Dave Korn
  Cc: 'Geoffrey Keating', 'Joseph S. Myers',
	'Zack Weinberg', 'Ranjit Mathew',
	gcc, 'Andreas Schwab'

"Dave Korn" <dk@artimi.com> writes:

| [ Phil Edwards snecked from Cc: line in accordance with his wish to escape
| "this eternal thread"! ]
| 
| > -----Original Message-----
| > From: Geoffrey Keating 
| > Sent: 13 October 2004 20:42
| 
| > On 13/10/2004, at 8:23 AM, Dave Korn wrote:
| 
| > >   Huh?  Are you saying that in:
| > >
| > > typedef struct { const char x } AA;
| > >
| > > AA *py1, py2;
| > > AA y1 = { z };
| > >
| > >   py1 = malloc (sizeof *py2);
| > >   py2 = &y1;
| > >
| > > it is valid to say
| > >
| > >   *(char *)(&py1->x) = '?';
| > >
| > > but not valid to say
| > >
| > >   *(char *)(&py2->x) = '?';
| > 
| > Yes, that sounds right.
| 
| 
|   Wow, we really seem to me to be entering the realm of the bizarre here.

Yep.

| What about this function: is it valid, conformant C?
| 
| void fubar (const char *x)
| {
|     *(char *)x = '?';
| }

It is valid C and C++, if only if the object pointed to by x is const.

|   Is it not implicit from what you've just told me that the answer to the
| question of whether or not that function is valid conformant C depends on
| whether the value of the pointer you pass into it was originally derived
| from a call to malloc (valid) or by taking the address-of a local or static
| variable (not valid)?

If you remove the argument about malloc(), I agree.

|  Does this still make sense?  It's making my mind
| boggle in several directions at once.

I think there is a hole in the argument about allocating object
with malloc().  The key is to understand what the effective type of
the object is.

-- Gaby

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

* Re: Compiling GCC With a C++ Compiler (g++)
  2004-10-14 13:06                             ` Gabriel Dos Reis
@ 2004-10-14 18:37                               ` Andreas Schwab
  2004-10-15 12:48                                 ` Kai Henningsen
  0 siblings, 1 reply; 63+ messages in thread
From: Andreas Schwab @ 2004-10-14 18:37 UTC (permalink / raw)
  To: Gabriel Dos Reis; +Cc: Geoffrey Keating, GCC

Gabriel Dos Reis <gdr@cs.tamu.edu> writes:

> If you're making the assumption that nonmodifiability necessarily
> implies that the whole thing is const-qualified, then you're wrong and
> I'm not surprised you're not satisfied with what the standard says.

You mean that the following (which does not contain any casts) is invoking
undefined behaviour?

struct A { int a; const int b; } X;

void f (int *x) { *x = 1; }

int main (void) { f (&X.a); return 0; }

Andreas.

-- 
Andreas Schwab, SuSE Labs, schwab@suse.de
SuSE Linux AG, Maxfeldstraße 5, 90409 Nürnberg, Germany
Key fingerprint = 58CA 54C7 6D53 942B 1756  01D3 44D5 214B 8276 4ED5
"And now for something completely different."

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

* Re: Compiling GCC With a C++ Compiler (g++)
  2004-10-14 13:32                               ` Gabriel Dos Reis
@ 2004-10-14 18:40                                 ` Andreas Schwab
  2004-10-14 18:48                                   ` Gabriel Dos Reis
  2004-10-14 20:33                                 ` Geoffrey Keating
  1 sibling, 1 reply; 63+ messages in thread
From: Andreas Schwab @ 2004-10-14 18:40 UTC (permalink / raw)
  To: Gabriel Dos Reis; +Cc: gcc

Gabriel Dos Reis <gdr@cs.tamu.edu> writes:

> | What about this function: is it valid, conformant C?
> | 
> | void fubar (const char *x)
> | {
> |     *(char *)x = '?';
> | }
>
> It is valid C and C++, if only if the object pointed to by x is const.

No, it isn't.

Andreas.

-- 
Andreas Schwab, SuSE Labs, schwab@suse.de
SuSE Linux AG, Maxfeldstraße 5, 90409 Nürnberg, Germany
Key fingerprint = 58CA 54C7 6D53 942B 1756  01D3 44D5 214B 8276 4ED5
"And now for something completely different."

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

* Re: Compiling GCC With a C++ Compiler (g++)
  2004-10-14 18:40                                 ` Andreas Schwab
@ 2004-10-14 18:48                                   ` Gabriel Dos Reis
  0 siblings, 0 replies; 63+ messages in thread
From: Gabriel Dos Reis @ 2004-10-14 18:48 UTC (permalink / raw)
  To: Andreas Schwab; +Cc: gcc

On Thu, 14 Oct 2004, Andreas Schwab wrote:

| Gabriel Dos Reis <gdr@cs.tamu.edu> writes:
|
| > | What about this function: is it valid, conformant C?
| > |
| > | void fubar (const char *x)
| > | {
| > |     *(char *)x = '?';
| > | }
| >
| > It is valid C and C++, if only if the object pointed to by x is const.
                                                                   ^
Obviously, there is a missing "not" there

| No, it isn't.

-- Gaby

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

* Re: Compiling GCC With a C++ Compiler (g++)
  2004-10-14 13:26                             ` Dave Korn
  2004-10-14 13:32                               ` Gabriel Dos Reis
@ 2004-10-14 20:19                               ` Geoffrey Keating
  2004-10-15 12:03                               ` Kai Henningsen
  2 siblings, 0 replies; 63+ messages in thread
From: Geoffrey Keating @ 2004-10-14 20:19 UTC (permalink / raw)
  To: Dave Korn
  Cc: 'Joseph S. Myers', 'Zack Weinberg',
	gcc, 'Ranjit Mathew', 'Andreas Schwab',
	'Gabriel Dos Reis'

[-- Attachment #1: Type: text/plain, Size: 1490 bytes --]


On 14/10/2004, at 5:33 AM, Dave Korn wrote:

>
> [ Phil Edwards snecked from Cc: line in accordance with his wish to 
> escape
> "this eternal thread"! ]
>
>> -----Original Message-----
>> From: Geoffrey Keating
>> Sent: 13 October 2004 20:42
>
>> On 13/10/2004, at 8:23 AM, Dave Korn wrote:
>
>>>   Huh?  Are you saying that in:
>>>
>>> typedef struct { const char x } AA;
>>>
>>> AA *py1, py2;
>>> AA y1 = { z };
>>>
>>>   py1 = malloc (sizeof *py2);
>>>   py2 = &y1;
>>>
>>> it is valid to say
>>>
>>>   *(char *)(&py1->x) = '?';
>>>
>>> but not valid to say
>>>
>>>   *(char *)(&py2->x) = '?';
>>
>> Yes, that sounds right.
>
>
>   Wow, we really seem to me to be entering the realm of the bizarre 
> here.
> What about this function: is it valid, conformant C?
>
> void fubar (const char *x)
> {
>     *(char *)x = '?';
> }

It can be part of a conforming program, yes.

>   Is it not implicit from what you've just told me that the answer to 
> the
> question of whether or not that function is valid conformant C depends 
> on
> whether the value of the pointer you pass into it was originally 
> derived
> from a call to malloc (valid) or by taking the address-of a local or 
> static
> variable (not valid)?  Does this still make sense?  It's making my mind
> boggle in several directions at once.

Yes, it matters what value 'x' has.  For instance, consider

int main(void)
{
   fubar(NULL);
   return 0;
}

Obviously that program is not conforming, whether or not 'x' is const.

[-- Attachment #2: smime.p7s --]
[-- Type: application/pkcs7-signature, Size: 2408 bytes --]

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

* Re: Compiling GCC With a C++ Compiler (g++)
  2004-10-14 13:32                               ` Gabriel Dos Reis
  2004-10-14 18:40                                 ` Andreas Schwab
@ 2004-10-14 20:33                                 ` Geoffrey Keating
  1 sibling, 0 replies; 63+ messages in thread
From: Geoffrey Keating @ 2004-10-14 20:33 UTC (permalink / raw)
  To: Gabriel Dos Reis
  Cc: 'Joseph S. Myers', 'Zack Weinberg',
	gcc, 'Ranjit Mathew', Dave Korn, 'Andreas Schwab'

[-- Attachment #1: Type: text/plain, Size: 1191 bytes --]


On 14/10/2004, at 5:42 AM, Gabriel Dos Reis wrote:

> "Dave Korn" <dk@artimi.com> writes:
>
> |  Does this still make sense?  It's making my mind
> | boggle in several directions at once.
>
> I think there is a hole in the argument about allocating object
> with malloc().  The key is to understand what the effective type of
> the object is.

Why do you think the effective type has anything to do with it?  
Section 6.7.3 speaks only of "an object defined with a const-qualified 
type".  For that to be relevant, you must be able to point at a 
definition.  The word "definition" is defined in section 6.7 paragraph 
5:

> A definition of an identifier is a declaration for that identifier 
> that: —for an object, causes storage to be reserved for that object 
> ...

When malloc is used no identifier is declared, so no object allocated 
with malloc is ever 'defined'.  This is why things allocated with 
malloc do not have a scope, and do not go away at the next close-brace.

This is why it's important to realise that the effective type is not 
relevant here.  Objects allocated with malloc have an effective type, 
but they are not defined with a type.

[-- Attachment #2: smime.p7s --]
[-- Type: application/pkcs7-signature, Size: 2408 bytes --]

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

* Re: Compiling GCC With a C++ Compiler (g++)
  2004-10-14 13:26                             ` Dave Korn
  2004-10-14 13:32                               ` Gabriel Dos Reis
  2004-10-14 20:19                               ` Geoffrey Keating
@ 2004-10-15 12:03                               ` Kai Henningsen
  2 siblings, 0 replies; 63+ messages in thread
From: Kai Henningsen @ 2004-10-15 12:03 UTC (permalink / raw)
  To: gcc

dk@artimi.com (Dave Korn)  wrote on 14.10.04 in <NUTMEGD3zCParqjPikM00000488@NUTMEG.CAM.ARTIMI.COM>:

>   Wow, we really seem to me to be entering the realm of the bizarre here.

Not really.

> What about this function: is it valid, conformant C?
>
> void fubar (const char *x)
> {
>     *(char *)x = '?';
> }
>
>   Is it not implicit from what you've just told me that the answer to the
> question of whether or not that function is valid conformant C depends on
> whether the value of the pointer you pass into it was originally derived
> from a call to malloc (valid) or by taking the address-of a local or static
> variable (not valid)?

Nope, malloc or variable is the wrong distinction.

The argument is really very simple. Essentially, it reduces to where x  
points.

x == NULL                           -> invalid
x points into nonmodifiable storage -> invalid
x points into modifiable storage    -> valid

Rule of thumb: assuming the compiler (and os) did this optimally right,  
it's invalid exactly if it would get a SIGSEGV. Or at least that seems to  
be the intention behind these rules.

Of course, the closest C can come to this is to look if the object was  
defined with const. (malloc() results are never defined with const.)  
That's defined, not declared or cast to, and that's the object, not a  
pointer to it, or something the object is embedded in. (But obviously, if  
you can't modify a subobject, then you can't modify the object AS A WHOLE  
either, as that would modify the subobject.)

MfG Kai

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

* Re: Compiling GCC With a C++ Compiler (g++)
  2004-10-14 18:37                               ` Andreas Schwab
@ 2004-10-15 12:48                                 ` Kai Henningsen
  0 siblings, 0 replies; 63+ messages in thread
From: Kai Henningsen @ 2004-10-15 12:48 UTC (permalink / raw)
  To: gcc

schwab@suse.de (Andreas Schwab)  wrote on 14.10.04 in <jeis9dqn79.fsf@sykes.suse.de>:

> Gabriel Dos Reis <gdr@cs.tamu.edu> writes:
>
> > If you're making the assumption that nonmodifiability necessarily
> > implies that the whole thing is const-qualified, then you're wrong and
> > I'm not surprised you're not satisfied with what the standard says.
>
> You mean that the following (which does not contain any casts) is invoking
> undefined behaviour?
>
> struct A { int a; const int b; } X;
>
> void f (int *x) { *x = 1; }
>
> int main (void) { f (&X.a); return 0; }

Try this instead, which doesn't even use pointers:

struct A { int a; const int b; };

struct A a1;
struct A a2 = { 1, 2 };

...

a1.a = a2.a; // legal
a1.b = a2.b; // illegal

a1 = a2; // illegal


MfG Kai

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

* Re: Compiling GCC With a C++ Compiler (g++)
  2004-10-13  3:47 Steven L. Zook
@ 2004-10-13  7:26 ` Gabriel Dos Reis
  0 siblings, 0 replies; 63+ messages in thread
From: Gabriel Dos Reis @ 2004-10-13  7:26 UTC (permalink / raw)
  To: Steven L. Zook; +Cc: Zack Weinberg, Geoffrey Keating, Ranjit Mathew, GCC

"Steven L. Zook" <SLZook@Qualstar.com> writes:

| Pardon me for intruding here. This may not be applicable to your specifics.
| 
| C++ does have a construct for write-once storage; construction. For example,
| 
| struct sDerf { sDerf( int WriteOnceValue ) : ReadOnlyValue( WriteOnceValue ) {}
|                int const ReadOnlyValue;
|              };

Yep.  That was explicilty listed in the message Zack was replying to.
But for some reasons I can't understand, it disappeared from the
message he quote when replying.

-- Gaby

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

* RE: Compiling GCC With a C++ Compiler (g++)
@ 2004-10-13  3:47 Steven L. Zook
  2004-10-13  7:26 ` Gabriel Dos Reis
  0 siblings, 1 reply; 63+ messages in thread
From: Steven L. Zook @ 2004-10-13  3:47 UTC (permalink / raw)
  To: Zack Weinberg, Gabriel Dos Reis; +Cc: Geoffrey Keating, Ranjit Mathew, GCC

Pardon me for intruding here. This may not be applicable to your specifics.

C++ does have a construct for write-once storage; construction. For example,

struct sDerf { sDerf( int WriteOnceValue ) : ReadOnlyValue( WriteOnceValue ) {}
               int const ReadOnlyValue;
             };

As far as I know, this is the only "supported" method. The rest are tricks that tunnel around the language by using unions, casting, or pointer aliasing.

As far a language deficiency is concerned, I have always thought that some more modifiers than const and volatile would be useful. Especially for embedded programmers like me. The spelling of the following is not important: only the effect matters.

readonly: class members and friends can write but outsiders can only read. This would eliminate having to write accessor functions.

construct: constructor can modify any number of times in initializer list or in body but all others can only read.

interrupt: acts like volatile in non-interrupt service routines and non-volatile in an ISR (where an ISR is marked by some attribute or perhaps by name).

-----Original Message-----
From: gcc-owner@gcc.gnu.org [mailto:gcc-owner@gcc.gnu.org]On Behalf Of
Zack Weinberg
Sent: Tuesday, October 12, 2004 3:58 PM
To: Gabriel Dos Reis
Cc: Geoffrey Keating; Ranjit Mathew; GCC
Subject: Re: Compiling GCC With a C++ Compiler (g++)


Gabriel Dos Reis <gdr@cs.tamu.edu> writes:

> Geoffrey Keating <geoffk@apple.com> writes:
> | The 'const' is there to indicate that the string should not be changed
> | once the STRING_CST is created;
>
> And how do you create it?

By casting away the const, as is done in build_string.  Or by
constructing the data in memory before giving it the type with the
const qualifier.

How else do you propose to enforce write-once semantics on a data
structure that is, in fact, write-once?  I am definitely with Geoff
here - this should be allowed (or, to rephrase, if C++ has no
construct which allows what we want to do here, that is a language
deficiency).

zw

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

end of thread, other threads:[~2004-10-15  7:23 UTC | newest]

Thread overview: 63+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2004-10-11  9:53 Compiling GCC With a C++ Compiler (g++) Ranjit Mathew
2004-10-12 10:06 ` Ranjit Mathew
2004-10-12 13:17   ` Gabriel Dos Reis
2004-10-12 21:15   ` Geoffrey Keating
2004-10-12 23:00     ` Gabriel Dos Reis
2004-10-12 23:23       ` Zack Weinberg
2004-10-13  2:53         ` Phil Edwards
2004-10-13  6:24           ` Gabriel Dos Reis
2004-10-13 10:57             ` Andreas Schwab
2004-10-13 13:16               ` Gabriel Dos Reis
2004-10-13 13:56                 ` Andreas Schwab
2004-10-13 14:22                   ` Gabriel Dos Reis
2004-10-13 15:06                     ` Andreas Schwab
2004-10-13 15:22                       ` Gabriel Dos Reis
2004-10-13 15:33                         ` Andreas Schwab
2004-10-13 18:20                           ` Gabriel Dos Reis
2004-10-13 19:09                             ` Andreas Schwab
2004-10-13 11:47             ` Dave Korn
2004-10-13 12:24               ` Andreas Schwab
2004-10-13 13:29                 ` Gabriel Dos Reis
2004-10-13 14:10                   ` Andreas Schwab
2004-10-13 14:30                     ` Dave Korn
2004-10-13 14:50                       ` Dave Korn
2004-10-13 18:25                         ` Andreas Schwab
2004-10-13 15:04                       ` Joseph S. Myers
2004-10-13 17:01                         ` Dave Korn
2004-10-13 21:16                           ` Geoffrey Keating
2004-10-14 13:26                             ` Dave Korn
2004-10-14 13:32                               ` Gabriel Dos Reis
2004-10-14 18:40                                 ` Andreas Schwab
2004-10-14 18:48                                   ` Gabriel Dos Reis
2004-10-14 20:33                                 ` Geoffrey Keating
2004-10-14 20:19                               ` Geoffrey Keating
2004-10-15 12:03                               ` Kai Henningsen
2004-10-13 14:53                     ` Gabriel Dos Reis
2004-10-13 15:46                     ` Gabriel Dos Reis
2004-10-13 19:41                 ` Matt Austern
2004-10-13 20:29                   ` Andreas Schwab
2004-10-13 20:41                     ` Matt Austern
2004-10-13 20:58             ` Phil Edwards
2004-10-13  9:23           ` Ranjit Mathew
2004-10-13 13:09             ` Ranjit Mathew
2004-10-13 19:13               ` Richard Henderson
2004-10-13 21:55                 ` Gabriel Dos Reis
2004-10-13 13:29             ` Gabriel Dos Reis
2004-10-13  5:49         ` Gabriel Dos Reis
2004-10-13  9:19           ` Zack Weinberg
2004-10-13 13:45             ` Gabriel Dos Reis
2004-10-13 20:39           ` Geoffrey Keating
2004-10-13 21:45             ` Gabriel Dos Reis
2004-10-13 22:15               ` Geoffrey Keating
2004-10-13 22:24                 ` Gabriel Dos Reis
2004-10-13 22:53                   ` Joseph S. Myers
2004-10-13 23:19                   ` Geoffrey Keating
2004-10-14  0:21                     ` Gabriel Dos Reis
2004-10-14  6:04                       ` Andreas Schwab
2004-10-14  7:10                         ` Gabriel Dos Reis
2004-10-14 11:29                           ` Andreas Schwab
2004-10-14 13:06                             ` Gabriel Dos Reis
2004-10-14 18:37                               ` Andreas Schwab
2004-10-15 12:48                                 ` Kai Henningsen
2004-10-13  3:47 Steven L. Zook
2004-10-13  7:26 ` 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).