Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c > #30504 > unrolled thread
| Started by | Noob <root@127.0.0.1> |
|---|---|
| First post | 2013-01-22 16:36 +0100 |
| Last post | 2013-01-22 20:48 -0800 |
| Articles | 20 on this page of 64 — 13 participants |
Back to article view | Back to comp.lang.c
Initializing a malloc'ed struct whose fields are const with run-time values Noob <root@127.0.0.1> - 2013-01-22 16:36 +0100
Re: Initializing a malloc'ed struct whose fields are const with run-time values Shao Miller <sha0.miller@gmail.com> - 2013-01-22 11:23 -0500
Re: Initializing a malloc'ed struct whose fields are const with run-time values Ben Bacarisse <ben.usenet@bsb.me.uk> - 2013-01-22 21:26 +0000
Re: Initializing a malloc'ed struct whose fields are const with run-time values James Kuyper <jameskuyper@verizon.net> - 2013-01-22 16:41 -0500
Re: Initializing a malloc'ed struct whose fields are const with run-time values William Ahern <william@wilbur.25thandClement.com> - 2013-01-22 13:25 -0800
Re: Initializing a malloc'ed struct whose fields are const with run-time values Shao Miller <sha0.miller@gmail.com> - 2013-01-22 23:17 -0500
Re: Initializing a malloc'ed struct whose fields are const with run-time values Ben Bacarisse <ben.usenet@bsb.me.uk> - 2013-01-23 13:09 +0000
Re: Initializing a malloc'ed struct whose fields are const with run-time values Noob <root@127.0.0.1> - 2013-01-23 14:16 +0100
Re: Initializing a malloc'ed struct whose fields are const with run-time values "BartC" <bc@freeuk.com> - 2013-01-23 13:25 +0000
Re: Initializing a malloc'ed struct whose fields are const with run-time values Noob <root@127.0.0.1> - 2013-01-23 15:21 +0100
Re: Initializing a malloc'ed struct whose fields are const with run-time values Ben Bacarisse <ben.usenet@bsb.me.uk> - 2013-01-23 14:56 +0000
Re: Initializing a malloc'ed struct whose fields are const with run-time values Noob <root@127.0.0.1> - 2013-01-23 16:40 +0100
Re: Initializing a malloc'ed struct whose fields are const with run-time values Ben Bacarisse <ben.usenet@bsb.me.uk> - 2013-01-23 18:26 +0000
Re: Initializing a malloc'ed struct whose fields are const with run-time values Tim Rentsch <txr@alumni.caltech.edu> - 2013-01-23 20:39 -0800
Re: Initializing a malloc'ed struct whose fields are const with run-time values Shao Miller <sha0.miller@gmail.com> - 2013-01-23 17:14 -0500
Re: Initializing a malloc'ed struct whose fields are const with run-time values Ike Naar <ike@sverige.freeshell.org> - 2013-01-22 17:59 +0000
Re: Initializing a malloc'ed struct whose fields are const with run-time values Shao Miller <sha0.miller@gmail.com> - 2013-01-22 14:09 -0500
Re: Initializing a malloc'ed struct whose fields are const with run-time values Noob <root@localhost> - 2013-01-22 21:59 +0100
Re: Initializing a malloc'ed struct whose fields are const with run-time values glen herrmannsfeldt <gah@ugcs.caltech.edu> - 2013-01-22 21:19 +0000
Re: Initializing a malloc'ed struct whose fields are const with run-time values Shao Miller <sha0.miller@gmail.com> - 2013-01-22 23:47 -0500
Re: Initializing a malloc'ed struct whose fields are const with run-time values Ben Bacarisse <ben.usenet@bsb.me.uk> - 2013-01-22 21:05 +0000
Re: Initializing a malloc'ed struct whose fields are const with run-time values Shao Miller <sha0.miller@gmail.com> - 2013-01-22 16:15 -0500
Re: Initializing a malloc'ed struct whose fields are const with run-time values Ian Collins <ian-news@hotmail.com> - 2013-01-23 09:43 +1300
Re: Initializing a malloc'ed struct whose fields are const with run-time values William Ahern <william@wilbur.25thandClement.com> - 2013-01-22 13:19 -0800
Re: Initializing a malloc'ed struct whose fields are const with run-time values William Ahern <william@wilbur.25thandClement.com> - 2013-01-22 13:35 -0800
Re: Initializing a malloc'ed struct whose fields are const with run-time values Ian Collins <ian-news@hotmail.com> - 2013-01-23 10:45 +1300
Re: Initializing a malloc'ed struct whose fields are const with run-time values Shao Miller <sha0.miller@gmail.com> - 2013-01-22 17:07 -0500
Re: Initializing a malloc'ed struct whose fields are const with run-time values Tim Rentsch <txr@alumni.caltech.edu> - 2013-01-22 21:29 -0800
Re: Initializing a malloc'ed struct whose fields are const with run-time values Ben Bacarisse <ben.usenet@bsb.me.uk> - 2013-01-23 13:54 +0000
Re: Initializing a malloc'ed struct whose fields are const with run-time values Shao Miller <sha0.miller@gmail.com> - 2013-01-23 17:08 -0500
Re: Initializing a malloc'ed struct whose fields are const with run-time values Ian Collins <ian-news@hotmail.com> - 2013-01-24 11:29 +1300
Re: Initializing a malloc'ed struct whose fields are const with run-time values Shao Miller <sha0.miller@gmail.com> - 2013-01-23 18:26 -0500
Re: Initializing a malloc'ed struct whose fields are const with run-time values Ian Collins <ian-news@hotmail.com> - 2013-01-24 14:03 +1300
Re: Initializing a malloc'ed struct whose fields are const with run-time values Shao Miller <sha0.miller@gmail.com> - 2013-01-23 23:58 -0500
Re: Initializing a malloc'ed struct whose fields are const with run-time values Ben Bacarisse <ben.usenet@bsb.me.uk> - 2013-01-23 23:36 +0000
Re: Initializing a malloc'ed struct whose fields are const with run-time values Ian Collins <ian-news@hotmail.com> - 2013-01-24 13:55 +1300
Re: Initializing a malloc'ed struct whose fields are const with run-time values Ben Bacarisse <ben.usenet@bsb.me.uk> - 2013-01-24 02:44 +0000
Re: Initializing a malloc'ed struct whose fields are const with run-time values Tim Rentsch <txr@alumni.caltech.edu> - 2013-01-23 21:39 -0800
Re: Initializing a malloc'ed struct whose fields are const with run-time values Shao Miller <sha0.miller@gmail.com> - 2013-01-24 00:54 -0500
Re: Initializing a malloc'ed struct whose fields are const with run-time values Ben Bacarisse <ben.usenet@bsb.me.uk> - 2013-01-24 17:56 +0000
Re: Initializing a malloc'ed struct whose fields are const with run-time values Tim Rentsch <txr@alumni.caltech.edu> - 2013-01-24 13:58 -0800
Re: Initializing a malloc'ed struct whose fields are const with run-time values James Kuyper <jameskuyper@verizon.net> - 2013-01-22 16:37 -0500
Re: Initializing a malloc'ed struct whose fields are const with run-time values Tim Rentsch <txr@alumni.caltech.edu> - 2013-01-22 21:22 -0800
Re: Initializing a malloc'ed struct whose fields are const with run-time values Tim Rentsch <txr@alumni.caltech.edu> - 2013-01-22 21:06 -0800
Re: Initializing a malloc'ed struct whose fields are const with run-time values Ian Collins <ian-news@hotmail.com> - 2013-01-23 19:55 +1300
Re: Initializing a malloc'ed struct whose fields are const with run-time values Tim Rentsch <txr@alumni.caltech.edu> - 2013-01-23 00:48 -0800
Re: Initializing a malloc'ed struct whose fields are const with run-time values Ian Collins <ian-news@hotmail.com> - 2013-01-23 23:06 +1300
Re: Initializing a malloc'ed struct whose fields are const with run-time values Ben Bacarisse <ben.usenet@bsb.me.uk> - 2013-01-22 21:02 +0000
Re: Initializing a malloc'ed struct whose fields are const with run-time values Shao Miller <sha0.miller@gmail.com> - 2013-01-22 16:12 -0500
Re: Initializing a malloc'ed struct whose fields are const with run-time values Ben Bacarisse <ben.usenet@bsb.me.uk> - 2013-01-22 22:37 +0000
Re: Initializing a malloc'ed struct whose fields are const with run-time values Shao Miller <sha0.miller@gmail.com> - 2013-01-22 22:29 -0500
Re: Initializing a malloc'ed struct whose fields are const with run-time values Ben Bacarisse <ben.usenet@bsb.me.uk> - 2013-01-23 04:28 +0000
Re: Initializing a malloc'ed struct whose fields are const with run-time values Shao Miller <sha0.miller@gmail.com> - 2013-01-23 00:07 -0500
Re: Initializing a malloc'ed struct whose fields are const with run-time values Ben Bacarisse <ben.usenet@bsb.me.uk> - 2013-01-23 14:04 +0000
Re: Initializing a malloc'ed struct whose fields are const with run-time values Noob <root@localhost> - 2013-01-22 22:10 +0100
Re: Initializing a malloc'ed struct whose fields are const with run-time values Ben Bacarisse <ben.usenet@bsb.me.uk> - 2013-01-22 21:13 +0000
Re: Initializing a malloc'ed struct whose fields are const with run-time values Shao Miller <sha0.miller@gmail.com> - 2013-01-22 16:25 -0500
Re: Initializing a malloc'ed struct whose fields are const with run-time values Ben Bacarisse <ben.usenet@bsb.me.uk> - 2013-01-22 22:21 +0000
Re: Initializing a malloc'ed struct whose fields are const with run-time values William Ahern <william@wilbur.25thandClement.com> - 2013-01-22 13:32 -0800
Re: Initializing a malloc'ed struct whose fields are const with run-time values Ben Bacarisse <ben.usenet@bsb.me.uk> - 2013-01-23 03:50 +0000
Re: Initializing a malloc'ed struct whose fields are const with run-time values Nick Bowler <nbowler@draconx.ca> - 2013-01-22 21:43 +0000
Re: Initializing a malloc'ed struct whose fields are const with run-time values Ben Bacarisse <ben.usenet@bsb.me.uk> - 2013-01-23 03:45 +0000
Re: Initializing a malloc'ed struct whose fields are const with run-time values Keith Thompson <kst-u@mib.org> - 2013-01-24 08:23 -0800
Re: Initializing a malloc'ed struct whose fields are const with run-time values Tim Rentsch <txr@alumni.caltech.edu> - 2013-01-22 20:48 -0800
Page 2 of 4 — ← Prev page 1 [2] 3 4 Next page →
| From | Ben Bacarisse <ben.usenet@bsb.me.uk> |
|---|---|
| Date | 2013-01-22 21:05 +0000 |
| Message-ID | <0.fa15a69006d5f876011f.20130122210519GMT.87k3r53p4g.fsf@bsb.me.uk> |
| In reply to | #30514 |
Shao Miller <sha0.miller@gmail.com> writes:
> On 1/22/2013 12:59, Ike Naar wrote:
>> On 2013-01-22, Noob <root@127.0.0.1> wrote:
>>> #include <stdlib.h>
>>> #include <string.h>
>>> struct toto *foo(int i, float f, void *p)
>>> {
>>> struct toto s = { i, f, p };
>>> struct toto *res = malloc(sizeof *res);
>>> if (res != NULL) memcpy(res, &s, sizeof s);
>>
>> Why memcpy instead of an assignment?
>> if (res != NULL) *res = s;
>>
>
> Because they amount to the same thing, behind the scenes, on a few
> implementations? ;)
But in front of the scenes, they are very different! The assignment is
a constraint violation.
<snip>
--
Ben.
[toc] | [prev] | [next] | [standalone]
| From | Shao Miller <sha0.miller@gmail.com> |
|---|---|
| Date | 2013-01-22 16:15 -0500 |
| Message-ID | <kdmvgr$jbm$1@dont-email.me> |
| In reply to | #30524 |
On 1/22/2013 16:05, Ben Bacarisse wrote:
> Shao Miller <sha0.miller@gmail.com> writes:
>
>> On 1/22/2013 12:59, Ike Naar wrote:
>>> On 2013-01-22, Noob <root@127.0.0.1> wrote:
>>>> #include <stdlib.h>
>>>> #include <string.h>
>>>> struct toto *foo(int i, float f, void *p)
>>>> {
>>>> struct toto s = { i, f, p };
>>>> struct toto *res = malloc(sizeof *res);
>>>> if (res != NULL) memcpy(res, &s, sizeof s);
>>>
>>> Why memcpy instead of an assignment?
>>> if (res != NULL) *res = s;
>>>
>>
>> Because they amount to the same thing, behind the scenes, on a few
>> implementations? ;)
>
> But in front of the scenes, they are very different! The assignment is
> a constraint violation.
>
> <snip>
>
Yes, that's quite true. I was teasing about a bad reason for doing it,
not pointing out a good reason for doing it. :)
--
- Shao Miller
--
"Thank you for the kind words; those are the kind of words I like to hear.
Cheerily," -- Richard Harter
[toc] | [prev] | [next] | [standalone]
| From | Ian Collins <ian-news@hotmail.com> |
|---|---|
| Date | 2013-01-23 09:43 +1300 |
| Subject | Re: Initializing a malloc'ed struct whose fields are const with run-time values |
| Message-ID | <am8bvaFbgsgU2@mid.individual.net> |
| In reply to | #30511 |
Ike Naar wrote:
> On 2013-01-22, Noob <root@127.0.0.1> wrote:
>> #include <stdlib.h>
>> #include <string.h>
>> struct toto *foo(int i, float f, void *p)
>> {
>> struct toto s = { i, f, p };
>> struct toto *res = malloc(sizeof *res);
>> if (res != NULL) memcpy(res, &s, sizeof s);
>
> Why memcpy instead of an assignment?
> if (res != NULL) *res = s;
>
>> return res;
>> }
>
> And how about returning by value?
>
> struct toto foo(int i, float f, void *p)
> {
> struct toto res = {i, f, p};
> return res;
> }
Is that legal? struct toto has const members, so can it be returned by
value from a function?
--
Ian Collins
[toc] | [prev] | [next] | [standalone]
| From | William Ahern <william@wilbur.25thandClement.com> |
|---|---|
| Date | 2013-01-22 13:19 -0800 |
| Subject | Re: Initializing a malloc'ed struct whose fields are const with run-time values |
| Message-ID | <gcc3t9-6br.ln1@wilbur.25thandClement.com> |
| In reply to | #30520 |
Ian Collins <ian-news@hotmail.com> wrote:
> Ike Naar wrote:
> > On 2013-01-22, Noob <root@127.0.0.1> wrote:
> >> #include <stdlib.h>
> >> #include <string.h>
> >> struct toto *foo(int i, float f, void *p)
> >> {
> >> struct toto s = { i, f, p };
> >> struct toto *res = malloc(sizeof *res);
> >> if (res != NULL) memcpy(res, &s, sizeof s);
> >
> > Why memcpy instead of an assignment?
> > if (res != NULL) *res = s;
> >
> >> return res;
> >> }
> >
> > And how about returning by value?
> >
> > struct toto foo(int i, float f, void *p)
> > {
> > struct toto res = {i, f, p};
> > return res;
> > }
> Is that legal? struct toto has const members, so can it be returned by
> value from a function?
What about foo().f? Does the simple return constitute modification of a
const-qualified lvalue?
I'm still not convinced that "modifying" a const-qualified member through
assignment of a non-const-qualified aggregate is undefined behaviour. But I
don't know enough about the rules of lvalues to prove it.
[toc] | [prev] | [next] | [standalone]
| From | William Ahern <william@wilbur.25thandClement.com> |
|---|---|
| Date | 2013-01-22 13:35 -0800 |
| Subject | Re: Initializing a malloc'ed struct whose fields are const with run-time values |
| Message-ID | <49d3t9-7rb.ln1@wilbur.25thandClement.com> |
| In reply to | #30533 |
William Ahern <william@wilbur.25thandclement.com> wrote:
> Ian Collins <ian-news@hotmail.com> wrote:
> > Ike Naar wrote:
<snip>
> > > And how about returning by value?
> > >
> > > struct toto foo(int i, float f, void *p)
> > > {
> > > struct toto res = {i, f, p};
> > > return res;
> > > }
> > Is that legal? struct toto has const members, so can it be returned by
> > value from a function?
> What about foo().f? Does the simple return constitute modification of a
> const-qualified lvalue?
> I'm still not convinced that "modifying" a const-qualified member through
> assignment of a non-const-qualified aggregate is undefined behaviour. But I
> don't know enough about the rules of lvalues to prove it.
Ok, now I am:
C99 (N1256) 6.3.2.1
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.
But foo().f should still be fine, I think.
[toc] | [prev] | [next] | [standalone]
| From | Ian Collins <ian-news@hotmail.com> |
|---|---|
| Date | 2013-01-23 10:45 +1300 |
| Subject | Re: Initializing a malloc'ed struct whose fields are const with run-time values |
| Message-ID | <am8fjtFbgsgU4@mid.individual.net> |
| In reply to | #30536 |
William Ahern wrote:
> William Ahern <william@wilbur.25thandclement.com> wrote:
>> Ian Collins <ian-news@hotmail.com> wrote:
>>> Ike Naar wrote:
> <snip>
>>>> And how about returning by value?
>>>>
>>>> struct toto foo(int i, float f, void *p)
>>>> {
>>>> struct toto res = {i, f, p};
>>>> return res;
>>>> }
>
>>> Is that legal? struct toto has const members, so can it be returned by
>>> value from a function?
>
>> What about foo().f? Does the simple return constitute modification of a
>> const-qualified lvalue?
>
>> I'm still not convinced that "modifying" a const-qualified member through
>> assignment of a non-const-qualified aggregate is undefined behaviour. But I
>> don't know enough about the rules of lvalues to prove it.
>
> Ok, now I am:
>
> C99 (N1256) 6.3.2.1
>
> 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.
>
> But foo().f should still be fine, I think.
So res above isn't a modifiable lvalue.
I just tried this code:
#include <stdio.h>
struct toto { const int i; const float f; const void *p; };
struct toto foo(int i, float f, void *p)
{
return (struct toto){i, f, p};
}
int main(void)
{
float f = foo( 1,2,NULL).f;
}
and gcc (-Wall -std=c99 -pedantic) compiles it, but Sun c99 (which tends
to be both strict and conforming) rejects it with one error:
"x.c", line 7: left operand must be modifiable lvalue: op "="
where line 7 is the function return.
--
Ian Collins
[toc] | [prev] | [next] | [standalone]
| From | Shao Miller <sha0.miller@gmail.com> |
|---|---|
| Date | 2013-01-22 17:07 -0500 |
| Subject | Re: Initializing a malloc'ed struct whose fields are const with run-time values |
| Message-ID | <kdn2ji$878$1@dont-email.me> |
| In reply to | #30540 |
On 1/22/2013 16:45, Ian Collins wrote:
> William Ahern wrote:
>> William Ahern <william@wilbur.25thandclement.com> wrote:
>>> Ian Collins <ian-news@hotmail.com> wrote:
>>>> Ike Naar wrote:
>> <snip>
>>>>> And how about returning by value?
>>>>>
>>>>> struct toto foo(int i, float f, void *p)
>>>>> {
>>>>> struct toto res = {i, f, p};
>>>>> return res;
>>>>> }
>>
>>>> Is that legal? struct toto has const members, so can it be returned by
>>>> value from a function?
>>
>>> What about foo().f? Does the simple return constitute modification of a
>>> const-qualified lvalue?
>>
>>> I'm still not convinced that "modifying" a const-qualified member
>>> through
>>> assignment of a non-const-qualified aggregate is undefined behaviour.
>>> But I
>>> don't know enough about the rules of lvalues to prove it.
>>
>> Ok, now I am:
>>
>> C99 (N1256) 6.3.2.1
>>
>> 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.
>>
>> But foo().f should still be fine, I think.
>
> So res above isn't a modifiable lvalue.
>
> I just tried this code:
>
> #include <stdio.h>
>
> struct toto { const int i; const float f; const void *p; };
>
> struct toto foo(int i, float f, void *p)
> {
> return (struct toto){i, f, p};
> }
>
> int main(void)
> {
> float f = foo( 1,2,NULL).f;
> }
>
> and gcc (-Wall -std=c99 -pedantic) compiles it, but Sun c99 (which tends
> to be both strict and conforming) rejects it with one error:
>
> "x.c", line 7: left operand must be modifiable lvalue: op "="
>
> where line 7 is the function return.
>
That seems a bit odd. 'return' has little to do with an lvalue or object:
"The properties associated with qualified types are meaningful only
for expressions that are lvalues.132)"
So "as if by assignment" should be satisfied by:
"the left operand has an atomic, qualified, or unqualified version of
a structure or union type compatible with the type of the right;"
No?
--
- Shao Miller
--
"Thank you for the kind words; those are the kind of words I like to hear.
Cheerily," -- Richard Harter
[toc] | [prev] | [next] | [standalone]
| From | Tim Rentsch <txr@alumni.caltech.edu> |
|---|---|
| Date | 2013-01-22 21:29 -0800 |
| Subject | Re: Initializing a malloc'ed struct whose fields are const with run-time values |
| Message-ID | <kfn38xssc0i.fsf@x-alumni2.alumni.caltech.edu> |
| In reply to | #30540 |
Ian Collins <ian-news@hotmail.com> writes:
>> [snip]
>>
> I just tried this code:
>
> #include <stdio.h>
>
> struct toto { const int i; const float f; const void *p; };
>
> struct toto foo(int i, float f, void *p)
> {
> return (struct toto){i, f, p};
> }
>
> int main(void)
> {
> float f = foo( 1,2,NULL).f;
> }
>
> and gcc (-Wall -std=c99 -pedantic) compiles it, but Sun c99 (which
> tends to be both strict and conforming) rejects it with one error:
>
> "x.c", line 7: left operand must be modifiable lvalue: op "="
>
> where line 7 is the function return.
I believe gcc has it right here. Even the error message from
the Sun compiler suggests they were thinking of this like a
kind of assignment, which it certainly isn't in this case.
[toc] | [prev] | [next] | [standalone]
| From | Ben Bacarisse <ben.usenet@bsb.me.uk> |
|---|---|
| Date | 2013-01-23 13:54 +0000 |
| Subject | Re: Initializing a malloc'ed struct whose fields are const with run-time values |
| Message-ID | <0.587c540b10d4d98feb70.20130123135415GMT.87zk000zug.fsf@bsb.me.uk> |
| In reply to | #30561 |
Tim Rentsch <txr@alumni.caltech.edu> writes:
> Ian Collins <ian-news@hotmail.com> writes:
>
>>> [snip]
>>>
>> I just tried this code:
>>
>> #include <stdio.h>
>>
>> struct toto { const int i; const float f; const void *p; };
>>
>> struct toto foo(int i, float f, void *p)
>> {
>> return (struct toto){i, f, p};
>> }
>>
>> int main(void)
>> {
>> float f = foo( 1,2,NULL).f;
>> }
>>
>> and gcc (-Wall -std=c99 -pedantic) compiles it, but Sun c99 (which
>> tends to be both strict and conforming) rejects it with one error:
>>
>> "x.c", line 7: left operand must be modifiable lvalue: op "="
>>
>> where line 7 is the function return.
>
> I believe gcc has it right here. Even the error message from
> the Sun compiler suggests they were thinking of this like a
> kind of assignment, which it certainly isn't in this case.
As you say elsewhere, the assignment-like nature of the return only
kicks in when the types differ, but even when it does, I'd take "is
converted as if by assignment" to mean that only the conversion and type
constraints of assignment are to be considered. (The constraints being
important because they would, for example, prevent a function with type
'T *' returning a 'const T * value without a diagnostic).
More curious to me is that gcc (in conforming mode) permits this:
struct toto { const int i; const float f; const void *p; };
struct toto foo(int i, float f, void *p)
{
return (struct toto){i, f, p};
}
int bar(struct toto p) { return p.i; }
int main(void)
{
return bar(foo(1, 2, 0));
}
but 6.5.2.2 p2 says:
"Each argument shall have a type such that its value may be assigned
to an object with the unqualified version of the type of its
corresponding parameter."
The phrase "unqualified version of the type" can't surely be intended to
mean the recursive removal of all type qualifiers. Elsewhere it simply
means that the "top level" qualifiers are removed. If that's the right
interpretation, the call to bar should be a constraint violation.
It looks like gcc is borrowing from C++ where argument passing is
defined to like initialisation (which I've always found that to be more
logical than C's assignment-like call semantics). Anyway, either I'm
misreading something or gcc has missed something.
--
Ben.
[toc] | [prev] | [next] | [standalone]
| From | Shao Miller <sha0.miller@gmail.com> |
|---|---|
| Date | 2013-01-23 17:08 -0500 |
| Subject | Re: Initializing a malloc'ed struct whose fields are const with run-time values |
| Message-ID | <kdpn11$79e$1@dont-email.me> |
| In reply to | #30573 |
On 1/23/2013 08:54, Ben Bacarisse wrote:
> Tim Rentsch <txr@alumni.caltech.edu> writes:
>
>> Ian Collins <ian-news@hotmail.com> writes:
>>
>>>> [snip]
>>>>
>>> I just tried this code:
>>>
>>> #include <stdio.h>
>>>
>>> struct toto { const int i; const float f; const void *p; };
>>>
>>> struct toto foo(int i, float f, void *p)
>>> {
>>> return (struct toto){i, f, p};
>>> }
>>>
>>> int main(void)
>>> {
>>> float f = foo( 1,2,NULL).f;
>>> }
>>>
>>> and gcc (-Wall -std=c99 -pedantic) compiles it, but Sun c99 (which
>>> tends to be both strict and conforming) rejects it with one error:
>>>
>>> "x.c", line 7: left operand must be modifiable lvalue: op "="
>>>
>>> where line 7 is the function return.
>>
>> I believe gcc has it right here. Even the error message from
>> the Sun compiler suggests they were thinking of this like a
>> kind of assignment, which it certainly isn't in this case.
>
> As you say elsewhere, the assignment-like nature of the return only
> kicks in when the types differ, but even when it does, I'd take "is
> converted as if by assignment" to mean that only the conversion and type
> constraints of assignment are to be considered. (The constraints being
> important because they would, for example, prevent a function with type
> 'T *' returning a 'const T * value without a diagnostic).
>
> More curious to me is that gcc (in conforming mode) permits this:
>
> struct toto { const int i; const float f; const void *p; };
>
> struct toto foo(int i, float f, void *p)
> {
> return (struct toto){i, f, p};
> }
>
> int bar(struct toto p) { return p.i; }
>
> int main(void)
> {
> return bar(foo(1, 2, 0));
> }
>
> but 6.5.2.2 p2 says:
>
> "Each argument shall have a type such that its value may be assigned
> to an object with the unqualified version of the type of its
> corresponding parameter."
>
> The phrase "unqualified version of the type" can't surely be intended to
> mean the recursive removal of all type qualifiers. Elsewhere it simply
> means that the "top level" qualifiers are removed. If that's the right
> interpretation, the call to bar should be a constraint violation.
>
Why? The result of the call to 'foo' yields a 'struct toto', which is
not qualified (and also isn't an lvalue).
> It looks like gcc is borrowing from C++ where argument passing is
> defined to like initialisation (which I've always found that to be more
> logical than C's assignment-like call semantics). Anyway, either I'm
> misreading something or gcc has missed something.
>
--
- Shao Miller
--
"Thank you for the kind words; those are the kind of words I like to hear.
Cheerily," -- Richard Harter
[toc] | [prev] | [next] | [standalone]
| From | Ian Collins <ian-news@hotmail.com> |
|---|---|
| Date | 2013-01-24 11:29 +1300 |
| Subject | Re: Initializing a malloc'ed struct whose fields are const with run-time values |
| Message-ID | <amb6hrFbhmbU2@mid.individual.net> |
| In reply to | #30581 |
Shao Miller wrote:
> On 1/23/2013 08:54, Ben Bacarisse wrote:
>> Tim Rentsch <txr@alumni.caltech.edu> writes:
>>
>>> Ian Collins <ian-news@hotmail.com> writes:
>>>
>>>>> [snip]
>>>>>
>>>> I just tried this code:
>>>>
>>>> #include <stdio.h>
>>>>
>>>> struct toto { const int i; const float f; const void *p; };
>>>>
>>>> struct toto foo(int i, float f, void *p)
>>>> {
>>>> return (struct toto){i, f, p};
>>>> }
>>>>
>>>> int main(void)
>>>> {
>>>> float f = foo( 1,2,NULL).f;
>>>> }
>>>>
>>>> and gcc (-Wall -std=c99 -pedantic) compiles it, but Sun c99 (which
>>>> tends to be both strict and conforming) rejects it with one error:
>>>>
>>>> "x.c", line 7: left operand must be modifiable lvalue: op "="
>>>>
>>>> where line 7 is the function return.
>>>
>>> I believe gcc has it right here. Even the error message from
>>> the Sun compiler suggests they were thinking of this like a
>>> kind of assignment, which it certainly isn't in this case.
>>
>> As you say elsewhere, the assignment-like nature of the return only
>> kicks in when the types differ, but even when it does, I'd take "is
>> converted as if by assignment" to mean that only the conversion and type
>> constraints of assignment are to be considered. (The constraints being
>> important because they would, for example, prevent a function with type
>> 'T *' returning a 'const T * value without a diagnostic).
>>
>> More curious to me is that gcc (in conforming mode) permits this:
>>
>> struct toto { const int i; const float f; const void *p; };
>>
>> struct toto foo(int i, float f, void *p)
>> {
>> return (struct toto){i, f, p};
>> }
>>
>> int bar(struct toto p) { return p.i; }
>>
>> int main(void)
>> {
>> return bar(foo(1, 2, 0));
>> }
>>
>> but 6.5.2.2 p2 says:
>>
>> "Each argument shall have a type such that its value may be assigned
>> to an object with the unqualified version of the type of its
>> corresponding parameter."
>>
>> The phrase "unqualified version of the type" can't surely be intended to
>> mean the recursive removal of all type qualifiers. Elsewhere it simply
>> means that the "top level" qualifiers are removed. If that's the right
>> interpretation, the call to bar should be a constraint violation.
>>
>
> Why? The result of the call to 'foo' yields a 'struct toto', which is
> not qualified (and also isn't an lvalue).
I think Ben's point is the *parameter* value may be *assigned*, not the
result of the expression.
I see Sun c99, which rejects the return in foo, also accepts bar.
--
Ian Collins
[toc] | [prev] | [next] | [standalone]
| From | Shao Miller <sha0.miller@gmail.com> |
|---|---|
| Date | 2013-01-23 18:26 -0500 |
| Subject | Re: Initializing a malloc'ed struct whose fields are const with run-time values |
| Message-ID | <kdprii$h72$1@dont-email.me> |
| In reply to | #30584 |
On 1/23/2013 17:29, Ian Collins wrote:
> Shao Miller wrote:
>> On 1/23/2013 08:54, Ben Bacarisse wrote:
>>> Tim Rentsch <txr@alumni.caltech.edu> writes:
>>>
>>>> Ian Collins <ian-news@hotmail.com> writes:
>>>>
>>>>>> [snip]
>>>>>>
>>>>> I just tried this code:
>>>>>
>>>>> #include <stdio.h>
>>>>>
>>>>> struct toto { const int i; const float f; const void *p; };
>>>>>
>>>>> struct toto foo(int i, float f, void *p)
>>>>> {
>>>>> return (struct toto){i, f, p};
>>>>> }
>>>>>
>>>>> int main(void)
>>>>> {
>>>>> float f = foo( 1,2,NULL).f;
>>>>> }
>>>>>
>>>>> and gcc (-Wall -std=c99 -pedantic) compiles it, but Sun c99 (which
>>>>> tends to be both strict and conforming) rejects it with one error:
>>>>>
>>>>> "x.c", line 7: left operand must be modifiable lvalue: op "="
>>>>>
>>>>> where line 7 is the function return.
>>>>
>>>> I believe gcc has it right here. Even the error message from
>>>> the Sun compiler suggests they were thinking of this like a
>>>> kind of assignment, which it certainly isn't in this case.
>>>
>>> As you say elsewhere, the assignment-like nature of the return only
>>> kicks in when the types differ, but even when it does, I'd take "is
>>> converted as if by assignment" to mean that only the conversion and type
>>> constraints of assignment are to be considered. (The constraints being
>>> important because they would, for example, prevent a function with type
>>> 'T *' returning a 'const T * value without a diagnostic).
>>>
>>> More curious to me is that gcc (in conforming mode) permits this:
>>>
>>> struct toto { const int i; const float f; const void *p; };
>>>
>>> struct toto foo(int i, float f, void *p)
>>> {
>>> return (struct toto){i, f, p};
>>> }
>>>
>>> int bar(struct toto p) { return p.i; }
>>>
>>> int main(void)
>>> {
>>> return bar(foo(1, 2, 0));
>>> }
>>>
>>> but 6.5.2.2 p2 says:
>>>
>>> "Each argument shall have a type such that its value may be assigned
>>> to an object with the unqualified version of the type of its
>>> corresponding parameter."
>>>
>>> The phrase "unqualified version of the type" can't surely be intended to
>>> mean the recursive removal of all type qualifiers. Elsewhere it simply
>>> means that the "top level" qualifiers are removed. If that's the right
>>> interpretation, the call to bar should be a constraint violation.
>>>
>>
>> Why? The result of the call to 'foo' yields a 'struct toto', which is
>> not qualified (and also isn't an lvalue).
>
> I think Ben's point is the *parameter* value may be *assigned*, not the
> result of the expression.
>
> I see Sun c99, which rejects the return in foo, also accepts bar.
>
As in, a constraint violation against 6.5.16p2? If so, why would that
constraint apply? There are still constraints in 6.5.16.1p1... As
asked elsethread, why pick out "modifiable" and not "lvalue"? Do we
need to worry about the constraints and semantics of 6.5.16.2? Isn't
backing up to 6.5.16 backing up too far?
--
- Shao Miller
--
"Thank you for the kind words; those are the kind of words I like to hear.
Cheerily," -- Richard Harter
[toc] | [prev] | [next] | [standalone]
| From | Ian Collins <ian-news@hotmail.com> |
|---|---|
| Date | 2013-01-24 14:03 +1300 |
| Subject | Re: Initializing a malloc'ed struct whose fields are const with run-time values |
| Message-ID | <ambfjhFbhmbU4@mid.individual.net> |
| In reply to | #30586 |
Shao Miller wrote: > On 1/23/2013 17:29, Ian Collins wrote: >> Shao Miller wrote: >>> On 1/23/2013 08:54, Ben Bacarisse wrote: >>>> >>>> but 6.5.2.2 p2 says: >>>> >>>> "Each argument shall have a type such that its value may be assigned >>>> to an object with the unqualified version of the type of its >>>> corresponding parameter." >>>> >>>> The phrase "unqualified version of the type" can't surely be intended to >>>> mean the recursive removal of all type qualifiers. Elsewhere it simply >>>> means that the "top level" qualifiers are removed. If that's the right >>>> interpretation, the call to bar should be a constraint violation. >>>> >>> >>> Why? The result of the call to 'foo' yields a 'struct toto', which is >>> not qualified (and also isn't an lvalue). >> >> I think Ben's point is the *parameter* value may be *assigned*, not the >> result of the expression. >> >> I see Sun c99, which rejects the return in foo, also accepts bar. >> > > As in, a constraint violation against 6.5.16p2? Yes. > If so, why would that constraint apply? Because of 6.5.2.2 p4, if you take the word "assigned" literally. -- Ian Collins
[toc] | [prev] | [next] | [standalone]
| From | Shao Miller <sha0.miller@gmail.com> |
|---|---|
| Date | 2013-01-23 23:58 -0500 |
| Subject | Re: Initializing a malloc'ed struct whose fields are const with run-time values |
| Message-ID | <kdqf23$6ci$1@dont-email.me> |
| In reply to | #30591 |
On 1/23/2013 20:03, Ian Collins wrote: > Shao Miller wrote: >> On 1/23/2013 17:29, Ian Collins wrote: >>> Shao Miller wrote: >>>> On 1/23/2013 08:54, Ben Bacarisse wrote: >>>>> >>>>> but 6.5.2.2 p2 says: >>>>> >>>>> "Each argument shall have a type such that its value may be >>>>> assigned >>>>> to an object with the unqualified version of the type of its >>>>> corresponding parameter." >>>>> >>>>> The phrase "unqualified version of the type" can't surely be >>>>> intended to >>>>> mean the recursive removal of all type qualifiers. Elsewhere it >>>>> simply >>>>> means that the "top level" qualifiers are removed. If that's the >>>>> right >>>>> interpretation, the call to bar should be a constraint violation. >>>>> >>>> >>>> Why? The result of the call to 'foo' yields a 'struct toto', which is >>>> not qualified (and also isn't an lvalue). >>> >>> I think Ben's point is the *parameter* value may be *assigned*, not the >>> result of the expression. >>> >>> I see Sun c99, which rejects the return in foo, also accepts bar. >>> >> >> As in, a constraint violation against 6.5.16p2? > > Yes. > >> If so, why would that constraint apply? > > Because of 6.5.2.2 p4, if you take the word "assigned" literally. > Did you mean if you _don't_ take it literally? I don't see "assigned" as a defined term, so I assume it's plain English. The Committee Response for Defect Report #212 includes "assigned" when their code shows initialization. Considering 6.9.1p11, does its use of "assigned" make sense if one of the parameters was 'const'-qualified? I don't think so. >> There are still constraints in 6.5.16.1p1... As asked elsethread, why pick out "modifiable" and not "lvalue"? Do we need to worry about the constraints and semantics of 6.5.16.2? Isn't backing up to 6.5.16 backing up too far? 6.7.3p4: "The properties associated with qualified types are meaningful only for expressions that are lvalues.132)" The "object" in "object with the unqualified version of the type of its corresponding parameter" seems to me to be a theoretical object and not an lvalue. It's not the parameter, for example, because the parameter could have a different type. So I don't grok a constraint violation against 6.5.16p2. -- - Shao Miller -- "Thank you for the kind words; those are the kind of words I like to hear. Cheerily," -- Richard Harter
[toc] | [prev] | [next] | [standalone]
| From | Ben Bacarisse <ben.usenet@bsb.me.uk> |
|---|---|
| Date | 2013-01-23 23:36 +0000 |
| Subject | Re: Initializing a malloc'ed struct whose fields are const with run-time values |
| Message-ID | <0.034ba52261503ab8aa1d.20130123233611GMT.877gn31nh0.fsf@bsb.me.uk> |
| In reply to | #30584 |
Ian Collins <ian-news@hotmail.com> writes:
> Shao Miller wrote:
>> On 1/23/2013 08:54, Ben Bacarisse wrote:
>>> Tim Rentsch <txr@alumni.caltech.edu> writes:
>>>
>>>> Ian Collins <ian-news@hotmail.com> writes:
>>>>
>>>>>> [snip]
>>>>>>
>>>>> I just tried this code:
>>>>>
>>>>> #include <stdio.h>
>>>>>
>>>>> struct toto { const int i; const float f; const void *p; };
>>>>>
>>>>> struct toto foo(int i, float f, void *p)
>>>>> {
>>>>> return (struct toto){i, f, p};
>>>>> }
>>>>>
>>>>> int main(void)
>>>>> {
>>>>> float f = foo( 1,2,NULL).f;
>>>>> }
>>>>>
>>>>> and gcc (-Wall -std=c99 -pedantic) compiles it, but Sun c99 (which
>>>>> tends to be both strict and conforming) rejects it with one error:
>>>>>
>>>>> "x.c", line 7: left operand must be modifiable lvalue: op "="
>>>>>
>>>>> where line 7 is the function return.
>>>>
>>>> I believe gcc has it right here. Even the error message from
>>>> the Sun compiler suggests they were thinking of this like a
>>>> kind of assignment, which it certainly isn't in this case.
>>>
>>> As you say elsewhere, the assignment-like nature of the return only
>>> kicks in when the types differ, but even when it does, I'd take "is
>>> converted as if by assignment" to mean that only the conversion and type
>>> constraints of assignment are to be considered. (The constraints being
>>> important because they would, for example, prevent a function with type
>>> 'T *' returning a 'const T * value without a diagnostic).
>>>
>>> More curious to me is that gcc (in conforming mode) permits this:
>>>
>>> struct toto { const int i; const float f; const void *p; };
>>>
>>> struct toto foo(int i, float f, void *p)
>>> {
>>> return (struct toto){i, f, p};
>>> }
>>>
>>> int bar(struct toto p) { return p.i; }
>>>
>>> int main(void)
>>> {
>>> return bar(foo(1, 2, 0));
>>> }
>>>
>>> but 6.5.2.2 p2 says:
>>>
>>> "Each argument shall have a type such that its value may be assigned
>>> to an object with the unqualified version of the type of its
>>> corresponding parameter."
>>>
>>> The phrase "unqualified version of the type" can't surely be intended to
>>> mean the recursive removal of all type qualifiers. Elsewhere it simply
>>> means that the "top level" qualifiers are removed. If that's the right
>>> interpretation, the call to bar should be a constraint violation.
>>>
>>
>> Why? The result of the call to 'foo' yields a 'struct toto', which is
>> not qualified (and also isn't an lvalue).
>
> I think Ben's point is the *parameter* value may be *assigned*, not
> the result of the expression.
Yes, the types are fine but a value of stuct foo type can't be assigned
to an object of that type. It reads as though parameter passing is,
essentially, assignment and whilst you can initialise a struct toto
object, you can't assign to one.
[I've just snipped a long and tedious paragraph trying to give some other
meaning to the phrasing, but since I don't buy it seems pointless to punt
it.]
> I see Sun c99, which rejects the return in foo, also accepts bar.
Interesting. Is it also a C++ compiler when given other options? C++
uses initialisation semantics for parameter passing, so it might be an
accident. Of course it could just be that the gcc and Sun c99 authors
are just better as reading standards!
--
Ben.
[toc] | [prev] | [next] | [standalone]
| From | Ian Collins <ian-news@hotmail.com> |
|---|---|
| Date | 2013-01-24 13:55 +1300 |
| Subject | Re: Initializing a malloc'ed struct whose fields are const with run-time values |
| Message-ID | <ambf3jFbhmbU3@mid.individual.net> |
| In reply to | #30587 |
Ben Bacarisse wrote: > Ian Collins <ian-news@hotmail.com> writes: > >> I see Sun c99, which rejects the return in foo, also accepts bar. > > Interesting. Is it also a C++ compiler when given other options? C++ > uses initialisation semantics for parameter passing, so it might be an > accident. Of course it could just be that the gcc and Sun c99 authors > are just better as reading standards! No, I'm sure the compilers have a different front end, their error messages have a different style. For example with struct toto t; t = foo( 1,2,NULL); c99 reports "x.c", line 17: left operand must be modifiable lvalue: op "=" while CC reports "x.c", line 16: Error: t must be initialized. "x.c", line 17: Error: toto has a const member i and cannot be assigned. -- Ian Collins
[toc] | [prev] | [next] | [standalone]
| From | Ben Bacarisse <ben.usenet@bsb.me.uk> |
|---|---|
| Date | 2013-01-24 02:44 +0000 |
| Subject | Re: Initializing a malloc'ed struct whose fields are const with run-time values |
| Message-ID | <0.2f9d39b612ab01506709.20130124024406GMT.87txq7z4eh.fsf@bsb.me.uk> |
| In reply to | #30590 |
Ian Collins <ian-news@hotmail.com> writes: > Ben Bacarisse wrote: >> Ian Collins <ian-news@hotmail.com> writes: >> >>> I see Sun c99, which rejects the return in foo, also accepts bar. >> >> Interesting. Is it also a C++ compiler when given other options? C++ >> uses initialisation semantics for parameter passing, so it might be an >> accident. Of course it could just be that the gcc and Sun c99 authors >> are just better as reading standards! > > No, I'm sure the compilers have a different front end, their error > messages have a different style. Ah, right. Thanks. Just another data point: Comeau's online C99 compiler accepts it (both the return and the call of 'bar'). <snip> -- Ben.
[toc] | [prev] | [next] | [standalone]
| From | Tim Rentsch <txr@alumni.caltech.edu> |
|---|---|
| Date | 2013-01-23 21:39 -0800 |
| Subject | Re: Initializing a malloc'ed struct whose fields are const with run-time values |
| Message-ID | <kfn622n6sxu.fsf@x-alumni2.alumni.caltech.edu> |
| In reply to | #30573 |
Ben Bacarisse <ben.usenet@bsb.me.uk> writes:
> Tim Rentsch <txr@alumni.caltech.edu> writes:
>
>> Ian Collins <ian-news@hotmail.com> writes:
>>
>>>> [snip]
>>>>
>>> I just tried this code:
>>>
>>> #include <stdio.h>
>>>
>>> struct toto { const int i; const float f; const void *p; };
>>>
>>> struct toto foo(int i, float f, void *p)
>>> {
>>> return (struct toto){i, f, p};
>>> }
>>>
>>> int main(void)
>>> {
>>> float f = foo( 1,2,NULL).f;
>>> }
>>>
>>> and gcc (-Wall -std=c99 -pedantic) compiles it, but Sun c99
>>> (which tends to be both strict and conforming) rejects it
>>> with one error:
>>>
>>> "x.c", line 7: left operand must be modifiable lvalue: op "="
>>>
>>> where line 7 is the function return.
>>
>> I believe gcc has it right here. Even the error message from
>> the Sun compiler suggests they were thinking of this like a
>> kind of assignment, which it certainly isn't in this case.
>
> As you say elsewhere, the assignment-like nature of the return
> only kicks in when the types differ, but even when it does, I'd
> take "is converted as if by assignment" to mean that only the
> conversion and type constraints of assignment are to be
> considered.
I assume you mean >simple< assignment in the last part of that
sentence.
> (The constraints being important because they would, for example,
> prevent a function with type 'T *' returning a 'const T * value
> without a diagnostic).
I expect you're right if we're talking about what meaning was
intended. However, just in terms of what is written, it's hard
to make that stand up considering other parts of the Standard.
In both of the other two cases (those being function arguments
and initializer expressions) where there are similar concerns,
the limiting constraints are identified explicitly. So their
absence for 'return' stands out -- exceptio probat regulam in
casibus non exceptis, and all that. In all likelihood though
that was just an oversight, and a reasonable inference for
purposes of comp.lang.c is the constraints of simple assignment
are meant to apply.
> More curious to me is that gcc (in conforming mode) permits
> this:
>
> struct toto { const int i; const float f; const void *p; };
>
> struct toto foo(int i, float f, void *p)
> {
> return (struct toto){i, f, p};
> }
>
> int bar(struct toto p) { return p.i; }
>
> int main(void)
> {
> return bar(foo(1, 2, 0));
> }
>
> but 6.5.2.2 p2 says:
>
> "Each argument shall have a type such that its value may be
> assigned to an object with the unqualified version of the
> type of its corresponding parameter."
>
> The phrase "unqualified version of the type" can't surely be
> intended to mean the recursive removal of all type qualifiers.
> Elsewhere it simply means that the "top level" qualifiers are
> removed. If that's the right interpretation, the call to bar
> should be a constraint violation.
>
> [speculation about why gcc acts as it does] Anyway, either
> I'm misreading something or gcc has missed something.
Yes, your analysis looks spot on.
Here though I think we're looking at the flip side of the coin.
That is, this case also represents an oversight, only here the
result is more restrictive rather than less restrictive. It
seems unlikely that this tiny incompatibility would knowingly be
imposed just for function arguments, especially since it is
clearly a useful capability to support, and initialization
semantics are so intuitively natural. I expect it was just an
accident of how the writing happened -- provisions were put in to
handle the common cases, and this one unusual case fell through
the cracks. (And you can see how someone reading the rules for
function arguments might gloss over the distinction between the
two ways "unqualified version of the type" might be read.) In
a way it's good to see that common sense has prevailed (ie, in
gcc, and also I think another compiler was mentioned in another
posting) about what was meant here. All that remains is making
sure what's in the Standard gets updated to reflect that.
[toc] | [prev] | [next] | [standalone]
| From | Shao Miller <sha0.miller@gmail.com> |
|---|---|
| Date | 2013-01-24 00:54 -0500 |
| Subject | Re: Initializing a malloc'ed struct whose fields are const with run-time values |
| Message-ID | <kdqia9$j95$1@dont-email.me> |
| In reply to | #30602 |
On 1/24/2013 00:39, Tim Rentsch wrote:
>
> Here though I think we're looking at the flip side of the coin.
> That is, this case also represents an oversight, only here the
> result is more restrictive rather than less restrictive. It
> seems unlikely that this tiny incompatibility would knowingly be
> imposed just for function arguments, especially since it is
> clearly a useful capability to support, and initialization
> semantics are so intuitively natural. I expect it was just an
> accident of how the writing happened -- provisions were put in to
> handle the common cases, and this one unusual case fell through
> the cracks. (And you can see how someone reading the rules for
> function arguments might gloss over the distinction between the
> two ways "unqualified version of the type" might be read.) In
> a way it's good to see that common sense has prevailed (ie, in
> gcc, and also I think another compiler was mentioned in another
> posting) about what was meant here. All that remains is making
> sure what's in the Standard gets updated to reflect that.
>
I don't see how you can reconcile a 'const'-qualified parameter with
these two paragraphs of 6.9.1, if the "modifiable lvalue" from 6.5.16p2
has any bearing:
"10 On entry to the function, the size expressions of each variably
modified parameter are evaluated and the value of each argument
expression is converted to the type of the corresponding parameter as if
by assignment. (Array expressions and function designators as arguments
were converted to pointers before the call.)
11 After all parameters have been assigned, the compound statement
that constitutes the body of the function definition is executed."
--
- Shao Miller
--
"Thank you for the kind words; those are the kind of words I like to hear.
Cheerily," -- Richard Harter
[toc] | [prev] | [next] | [standalone]
| From | Ben Bacarisse <ben.usenet@bsb.me.uk> |
|---|---|
| Date | 2013-01-24 17:56 +0000 |
| Subject | Re: Initializing a malloc'ed struct whose fields are const with run-time values |
| Message-ID | <0.1827e26976fc5b0b81cf.20130124175614GMT.87fw1qzcqp.fsf@bsb.me.uk> |
| In reply to | #30602 |
Tim Rentsch <txr@alumni.caltech.edu> writes:
> Ben Bacarisse <ben.usenet@bsb.me.uk> writes:
<snip>
>> More curious to me is that gcc (in conforming mode) permits
>> this:
>>
>> struct toto { const int i; const float f; const void *p; };
>>
>> struct toto foo(int i, float f, void *p)
>> {
>> return (struct toto){i, f, p};
>> }
>>
>> int bar(struct toto p) { return p.i; }
>>
>> int main(void)
>> {
>> return bar(foo(1, 2, 0));
>> }
>>
>> but 6.5.2.2 p2 says:
>>
>> "Each argument shall have a type such that its value may be
>> assigned to an object with the unqualified version of the
>> type of its corresponding parameter."
>>
>> The phrase "unqualified version of the type" can't surely be
>> intended to mean the recursive removal of all type qualifiers.
>> Elsewhere it simply means that the "top level" qualifiers are
>> removed. If that's the right interpretation, the call to bar
>> should be a constraint violation.
>>
>> [speculation about why gcc acts as it does] Anyway, either
>> I'm misreading something or gcc has missed something.
>
> Yes, your analysis looks spot on.
>
> Here though I think we're looking at the flip side of the coin.
> That is, this case also represents an oversight, only here the
> result is more restrictive rather than less restrictive. It
> seems unlikely that this tiny incompatibility would knowingly be
> imposed just for function arguments, especially since it is
> clearly a useful capability to support, and initialization
> semantics are so intuitively natural. I expect it was just an
> accident of how the writing happened -- provisions were put in to
> handle the common cases, and this one unusual case fell through
> the cracks. (And you can see how someone reading the rules for
> function arguments might gloss over the distinction between the
> two ways "unqualified version of the type" might be read.) In
> a way it's good to see that common sense has prevailed (ie, in
> gcc, and also I think another compiler was mentioned in another
> posting) about what was meant here. All that remains is making
> sure what's in the Standard gets updated to reflect that.
One option would be to define function calling in terms of
initialization but that may have unforeseen consequences. Something like
"Each argument shall have a type such that its value may be used as a
single expression initializer of its corresponding parameter."
and later:
"In preparing for the call to a function, the arguments are evaluated,
and each parameter is initialized using the value of the corresponding
argument."
At first glance, all the right wording is there, at least for scalar
types:
11 The initializer for a scalar shall be a single expression,
optionally enclosed in braces. The initial value of the object is
that of the expression (after conversion); the same type
constraints and conversions as for simple assignment apply, taking
the type of the scalar to be the unqualified version of its
declared type."
but then paragraph 13 surprised me a little:
13 The initializer for a structure or union object that has automatic
storage duration shall be either an initializer list as described
below, or a single expression that has compatible structure or
union type. In the latter case, the initial value of the object,
including unnamed members, is that of the expression.
This is from the "semantics" section, so for structure and union types
there is no constraint violation if the types are not compatible.
Whilst this is an odd anomaly of initialization, it's probably
unacceptable for function calls -- you really want to mandate a
diagnostic when the types don't match.
Also, on a side issue, the wording about disregarding the type's
qualifiers is also missing. Obviously
const struct s = (struct s){0};
is supposed to be permitted, so is "struct s" a "compatible structure or
union type"? Probably. It's not a compatible type, but the extra words
might be there to suggest that it's only the structural part that is to
be considered. I'd rather that were more explicit, though.
--
Ben.
[toc] | [prev] | [next] | [standalone]
Page 2 of 4 — ← Prev page 1 [2] 3 4 Next page →
Back to top | Article view | comp.lang.c
csiph-web