andy@cit-vax.Caltech.Edu (Andy Fyfe) (10/15/89)
The GNU C compiler permits assignment (where assignment includes things such as parameter passing) of a "char *" to a "const char *", but not of a "char **" to a "const char **" without an explicit cast. Rms assures me that this is in strict accordance with the ANSI standard. This came up when I provided the following prototype for execv: extern int execv(const char *path, const char **args); Gcc gave a warning about incompatible pointer types when execv was called with a "char **" as the second parameter. While "execv" may be a bad example (as it's not expected to return at all), my understanding of such a prototype is that the function will not change the characters pointed to by "path", or by "args[0], args[1], ...". Passing pointers that permit such changes I would expect to be allowed (and is, for "path"). I was wondering if someone could clarify this for me. Andy Fyfe andy@csvax.caltech.edu wjafyfe@caltech.bitnet andy@cit-vax.UUCP (...!ames!elroy!cit-vax!andy)
gwyn@smoke.BRL.MIL (Doug Gwyn) (10/16/89)
In article <12239@cit-vax.Caltech.Edu> andy@csvax.caltech.edu (Andy Fyfe) writes: >The GNU C compiler permits assignment (where assignment includes >things such as parameter passing) of a "char *" to a "const char *", >but not of a "char **" to a "const char **" without an explicit >cast. Rms assures me that this is in strict accordance with the >ANSI standard. Yes, the arguments must be "assignment compatible" with the corresponding parameters declared in the prototype. The rules for this are given in Section 3.3.16.1 "Constraints". Violation of a Constraint requires that a diagnostic be issued. The relevant constraint from 3.3.2.2 is that the (zeroth-level) argument type must be assignable to the (zeroth-level) parameter type after the parameter type has the 0th-level type qualifiers stripped (the qualifier is second-level in this example), and the relevant assignment-compatibility constraints are that the (first-level) types pointed to, i.e. (const char *) and (char *), be compatible ignoring FIRST-LEVEL qualifiers (there are none in this example), and the type pointed to by the parameter type, i.e. (const char *), have all the qualifiers of the type pointed to by the argument type, i.e. (char *), which it does NOT -- thus the constraint violation. Note that the first-level ignoring of qualifiers on the pointed-to types allows a (char *) argument to be passed without casting to a function declared as taking a (const char *) parameter, but the qualifier-ignoring does not occur at second or lower levels. > extern int execv(const char *path, const char **args); >... my understanding of such a prototype is that the >function will not change the characters pointed to by "path", or >by "args[0], args[1], ...". Passing pointers that permit such >changes I would expect to be allowed (and is, for "path"). You understand the meaning okay. The problem ultimately stems from a slight overloading of semantics for "const". You have to either use compatible types, or use a cast when invoking the function. Another interesting possibility is to declare the second argument as (char * const *), which is true of execv() (it doesn't modify the pointers in the args[] array either). While not as helpful as what you want, it works with the special rule for pointer first levels as explained previously. Of course the fully constrained spec is extern int execv( const char *path, const char *const *args ); Personally I would opt for extern int execv( const char *path, char *const *args ); as the most restrictive declaration that doesn't cause user hassles.
maart@cs.vu.nl (Maarten Litmaath) (10/16/89)
gwyn@smoke.BRL.MIL (Doug Gwyn) writes:
\... Note that the
\first-level ignoring of qualifiers on the pointed-to types allows a
\(char *) argument to be passed without casting to a function declared as
\taking a (const char *) parameter, but the qualifier-ignoring does not
\occur at second or lower levels.
^^^^^^^^^^^^^^^^^^^^^^
Why? (See below.)
\> extern int execv(const char *path, const char **args);
\>... my understanding of such a prototype is that the
\>function will not change the characters pointed to by "path", or
\>by "args[0], args[1], ...". Passing pointers that permit such
\>changes I would expect to be allowed (and is, for "path").
\
\You understand the meaning okay. The problem ultimately stems from a
\slight overloading of semantics for "const". [...]
Could you elaborate on this counter-intuitivity?
--
The UNIX Way of doing something [...] is to make it look as much like a filter
as possible. (Richard O'Keefe) | Maarten Litmaath (mcsun!botter!maart)
gwyn@smoke.BRL.MIL (Doug Gwyn) (10/17/89)
In article <3728@solo10.cs.vu.nl> maart@cs.vu.nl (Maarten Litmaath) writes: >Why? (See below.) The added complexity required to accurately specify what you might think should be the rule for these other cases was not judged to be worth the effort. As it is, we were changing the wording about this stuff up to practically the last minute before printing the final draft, because of the difficulty in getting even the simpler case specified (a) right, and (b) intelligibly. The simpler case suffices for the Standard library functions (str*() and mem*() in particular), and it was necessary to get that right. >\slight overloading of semantics for "const". [...] >Could you elaborate on this counter-intuitivity? Given your propensity for grumbling about the standardization process, I'm not sure I should. In essence, a couple of years ago Tom Plum (I think it was) identified the source of committee disputes about the meaning of type qualifiers as due to there being three essentially orthogonal attributes involved, not the two that we had been wrangling with ("const" and "volatile"). That allowed separating out the "noalias" meaning from "readonly", both of which had been confused together in "const". Subsequently, "const" was in effect redefined to have the "readonly" meaning and "noalias" was added as a separate type qualifier. To make a long story short, we had to retract "noalias" late in the review process, which left us with the newly resurfaced problem of specifying the library facilities such as str*() parameters in a way that had formerly been covered by combining two type qualifiers ("const noalias"), one of which had just vanished. The best we could do under the circumstances is what is now specified. Many of us think "noalias", with the problems in its specification straightened out, would have been a better solution, but it wasn't politically feasible to reintroduce such a qualifier. P.S. This is my own recollection of the essence of what happened, and you shouldn't take it as any sort of official X3J11 history!
perry@ccssrv.UUCP (Perry Hutchison) (10/19/89)
In article <11320@smoke.BRL.MIL> gwyn@brl.arpa (Doug Gwyn) writes:
+ In essence, a couple of years ago Tom Plum (I think it was) identified
+ the source of committee disputes about the meaning of type qualifiers ...
+ That allowed separating out the "noalias" meaning from "readonly", both
+ of which had been confused together in "const" ... "noalias"
+ was added as a separate type qualifier. To make a long story short,
+ we had to retract "noalias" late in the review process, which left us
^^^^^^^^^^^^^^^^^^^^^^^^^^
+ with the newly resurfaced problem of specifying the library facilities ...
+ The best we could do under the circumstances is what is now specified.
^^^^^^^^^^^^^^^^^^^^^^^
+ Many of us think "noalias", with the problems in its specification
+ straightened out, would have been a better solution, but
+ it wasn't politically feasible to reintroduce such a qualifier.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
In other words, a _technically_ defective hack was put in the standard at
the last minute, to satisfy someone's _political_ agenda.
It sounds to me like the current "proposed standard" deserves to be voted
down and sent back to committee to have this mess (and any other problems
which may have surfaced) cleaned up.
henry@utzoo.uucp (Henry Spencer) (10/19/89)
In article <742@ccssrv.UUCP> perry@ccssrv.UUCP (Perry Hutchison) writes: >+ Many of us think "noalias", with the problems in its specification >+ straightened out, would have been a better solution, but >+ it wasn't politically feasible to reintroduce such a qualifier. > ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ > >In other words, a _technically_ defective hack was put in the standard at >the last minute, to satisfy someone's _political_ agenda. Well, yes, but not in the way you meant it. A technically defective hack ("noalias") was indeed put in the standard at the last minute (second public review) to satisfy someone's (the number crunchers') semi-political agenda. There was, quite legitimately and properly, a storm of protest from almost everyone else in sight, including Dennis Ritchie. Partly because the hack really was technically defective, as written. So it got hastily taken out again. Something along those lines might indeed have been the best solution, but it was introduced far too late and without adequate prior thought. If I am not mistaken, it was also an invention of the committee rather than proven prior art, which is a big no-no for a standards committee. If the current situation is a botch, which I don't necessarily admit (I'm of the anti-noalias faction), it is (a) one of the committee's own making, and (b) too late to fix. -- A bit of tolerance is worth a | Henry Spencer at U of Toronto Zoology megabyte of flaming. | uunet!attcan!utzoo!henry henry@zoo.toronto.edu
maart@cs.vu.nl (Maarten Litmaath) (10/20/89)
gwyn@smoke.BRL.MIL (Doug Gwyn) writes:
\... As it is, we were changing the wording about this stuff up to
\practically the last minute before printing the final draft, [...]
Wouldn't it have been beautiful, if X3J11 had been given another year...
\Given your propensity for grumbling about the standardization process,
\I'm not sure I should.
Thanks you did it anyway!
Of course I've been wrong sometimes, but there ARE things which were
handled rather in a rush... (You said so yourself.)
--
A symbolic link is a POINTER to a file, | Maarten Litmaath @ VU Amsterdam:
a hard link is the file system's GOTO. | maart@cs.vu.nl, mcsun!botter!maart
gwyn@smoke.BRL.MIL (Doug Gwyn) (10/20/89)
In article <742@ccssrv.UUCP> perry@ccssrv.UUCP (Perry Hutchison) writes: >It sounds to me like the current "proposed standard" deserves to be voted >down and sent back to committee to have this mess (and any other problems >which may have surfaced) cleaned up. Fortunately for the C programming community, numerous people in a much better position than you to make such a judgement have decided that the currently proposed Standard is technically good enough as it now stands. I'm sorry if you think I described a "mess". Perhaps that's what I get for trying to give an honest but brief description of the relevant history. In fact there IS NO MESS in this regard in the proposed Standard. There IS a void that has been left unfilled, but its effect is relatively minor. The two practical consequences will be: Occasionally, interface designers will have to decide whether or not to require a type cast to be used, as in the execve() example that started this thread. Certain types of optimization will require more complicated global flow analysis, or use of nonstandard extensions.
mcdonald@aries.uiuc.edu (Doug McDonald) (10/21/89)
> >Well, yes, but not in the way you meant it. A technically defective hack >("noalias") was indeed put in the standard at the last minute (second public >review) to satisfy someone's (the number crunchers') semi-political agenda. >There was, quite legitimately and properly, a storm of protest from almost >everyone else in sight, including Dennis Ritchie. Partly because the hack >really was technically defective, as written. So it got hastily taken out >again. Something along those lines might indeed have been the best solution, >but it was introduced far too late and without adequate prior thought. If >I am not mistaken, it was also an invention of the committee rather than >proven prior art, which is a big no-no for a standards committee. > Apparently X3 now has been taken by serious second thoughts about their subcommittees (i.e. J3) inventing new languages, as they have decided to contine the old one (Fortran77). The flamage in comp.std.c (and the .lang group) is as nothing, compared to the number of participants, as is the amount in comp.lang.fortran - in which X3J3 has invented a language so wholly new that X3 is having to give it a new name. Thankfully, X3J11 resisted the temptation. On the other hand, it looks like X3J3 is going to botch the technical requirements of the public review sufficiently badly that there will have to be another one! (They are not going to get out their replies to the last one - two years ago - in time!). Doug McDonald
gwyn@smoke.BRL.MIL (Doug Gwyn) (10/22/89)
In article <3753@pinas.cs.vu.nl> maart@cs.vu.nl (Maarten Litmaath) writes: >Wouldn't it have been beautiful, if X3J11 had been given another year... >Of course I've been wrong sometimes, but there ARE things which were >handled rather in a rush... (You said so yourself.) Yeah, life sometimes requires compromise. There was NO WAY that the C community was going to wait much longer; the commercial importance of C had increased tremendously since the time that the standardization effort began. For the record, I was the only X3J11 member to vote "NO" to sending the amended draft proposed Standard out for the third public review, which was expected to result in no further substantive changes to the proposed Standard, because I didn't think there had been enough time to adequately evaluate all the second-round comments. Yet not even I objected to sending along the final draft to X3 as the proposed ANSI (and, coincidentally, ISO) standard, because I agreed that in its current form it is certainly "good enough". In fact it seems better overall to me than any other similar standard I've seen, and I've seen several. It does not serve the best interests of the C community to keep tweaking on the document forever, seeking after the inattainable goal of absolute perfection. If the Standard meets the needs that motivated the standardization effort, then that's good enough. You think the "short" amount of time spent by X3J11 (what was it, 7 years?) was insufficient, you should look at IEEE 1003. Due partly to unwarranted pressure from NBS (now NIST), IEEE Std 1003.1 was pushed out the door with major changes appearing only in the middle of supplemental mailings after the final letter ballot. Now THERE's a case of rushing through the standardization process.
andy@cit-vax.Caltech.Edu (Andy Fyfe) (10/27/89)
When I look at a prototype of the form extern char *strcpy(char *to, const char *from); I'd like to think of it as not only telling me what the parameter types are, but also telling me that strcpy will not change the characters pointed at through "from". I had previously brought up the example of "execv", and Doug Gwyn suggested: >Personally I would opt for > extern int execv( const char *path, char *const *args ); >as the most restrictive declaration that doesn't cause user hassles. I would rather see the fully constrained extern int execv( const char *path, const char *const *args ); With just extern int execv( const char *path, char *const *args ); I would wonder about the "safety" of passing a "const char **" as the second argument. Explicitly casting the "const char **" to a "char **" would work, but only with something external (or a comment or something) to tell me it's "safe". Yet to use the fully constrained version causes compiler warnings in the typical case of passing a "char **", unless a cast is present. Such a cast strikes me as a bit incongruous, as what's allowed with the pointer after the cast was allowed to begin with. I can be somewhat pedantic. I assume that if a compiler puts a literal string constant in read-only memory (as Gnu CC does, for example), it should give that string the type "const char *" when type checking (and Gnu CC will do this, with a -W... option). Getting something that I think really should have the type "const char **" is easy (any array of pointers to literal strings), and since a write into such a string when using a compiler like Gnu CC can cause a run-time memory fault, I'd just as soon have the compiler doing some extra checking for me (I'm a bit too error-prone to do it myself). Thanks to those who've responded. Andy Fyfe andy@csvax.caltech.edu wjafyfe@caltech.bitnet andy@cit-vax.UUCP (...!ames!elroy!cit-vax!andy)
rpjday@ccu.umanitoba.ca (08/01/90)
I am trying to decode the ANSI draft in front of me, and am having trouble interpreting the section on the const qualifier. Rather than type out the entire example, I'll just refer to the page and line numbers in the Feb 14, 1990 draft. Section 3.5.3, line 26, we have, "For two qualified types to be compatible, both shall have the identically qualified version of a compatible type..." Does "compatible" mean assignment compatible? That is, I am not allowed to do const int i = 10; int j; j = i; ??? even though this has no effectg on the value of j? This is just the beginning. At the top of the next page, in the segment of code, line 7 shows an assignment of a const-qualified structure to a non-const-qualified structure. But based on the previous definition, should this work? The comment suggests it should. Clarification, please? Finally, line 12 of 3.5.3, "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 would one do this anyway? Maybe as follows? const int j = 10 ; int i ; *(&i + 1) = 20 ; If i and j are allocated in the standard order on the stack, this assignment would affect the value of j. Is this what this statement refers to ? Is there another example? Thanks for the help. R. Day U of Manitoba
gwyn@smoke.BRL.MIL (Doug Gwyn) (08/01/90)
In article <1990Aug1.005200.21645@ccu.umanitoba.ca> rpjday@ccu.umanitoba.ca writes:
- Section 3.5.3, line 26, we have, "For two qualified types to be
-compatible, both shall have the identically qualified version of a
-compatible type..." Does "compatible" mean assignment compatible?
No, "compatible type" is a technical term defined in section 3.1.2.6.
-That is, I am not allowed to do
- const int i = 10;
- int j;
- j = i; ???
-even though this has no effectg on the value of j?
I don't understand your example. Certainly it is allowed, and the
value of j is definitely affected (it is set to 10).
- This is just the beginning. At the top of the next page, in the
-segment of code, line 7 shows an assignment of a const-qualified
-structure to a non-const-qualified structure. But based on the
-previous definition, should this work? The comment suggests it should.
Of course it should work. What argumentation would you offer for it
being disallowed?
You cannot store INTO a const-qualified object; however, you may
pick up its contents!
- Finally, line 12 of 3.5.3, "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 would one
-do this anyway?
const int j = 10;
int *p = (int *)&j;
*p = 20;
- Maybe as follows?
- const int j = 10 ;
- int i ;
- *(&i + 1) = 20 ;
Yuck! That's horrible code, which one has no reason to expect to work.
karl@haddock.ima.isc.com (Karl Heuer) (08/01/90)
In article <1990Aug1.005200.21645@ccu.umanitoba.ca> rpjday@ccu.umanitoba.ca writes: >Section 3.5.3, line 26, we have, "For two qualified types to be >compatible, both shall have the identically qualified version of a >compatible type..." Does "compatible" mean assignment compatible? No, it means that they really are the exact same type, or could be after completion. For example, "void (*f[3])()" and "void (*f[])(double)" are compatible types, because each can be completed to "void (*f[3])(double)" (known as the _composite type_). See 3.1.2.6. >[deleted stuff that was based on the wrong assumption] > Finally, line 12 of 3.5.3, "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 would one >do this anyway? You can remove const-qualification by using an explicit cast. int const i = 10; int *p = (int *)&i; *p = 20; The cast itself is legal (though certainly questionable). The assignment to `*p' is legal syntactically but not semantically. Another example is extern char const buf[]; char *p = strchr(buf, c); where the cast is hidden inside the implementation of strchr(). Logically, the return type of strchr() is the same as its first actual argument (either `char const *' or `char *'), but C has no way to declare that. A similar problem exists with functions like `memcpy()'. Caveat emptor. Karl W. Z. Heuer (karl@kelp.ima.isc.com or ima!kelp!karl), The Walking Lint
rpjday@ccu.umanitoba.ca (08/02/90)
In article <1990Aug1.005200.21645@ccu.umanitoba.ca> I write: > Section 3.5.3, line 26, we have, "For two qualified types to be >compatible, both shall have the identically qualified version of a >compatible type..." Does "compatible" mean assignment compatible? >That is, I am not allowed to do > > const int i = 10; > int j; > j = i; ??? > >even though this has no effectg on the value of j? Of course, what I meant was "no effect on the value of i". Sigh.
rpjday@ccu.umanitoba.ca (08/02/90)
OK, now that I managed to make a total fool of myself with a well-placed typo, let me try to prove that I am not a complete cement-head. In article <13462@smoke.BRL.MIL> gwyn@smoke.BRL.MIL (Doug Gwyn) writes: >In article <1990Aug1.005200.21645@ccu.umanitoba.ca> rpjday@ccu.umanitoba.ca writes: >- Section 3.5.3, line 26, we have, "For two qualified types to be >-compatible, both shall have the identically qualified version of a >-compatible type..." Does "compatible" mean assignment compatible? > >No, "compatible type" is a technical term defined in section 3.1.2.6. All right, I can handle that. >-That is, I am not allowed to do >- const int i = 10; >- int j; >- j = i; ??? >-even though this has no effectg on the value of j? > >I don't understand your example. Certainly it is allowed, and the >value of j is definitely affected (it is set to 10). Uh, my fault, that should have been "no effect on the value of i". I realized that, logically, there can be no harm in the above code snippet, and maybe my confusion is now obvious when I thought "compatible" meant assignment compatible since, according to the draft, the types "int" and "const int" are not technically compatible since they are not identically qualified. Because of that, I concluded that the above code, harmless as it was, was somehow illegal. >- This is just the beginning. At the top of the next page, in the >-segment of code, line 7 shows an assignment of a const-qualified >-structure to a non-const-qualified structure. But based on the >-previous definition, should this work? The comment suggests it should. > >Of course it should work. What argumentation would you offer for it >being disallowed? See above. My misunderstanding. >- Finally, line 12 of 3.5.3, "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 would one >-do this anyway? > > const int j = 10; > int *p = (int *)&j; > *p = 20; > >- Maybe as follows? >- const int j = 10 ; >- int i ; >- *(&i + 1) = 20 ; > >Yuck! That's horrible code, which one has no reason to expect to work. I wasn't out to win any beauty contests, I just dragged this one out of the gutter because, in some places, it would do what I wanted -- modify the value of j. I still, however, have one point of confusion. On. p. 66, we have (among other things) const struct s { int mem ; } cs = { 1 } ; struct s ncs ; int *pi; pi = &cs.mem; /* violates type constraints for = */ ncs = cs ; /* valid */ Now I can appreciate that the assignment to "pi" should not be allowed, but PRECISELY which rule makes this illegal? Is the const qualification considered part of the "type" so that these are technically different types and must be cast? If this is true, I would think that the next assignment should be illegal for the same reason (yes, I know it's totally harmless, but "ncs" and "cs" have different qualification, so does that make them different types?) In short, the first assignment should obviously fail, and the second should obviously work, but what is the rule that makes the first illegal and the second valid? Thanks for the help (and the patience). R. Day U of Manitoba
rpjday@ccu.umanitoba.ca (08/02/90)
In article <1990Aug2.011735.1143@ccu.umanitoba.ca> rpjday@ccu.umanitoba.ca writes: >OK, now that I managed to make a total fool of myself with a well-placed >typo, let me try to prove that I am not a complete cement-head. . . . Never mind, it has been pointed out to me that the relevant section deals with lvalues and function designators (3.2.2.1). NOW it makes sense. thanks to all who mailed. R. Day U of Manitoba
gwyn@smoke.BRL.MIL (Doug Gwyn) (08/05/90)
In article <1990Aug2.011735.1143@ccu.umanitoba.ca> rpjday@ccu.umanitoba.ca writes: > const struct s { int mem ; } cs = { 1 } ; > struct s ncs ; > int *pi; > pi = &cs.mem; /* violates type constraints for = */ >Now I can appreciate that the assignment to "pi" should not be allowed, >but PRECISELY which rule makes this illegal? Supposedly the constraint in 3.3.16.1 that requires the thing pointed to by the LHS to have all the qualifiers of the thing pointed to by the RHS is violated. For this to work, the "mem" member of the struct "cs" must also be considered to be const-qualified, which is reasonable but hard to deduce from the wording in the standard. Basically, all parts of an object declared with a type qualifier are also so qualified. > ncs = cs ; /* valid */ >I know it's totally harmless, but "ncs" and "cs" have different >qualification, so does that make them different types?) No constraint is violated by this assignment.
scjones@thor.UUCP (Larry Jones) (08/05/90)
In article <13475@smoke.BRL.MIL>, gwyn@smoke.BRL.MIL (Doug Gwyn) writes: > Supposedly the constraint in 3.3.16.1 that requires the thing pointed to > by the LHS to have all the qualifiers of the thing pointed to by the RHS > is violated. For this to work, the "mem" member of the struct "cs" must > also be considered to be const-qualified, which is reasonable but hard > to deduce from the wording in the standard. Basically, all parts of an > object declared with a type qualifier are also so qualified. It seems to me that there used to be a statement in the standard that said basically that if an aggregate is qualified, all of the members are effectively qualified, and if a member of an aggregate is qualified, then the aggregate is effectively qualified. Now I don't seem to be able to find it. Am I imagining things again, did I miss it, or did we remove it? ---- Larry Jones UUCP: uunet!sdrc!thor!scjones SDRC scjones@thor.UUCP 2000 Eastman Dr. BIX: ltl Milford, OH 45150-2789 AT&T: (513) 576-2070 Girls are like slugs -- they probably serve some purpose, but it's hard to imagine what. -- Calvin
diamond@tkou02.enet.dec.com (diamond@tkovoa) (08/06/90)
In article <127@thor.UUCP> scjones@thor.UUCP (Larry Jones) writes: >It seems to me that there used to be a statement in the standard that >said basically that if an aggregate is qualified, all of the members >are effectively qualified, and if a member of an aggregate is >qualified, then the aggregate is effectively qualified. Now I don't >seem to be able to find it. Am I imagining things again, did I miss >it, or did we remove it? In section 3.5.3, the Semantics almost say that for arrays. (However, if a qualifier is "inherited" along the "wrong" path via a typedef, then the standard does not define the result.) The Semantics say nothing for structs. However, the Examples are a lot stronger. The Examples state that certain things are illegal even though the rules say nothing about them. I guess it's time for another interpretation. (At least this time, the Examples don't contradict the rules.) -- Norman Diamond, Nihon DEC diamond@tkou02.enet.dec.com This is me speaking. If you want to hear the company speak, you need DECtalk.
gwyn@smoke.BRL.MIL (Doug Gwyn) (08/06/90)
In article <127@thor.UUCP> scjones@thor.UUCP (Larry Jones) writes: >In article <13475@smoke.BRL.MIL>, gwyn@smoke.BRL.MIL (Doug Gwyn) writes: >It seems to me that there used to be a statement in the standard that >said basically that if an aggregate is qualified, all of the members >are effectively qualified, and if a member of an aggregate is >qualified, then the aggregate is effectively qualified. Now I don't >seem to be able to find it. Am I imagining things again, did I miss >it, or did we remove it? Yeah, I was looking for that too, and I didn't find it either. The only thing I found that was at all relevant said that a qualifier in an array declaration actually qualifies the elements of the array, not the array itself. However, that's not what we're looking for.. I have no idea what might have happened to the part<->whole clause.
walter@hpcllca.HP.COM (Walter Murray) (08/10/90)
Larry Jones: >It seems to me that there used to be a statement in the standard that >said basically that if an aggregate is qualified, all of the members >are effectively qualified, and if a member of an aggregate is >qualified, then the aggregate is effectively qualified. Now I don't >seem to be able to find it. Am I imagining things again, did I miss >it, or did we remove it? Doug Gwyn: >Yeah, I was looking for that too, and I didn't find it either. >The only thing I found that was at all relevant said that a qualifier >in an array declaration actually qualifies the elements of the array, >not the array itself. However, that's not what we're looking for.. >I have no idea what might have happened to the part<->whole clause. If you access a member of a struct or union that has qualified type, using the . operator or the -> operator, the qualifiers of the struct or union apply to the member. Section 3.3.2.3. Going the other way, a struct or union can't be a modifiable lvalue if it has a member with a const-qualified type. Section 3.2.2.1. Taken with the semantics rules in 3.5.3, these seem to provide what we are looking for. Walter Murray ----------