Topic: Is int const myNull 0 a null pointer constant?
Author: gdr@cs.tamu.edu (Gabriel Dos Reis)
Date: Wed, 15 Sep 2004 17:35:56 GMT Raw View
kanze@gabi-soft.fr writes:
| Gabriel Dos Reis <gdr@cs.tamu.edu> wrote in message
| news:<m3n00767s1.fsf@merlin.cs.tamu.edu>...
|=20
| [...]
| > | The standard says "An integral constant-expression can only involve
| > | [...] const variables or static data members of integral or
| > | enumeration types initialized with constant expressions, [...]".
| > | There's not the slightest requirement that the declaration
| > | containing the initialization be visible (although I'm sure we all
| > | agree The standard says "An integral constant-expression can only
| > | involve [...] const variables or static data members of integral or
| > | enumeration types initialized with constant expressions, [...]".
| > | There's not the slightest requirement that the declaration
| > | containing the initialization be visible (although I'm sure we all
| > | agree that this was the intent).
|=20
| > You made that reasoning once before and I suggested you read clause 3.
| > Where do you find initializers? In declarations. How are
| > declarations found? through name lookup. How name lookup works?
|=20
| Woah.
hoaw.
| =A75.19 doesn't say anything about finding initializers, or that
| the initializers have to be visible.
=A75.19 is the "further expression processing" which can take place only
*after* name lookup has collected the visible declarations which
dictates how the variable has to be interpreted.
3.4/1
[...] Name lookup associates the use of a name with a declaration
(3.1) of that name. Name lookup shall find an unambiguous
declaration for the name (see 10.2). Name lookup may associate more
than one declaration with a name if it finds the name to be a
function name; the declarations are said to form a set of overloaded
functions (13.1). Overload resolution (13.3) takes place after name
lookup has succeeded. The access rules (clause 11) are considered
only once name lookup and function overload resolution (if
applicable) have succeeded. Only after name lookup, function
overload resolution (if applicable) and access checking have
succeeded are the attributes introduced by the name s declaration
used further in expression processing (clause 5).=20
| If I write:
| extern int const x ;
| , the const variable here has an initializer.
No, it does not. That statement is just plain wrong.
The standard is very clear. Only refusal to consider how the standard
text says names should be interepeted makes it appear as there is a
problem. In reality, there is none.
--=20
Gabriel Dos Reis
gdr@cs.tamu.edu
Texas A&M University -- Computer Science Department
301, Bright Building -- College Station, TX 77843-3112
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: gdr@cs.tamu.edu (Gabriel Dos Reis)
Date: Wed, 15 Sep 2004 20:45:59 GMT Raw View
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D MODERATOR'S COMMENT:=20
This thread is moving away from discussing the standard and towards I-sa=
id-you-said. Please consider taking it to email. Thanks.
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D END OF MODERATOR'S COMMENT
kanze@gabi-soft.fr writes:
| Gabriel Dos Reis <gdr@cs.tamu.edu> wrote in message
| news:<m3sm9z680z.fsf@merlin.cs.tamu.edu>...
| > kanze@gabi-soft.fr writes:
|=20
| > | gdr@cs.tamu.edu (Gabriel Dos Reis) wrote in message
| > | news:<m3oekuowu9.fsf@merlin.cs.tamu.edu>...
| > | > johnchx2@yahoo.com (johnchx) writes:
| > | > | gdr@cs.tamu.edu (Gabriel Dos Reis) wrote in message
| > | > | news:<m37jrkbsn6.fsf@merlin.cs.tamu.edu>...
| > | > | > johnchx2@yahoo.com (johnchx) writes:
|=20
| > | > | > [...]
|=20
| > | > | > | I think that's correct, but it may be a defect in the
| > | > | > | standard. Consider:
|=20
| > | > | > | extern const int i; // defined in another translation =
unit
|=20
| > | > | > | int main () {
| > | > | > | void* p =3D i;
| > | > | > | }
|=20
| > | > | > | The validity of the assignment depends on the availability
| > | > | > | of the conversion from const int to pointer type, which in
| > | > | > | turn depends on the *value* of i.
|=20
| > | > | > The validity of the assignment depends on the presence of the
| > | > | > initializer.
|=20
| > | > | No, it also depends on the *value* of the initializer. That
| > | > | seems to me to be by far the more interesting wrinkle here.
|=20
| > | > Yes, but the point is that you get that information from the
| > | > declarations (given by name lookup), hence the initializer. Get
| > | > things in order, you'll see the light :-)
|=20
| > | You're looking at it as an implementer.
|=20
| > No. =20
|=20
| > You're not in my mind and you have no clue about how I'm looking at
| > it. As a matter of fact, I'm looking at it as if I were a user and
| > have no knowledge about how compilers implement C++.
|=20
| But a user who is used to how compilers work in general. Maybe not
That does not change how I'm looking at this issue. You simply are
not in my mind and have no way to know how I'm approaching this
issue. You may guess, but in this case the guess is wrong.
| formally, but from having used them. You are still using additional
| knowledge which is not explicitly stated, and cannot be deducted from
| the English in the standard.
No, I'm not using extra knowledge, I've already pointed you to the
relevant part of the standard and quoted the standard text in another
messsage. Those are what I'm using.
| > | The standard says that the expression uses a variable.
|=20
| > Great!
|=20
| > | An object.
|=20
| > Using a variable is not the same as using an object. An object is a
| > region of storage. A variable is an association of a name and a
| > variable.
|=20
| A variable is an association of a name and a variable? That sounds a
| bit recursive to me. I'm sure there's a typo in it somewhere. But I'm
Sure, my editor found that the second is "object", i.e.
A variable is an association of a name and an object.
| not sure where; I would have said that a variable is an association of =
a
| name and an object (or an object with a type).=20
you would have said right; which is also what I meant.
| But if that is what you
| meant, then you would be agreeing with me, that a variable is an object.
No, just like a variable is not a name. You might consider an abuse
of language for short-circuit purpose, but technically, no, a variable
is not an object.
| > | And thus, which can be declared without being defined,
|=20
| > You don't declare objects; you declare names. =20
|=20
| And a name refers to something.
|=20
| > Names are interpreted according to their declarations (and attributes
| > found therein). Declarations are found by name lookup.
|=20
| Quite. So if I look up the name, and that name declares an object, and
| that object is const, and has an integral type, and is initialized
| itself with an integral constant expression, then we can use it in an
| integral constant expression.
Notice that the result of name lookup is a declaration set.
If look up the name and find declarations for that name that specify
* the const qualifier, and
* an integral type, and
* an initializer that is itself an integral constant expression
then you can use the variable in contexts where an integral constant
expression is required. If you miss any of the three requiremnts,
then the declarations do not qualify for the integral constant
expression interepretation.
| You don't initialize names. You initialize objects. Saying that a nam=
e
| is initialized to ... doesn't make sense (at least to me). Saying that
| the object declared by the name is initialized does, but then, we are
| back to talking about objects.
No. =20
A name is introduced by a declaration. A declaration specifies how a
name should be interepreted. If you use a name "x", that "x" should
have a declaration. The validity of its use depends on the attributes
found in its declarations. In the case at hand, it depends on whether
the declaration has an initializer and specifies a const-qualified
integral type.
| > | and whose actual initializer might only be specified in another
| > | compilation unit.
|=20
| > So, if it is not there, name lookup cannot find it.
|=20
| Name lookup never finds an initializer.
Initializers are found in declarations. Declarations are found by
name lookup.
| If finds a name, which is part
| of a declaration.
The result of name lookup is a declaration set, not a name. So, when
you lookup the name, you find the entire set of declarations in effect
at the point of use. If none of them meets the integral constant
expression interpretation requirements, it cannot not be ineterpreted
as such. There is no if, no but.
| In this case, the declaration declares the existance
| of a variable. And object. Which may or may not be initialized, but w=
e
| can't necessarily know that from the declaration.
Then you cannot use the name in a context where an integral constant
expression is required.=20
[...]
| > Therefore, the interpretation of the name at point of use cannot infe=
r
| > "constant expression"ness. QED.
|=20
| The interpretation of the name is never sufficient to infer "constant
| expression"ness. You have to determine what the name refers to. If it
| refers to a const variable or a static data member of integral or
| enumeration type, it might be a constant expression. If that variable
| (the object) is initialized by an integral constant-expression, then it
| can be used itself in an integral constant-expression.
A variable is not an object. There is an abuse of language to say
variable when the associated object is meant, but technically a
variable is an association of a name and an object.=20
If you do name lookup and you find that the declarations that
introduced the variable also specify an initializer (that happens to
hae the right form) then you can use that variable as an integral
constant expression. Not otherwise.
| According to what is written in the standard, anyway. We both know tha=
t
| in reality, it can't be unless the initialization is also visible to th=
e
| compiler at that point.
I know what the reality is and what the standard says; and in this
case they match. After this discussion, I cannot claim you
also know the reality. But if you claim you know it, then why do you
continue in the direction you're heading? That is a guenuine question.
| [...]
| > And I really meant clause 3, because I feel johnchx2 (or you) would
| > greatly improve your understanding of the issue through reading it in
| > its entirety -- even if you might feel bored.
|=20
| Well, I will admit that you had a good suggestion there. Right off the
| bat, paragraph 4: "a variable is introduced by the declaration of an
| object. The variable's name denotes the object." So a declaration is
| sufficient to have a variable; we don't need the definition. And the
Yes, and further down the standard says when a declaration is a definitio=
n.
| variable's name denotes the object; i.e. when I use the name of the
| variable, I am refering to the object. Still, it would seem that we ar=
e
| dealing with a name,object pair, and not just the object. (I presume
| that that is the point you are trying to make.)
Yes, when you're using a variable you're using manipulating a pair:
ots name and the object it denotes. In many situations, there is a
decay of the variable to the underlying object, but you should be
distinguishing a variable from an object. Especially, when quibbling
on csc++ :-)
| Further on (=A73.5), I read that "A name is said to have linkagne when =
it
| might denote the same object, reference, function, type, template,
| namespace or value as a name introduced by a declaration in aother
| scope." If I understand your point correctly, each "declaration" is a
| different "variable", even if it refers to the same object, because the
unless it is a redeclaration.
3.1/1
A declaration (clause 7) introduces names into a translation unit or
redeclares names introduced by previous declarations. A declaration
specifies the interpretation and attributes of these names.=20
| names are "different".
No.
| So we have to find the initialization in the
| "variable", that is, the declaration, which introduced the name.
Yes.
| If that is what you are trying to say, then I think I see what you are
You have half right and half wrong in what I'm saying :-)
| getting at. I'm still not convinced, however. I think that this
| interpretation introduces more problems than it solves. For example:
|=20
| extern int const i ;
| int const i =3D 5 ;
|=20
| We both agree, I'm sure, that that is fully legal C++ (supposing it
| occurs at namespace scope, of course). But there are two declarations.
They are two declarations that happen to declare the same name. The
first is not a definition, the second is. The second redeclares "i".
Both declare the same variable.
| Are they the same variable, or do I have two variables.=20
You have one variable.
| And supposing I
| have two variables (which would seem to be the consequence of what you
| are saying),
no, that would be a consequence of what *you* labelled as I'm
saying, but I've not been saying anything that led to that conclusion.
| and that they refer to the same object (which is, I hope,
| the case), then which "variable" will be found during name lookup?
You have one variable, two declarations. The first declares the
variable (without being a definition) and the second redeclares the
same variable and is a definition.
| And an interesting question. Is the following legal?
|=20
| extern int const i ;
| char a[ i ] ;
| int const i =3D 5 ;
No. Because of the very same issue. At the definition point of "a",
the only declaration of "i" in effect is the one that does not contain
an initializer. Therefore it use in that context is invalid.
| I'll admit that I'm even more confused than before. If I have two
| variables, then I dont find the one with the initialization on name
| lookup.
You've confused yourself :-) You have one variable, two declarations
and you do know which contains the initializer.
| If I have only one, of course, it has the required initializer.
|=20
| Now let's try:
|=20
| int const i =3D 5 ;
| void f()
| {
| extern int const i ;
| char a[ i ] ;
| }
|=20
| Legal? How many variables?
You have only one variable named "i", but with two declarations. =20
Inside f(), you look up "i" and find the declaration=20
extern int const i ;
Now, the question is whether you stop there -- because you've found a
name. However, there is a specific wording in the standard text
saying under which circumstances some attributes in different declaration=
s
should be merged even when they do not appear at the same scope.
3.5/6
The name of a function declared in block scope, and the name of an
object declared by a block scope extern declaration, have
linkage. If there is a visible declaration of an entity with linkage
having the same name and type, ignoring entities declared outside
the innermost enclosing namespace scope, the block scope declaration
declares that same entity and receives the linkage of the previous
declaration. If there is more than one such matching entity, the
program is ill-formed. Otherwise, if no matching entity is found,
the block scope entity receives external linkage.=20
So clearly, the standard mandates that one goes and find out previous
declarations for the name "i". It also says that the declaration for "i"
inside the definition of f() declares the same entity, i.e. the same
variable as the declaration of "i" at global scope. Furthermore, it
requires that linkages be combined from outer declarations in specific
ways. What is less clear there is whether other attributes
(e.g. initializers) are to be considered too.
g++ and Comeau online seem to think so, Sun CC seems to think the opposit=
e.
| My compilers disagree. (Sun CC rejects it, g++ accepts it.) So I gues=
s
| I'm not the only one confused. Historically, I would have thought that
| the intention was that it be legal, but now, I'm really not sure. (If
| my original interpretation of the end of clause 5 is correct, then the
| answer is obvious, but we both agree that regardless of what it actuall=
y
| says, that interpretation cannot be what was meant.)
|=20
| Given that, how is this different from:
|=20
| struct S
| {
| static int const i ;
| } ;
|=20
| int const S::i =3D 5 ;
| char a[ i ] ;
|=20
| I have always been convinced that this was legal, although admittedly
| because some early compiler accepted it. This time, Sun CC also accept=
s
| it. Although as I say, I don't really see how it is different from the
| preceding case.
Why should it not be valid? Two are two declarations, one which is
not a definition, and the other which happens to be a definition and
specifies an initializer that has the right form. So S::i can be
interpreted as a constant integral expression.
--=20
Gabriel Dos Reis
gdr@cs.tamu.edu
Texas A&M University -- Computer Science Department
301, Bright Building -- College Station, TX 77843-3112
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: kanze@gabi-soft.fr
Date: Wed, 8 Sep 2004 18:06:33 GMT Raw View
Gabriel Dos Reis <gdr@cs.tamu.edu> wrote in message
news:<m3hdqf6653.fsf@merlin.cs.tamu.edu>...
> kanze@gabi-soft.fr writes:
> [...]
> | Finally, of course, it indicates that g++ did make the change
> | intentionally, because of the word "rvalue" in the definition of a
> | null pointer constant. (And probably knowing, or suspecting, that
> | it would break some poor users code, and gloating over the fact.)
> Why do you keep saying that GCC implementors gave the error
> intentionally?
Because someone said that when they reported it as a bug, they were told
that this was intended behavior.
> As far as I can determine, I cannot name any patch that went into GCC
> intentionally to break
> const int null = 0;
> int* p = null;
> Can you name any such patch?
> If you cannot, I think you should offer a public apology to g++
> developers for having implied the above.
It was meant ironically. G++ isn't the only implementor with the
problem. You make the compiler conform, and you break users code. In
general, at least.
Gloating is a loaded word, and I probably shouldn't have used it without
a smiley. But some compiler writers to make more effort than others to
provide a migration path, even when the original code wasn't ever
formally legal. (Sun CC, for example, still differs destruction of
temporaries until the end of the block, to avoid breaking code which was
never legal.)
In this case, I can hardly imagine anyone adding this kind of check to
the code without something of a chip on his shoulder. Even if it were
formally illegal, I would certainly make sure with the committee that
this was the intent, and not an error in the standard (or my
misinterpretation of the standard).
If it was just an accident, and g++ is going to correct it, then so much
the better. If any particular developer felt attacted by my phrase,
then I apologize to him -- despite the context, the actual phrase was
meant much more generally. And, to a very large degree, ironically --
implementors trying to conform to the standard do sometimes have to
break user code. I don't think many really "gloat" over the fact, but
they do break code, and they do so intentionally.
> [ And in case you'll wonder, I'm not taking this issue personaly but I
> feel that your assertion based on no evidence is just a plain insult
> to GCC developers. ]
Well, it is unfortunate that it came in a phrase which spoke explicitly
about g++. G++ being the most advanced compiler I use, it is also the
compiler that I curse most often, but I think that the problem is
general to all implementors.
> Here are facts.
> Last July, while having (again!) the null debate on fr.comp.lang.c,
> Bjarne sent me an email indicating that recent versions of GCC reject
> the above. My instinct reaction (and reply) was along the line "I
> don't think so." Just after the reply, I tested with the versions of
> GCC I had at hand and found that, indeed, GCC was rejecting the code.
> I sent Bjarne another mail telling him that I did my homework and
> found that GCC was misbehaving, but that was NOT intentional. I
> filled a proper PR, which got quickly fixed.
But apparently, other's had filed bug reports before, and were told that
it was the correct behavior.
If you say that the modification was accidental, as a result of some
other correction, or the implementation of some other feature, I've
nothing to say. If, on the other hand, the modification was
intentional, by someone who interpreted the one particular phrase in
4.10/1 to actually mean what it says, and implemented the restriction
without at least asking the committee if it really meant to user code,
then IMHO, he was acting irresponsibly.
> As a matter of fact:
> * I was unaware that the issue was reported to Core; (that would
> have saved me from sending a message about something I thought
> obviously wrong with GCC).
> * I did not remember that the issue was already reported to GCC and
> was erroneously closed; otherwise I would have just reopened it
> instead of filling a PR.
> * no fellow g++ implementers ever objected to the issue.
I wouldn't argue with Stroustrup either:-).
> The thing as I see it -- and this is no rewriting of history -- is
> that the GCC code for conversions got rewritten many times, in the
> process of correcting some obscure bugs and in the hope of making it
> less convoluted and many bugs found their ways in. I believe the
> majority of them got eventually fixed.
That is, regretfully, an all too common history. Not just for g++.
> I sincerelly don't recall any debate on the GCC list with g++
> implementors where they decided that they should reject the above code
> and implemented that decision. GCC mailing lists are open, archived
> and searchable. Feel free to bring in evidence.
I don't think that there was every any debate. I do think it possible
that someone "fixed" it in the process of fixing other things, and
slipped it in that way. While I doubt that there was any intentional
deception, I know from experience that when you are fixing 30 different
things, it's easy to forget to mention one when you check something in.
Anyway, the important thing is that it is to be fixed.
An even more important thing, IMHO, would be to get that word "rvalue"
out of there where it doesn't belong, in the standard.
And if we are going to talk about history, I'd be curious why we got
such a convoluted definition for null pointer constant anyway. As we
both know, the original null pointer constant was just 0. Plain,
ordinary, you can't get any simpler than that 0. Of course, 0 doesn't
work for C, once you start passing null pointers to functions which
don't have prototypes (which was all of the functions in C, back then).
So in C, a number of different definitions sprung up, and programmers
got used to using only NULL, and counting on the implementation to
define it to something that did work. (If null pointers didn't have all
bits 0, then the only thing that did work was ((char*)0). And if
different data pointers had different sizes, nothing worked.) The C
standards committee more or less ratified these variations.
At that point, I can see three alternatives for C++:
- 0 works for C++: it ain't broke, so don't fix it. A null pointer in
C++ is 0. Period.
- C compatibility is important -- adopt the C definition, verbatim.
- The whole concept is broken. Fix it correctly. (Roughly, what is
being proposed now. Except that back then, it might have been just
possible to forbid 0 completely. Or deprecated it. But probably
not.)
What we got seems to be an adaptation of the wording of C. Which is
unnecessarily complicated in order to solve a problem that C++ didn't
have. Except that someone apparently tried to "improve" it, and in the
process, messed it up even more.
--
James Kanze GABI Software http://www.gabi-soft.fr
Conseils en informatique orient e objet/
Beratung in objektorientierter Datenverarbeitung
9 place S mard, 78210 St.-Cyr-l' cole, France, +33 (0)1 30 23 00 34
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: kanze@gabi-soft.fr
Date: Thu, 9 Sep 2004 23:04:11 GMT Raw View
Gabriel Dos Reis <gdr@cs.tamu.edu> wrote in message
news:<m3n00767s1.fsf@merlin.cs.tamu.edu>...
[...]
> | The standard says "An integral constant-expression can only involve
> | [...] const variables or static data members of integral or
> | enumeration types initialized with constant expressions, [...]".
> | There's not the slightest requirement that the declaration
> | containing the initialization be visible (although I'm sure we all
> | agree The standard says "An integral constant-expression can only
> | involve [...] const variables or static data members of integral or
> | enumeration types initialized with constant expressions, [...]".
> | There's not the slightest requirement that the declaration
> | containing the initialization be visible (although I'm sure we all
> | agree that this was the intent).
> You made that reasoning once before and I suggested you read clause 3.
> Where do you find initializers? In declarations. How are
> declarations found? through name lookup. How name lookup works?
Woah. 5.19 doesn't say anything about finding initializers, or that
the initializers have to be visible. If I write:
extern int const x ;
, the const variable here has an initializer. It may not be visible,
but that doesn't mean that it doesn't exist. The problem with 5.19 is
that it doesn't say that the initializer has to be visible. Just that
the initializer, where ever it is, must itself be a integral constant
expression.
Name lookup is only relevant for the names in the integral constant
expression itself.
--
James Kanze GABI Software http://www.gabi-soft.fr
Conseils en informatique orient e objet/
Beratung in objektorientierter Datenverarbeitung
9 place S mard, 78210 St.-Cyr-l' cole, France, +33 (0)1 30 23 00 34
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: Gabriel Dos Reis <gdr@cs.tamu.edu>
Date: Fri, 3 Sep 2004 09:26:03 GMT Raw View
kanze@gabi-soft.fr writes:
| gdr@cs.tamu.edu (Gabriel Dos Reis) wrote in message
| news:<m36573q17s.fsf@merlin.cs.tamu.edu>...
| > johnchx2@yahoo.com (johnchx) writes:
|
| > [...]
|
| > | I was actually surprised not to find language in the standard
| > | outlawing this, since "everybody knows" that the value of an
| > | integral constant expression has to be availabe to the compiler at
| > | compile time. And I suspect that it would be easy to drop in a line
| > | or two of standardese to close the loophole. (I also suspect that
| > | I'm just overlooking something, which someone will point me to at
| > | any moment....)
|
| > I suspect you're missing the fact that interpretation of names is
| > based on the set of declarations available at use point.
|
| I suspect that you are basing your argument on what is blatently obvious
| (especially to an implementer) but not in the standard:-).
Actually I base my argument on the standard text and I've given
indication to the relevant parts.
| Now that he
| raised the point, I vaguely seem to remember having brought it up some
| time ago as well.
Yes, at least on fr.comp.lang.c++, and I gave you the answer that is
no defect because the standard says names are interpreted according
to their declarations, and it is only after name lookup is done,
access checking is done, overload resolution (if applicable) is done
that attributes of the names (specified through declarations) are used
in further processing of expressions.
| The standard says "An integral constant-expression
| can only involve [...] const variables or static data members of
| integral or enumeration types initialized with constant expressions,
| [...]". There's not the slightest requirement that the declaration
| containing the initialization be visible (although I'm sure we all agree
| that this was the intent).
You made that reasoning once before and I suggested you read clause 3.
Where do you find initializers? In declarations. How are
declarations found? through name lookup. How name lookup works?
--
Gabriel Dos Reis
gdr@cs.tamu.edu
Texas A&M University -- Computer Science Department
301, Bright Building -- College Station, TX 77843-3112
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: Gabriel Dos Reis <gdr@cs.tamu.edu>
Date: Fri, 3 Sep 2004 09:25:46 GMT Raw View
kanze@gabi-soft.fr writes:
| gdr@cs.tamu.edu (Gabriel Dos Reis) wrote in message
| news:<m3oekuowu9.fsf@merlin.cs.tamu.edu>...
| > johnchx2@yahoo.com (johnchx) writes:
| > | gdr@cs.tamu.edu (Gabriel Dos Reis) wrote in message
| > | news:<m37jrkbsn6.fsf@merlin.cs.tamu.edu>...
| > | > johnchx2@yahoo.com (johnchx) writes:
|
| > | > [...]
|
| > | > | I think that's correct, but it may be a defect in the standard.
| > | > | Consider:
|
| > | > | extern const int i; // defined in another translation unit
|
| > | > | int main () {
| > | > | void* p = i;
| > | > | }
|
| > | > | The validity of the assignment depends on the availability of
| > | > | the conversion from const int to pointer type, which in turn
| > | > | depends on the *value* of i.
|
| > | > The validity of the assignment depends on the presence of the
| > | > initializer.
|
| > | No, it also depends on the *value* of the initializer. That seems
| > | to me to be by far the more interesting wrinkle here.
|
| > Yes, but the point is that you get that information from the
| > declarations (given by name lookup), hence the initializer. Get
| > things in order, you'll see the light :-)
|
| You're looking at it as an implementer.
No.
You're not in my mind and you have no clue about how I'm looking at it.
As a matter of fact, I'm looking at it as if I were a user and have no
knowledge about how compilers implement C++.
| The standard says that the expression uses a variable.
Great!
| An object.
Using a variable is not the same as using an object. An object is a
region of storage. A variable is an association of a name and a
variable.
| And thus, which can be declared without being defined,
You don't declare objects; you declare names.
Names are interpreted according to their declarations (and attributes
found therein). Declarations are found by name lookup.
| and whose actual initializer might only be
| specified in another compilation unit.
So, if it is not there, name lookup cannot find it. Therefore, the
interpretation of the name at point of use cannot infer "constant
expression"ness. QED.
| The actual meaning of the phrase, strictly interpreted, in English, is
| clear.
Wonderful!
| Common sense, of course, tells us that it is not what we want,
| but since when does common sense have anything to do with reading a
| standard.
Wonderful!
| [...]
| > It is hard for me to see whether you're quibbling or being serious.
| > In the latter case, my recommendation would be to read clause 3 of the
| > standard text.
|
| I'm not sure what you mean by clause 3. There is a clause 3 in many of
| the chapters of the standard, and if you mean chapter 3, you'll have to
| be more precise -- chapter 3 is large, and covers a number of issues.
There is one and only one clause 3 in the standard text.
There is no chapter.
1.5/1 says:
Clauses 2 through 16 describe the C++ programming language. That
description includes detailed syntactic specifications in a form
described in 1.6. For convenience, Annex A repeats all such
syntactic specifications.
If you can locate clause 2, then clause 3 is the one coming just after.
And clause 2 is right after clause 1.
And I really meant clause 3, because I feel johnchx2 (or you) would
greatly improve your understanding of the issue through reading it in
its entirety -- even if you might feel bored.
--
Gabriel Dos Reis
gdr@cs.tamu.edu
Texas A&M University -- Computer Science Department
301, Bright Building -- College Station, TX 77843-3112
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: Gabriel Dos Reis <gdr@cs.tamu.edu>
Date: Fri, 3 Sep 2004 17:27:08 GMT Raw View
kanze@gabi-soft.fr writes:
| gdr@cs.tamu.edu (Gabriel Dos Reis) wrote in message
| news:<m3d61cbss4.fsf@merlin.cs.tamu.edu>...
| > llewelly.at@xmission.dot.com (llewelly) writes:
|
| > [...]
|
| > | There was a bugzilla item opened on this bug some time back, and it
| > | was closed as not a bug on the same logic you use:
| > | http://gcc.gnu.org/bugzilla/show_bug.cgi?id=13867
|
| > That was a mistake. See
|
| > http://gcc.gnu.org/bugzilla/show_bug.cgi?id=16489
|
| So the people at g++ either disagree, or have changed their mind:-).
I can only speak for me but I suspect that fellow C++ implementors at
GCC never thought that the code should be rejected :-)
| At any rate, would it be acceptable to consider the word "rvalue" in
| 4.10 as a defect, and have it removed.
I tried to send you an email saying to look at a message (posted
last July) on the C++ core reflector. But the mail returned to me, as
you have decided to use an invalid email address.
| It apparently caused some
| confusion to some of the implementors at g++, at least for a time, and
As I said, the error reported by GCC was *NOT* intentional. It
cripled in as a side effect of (re)writing some code with respect to
conversion.
--
Gabriel Dos Reis
gdr@cs.tamu.edu
Texas A&M University -- Computer Science Department
301, Bright Building -- College Station, TX 77843-3112
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: Gabriel Dos Reis <gdr@cs.tamu.edu>
Date: Fri, 3 Sep 2004 17:32:05 GMT Raw View
kanze@gabi-soft.fr writes:
[...]
| Finally, of course, it indicates that g++ did make the change
| intentionally, because of the word "rvalue" in the definition of a null
| pointer constant. (And probably knowing, or suspecting, that it would
| break some poor users code, and gloating over the fact.)
Why do you keep saying that GCC implementors gave the error intentionally?
As far as I can determine, I cannot name any patch that went into GCC
intentionally to break
const int null = 0;
int* p = null;
Can you name any such patch?
If you cannot, I think you should offer a public apology to g++
developers for having implied the above.
[ And in case you'll wonder, I'm not taking this issue personaly but I
feel that your assertion based on no evidence is just a plain insult
to GCC developers. ]
Here are facts.
Last July, while having (again!) the null debate on fr.comp.lang.c,
Bjarne sent me an email indicating that recent versions of GCC reject
the above. My instinct reaction (and reply) was along the line
"I don't think so." Just after the reply, I tested with the versions of
GCC I had at hand and found that, indeed, GCC was rejecting the code.
I sent Bjarne another mail telling him that I did my homework and
found that GCC was misbehaving, but that was NOT intentional.
I filled a proper PR, which got quickly fixed.
As a matter of fact:
* I was unaware that the issue was reported to Core; (that would
have saved me from sending a message about something I thought
obviously wrong with GCC).
* I did not remember that the issue was already reported to GCC and
was erroneously closed; otherwise I would have just reopened it
instead of filling a PR.
* no fellow g++ implementers ever objected to the issue.
The thing as I see it -- and this is no rewriting of history -- is
that the GCC code for conversions got rewritten many times, in the
process of correcting some obscure bugs and in the hope of making it
less convoluted and many bugs found their ways in.
I believe the majority of them got eventually fixed.
I sincerelly don't recall any debate on the GCC list with g++
implementors where they decided that they should reject the above code
and implemented that decision. GCC mailing lists are open, archived
and searchable. Feel free to bring in evidence.
--
Gabriel Dos Reis
gdr@cs.tamu.edu
Texas A&M University -- Computer Science Department
301, Bright Building -- College Station, TX 77843-3112
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: kanze@gabi-soft.fr
Date: Wed, 8 Sep 2004 17:06:06 GMT Raw View
Gabriel Dos Reis <gdr@cs.tamu.edu> wrote in message
news:<m3sm9z680z.fsf@merlin.cs.tamu.edu>...
> kanze@gabi-soft.fr writes:
> | gdr@cs.tamu.edu (Gabriel Dos Reis) wrote in message
> | news:<m3oekuowu9.fsf@merlin.cs.tamu.edu>...
> | > johnchx2@yahoo.com (johnchx) writes:
> | > | gdr@cs.tamu.edu (Gabriel Dos Reis) wrote in message
> | > | news:<m37jrkbsn6.fsf@merlin.cs.tamu.edu>...
> | > | > johnchx2@yahoo.com (johnchx) writes:
> | > | > [...]
> | > | > | I think that's correct, but it may be a defect in the
> | > | > | standard. Consider:
> | > | > | extern const int i; // defined in another translation unit
> | > | > | int main () {
> | > | > | void* p = i;
> | > | > | }
> | > | > | The validity of the assignment depends on the availability
> | > | > | of the conversion from const int to pointer type, which in
> | > | > | turn depends on the *value* of i.
> | > | > The validity of the assignment depends on the presence of the
> | > | > initializer.
> | > | No, it also depends on the *value* of the initializer. That
> | > | seems to me to be by far the more interesting wrinkle here.
> | > Yes, but the point is that you get that information from the
> | > declarations (given by name lookup), hence the initializer. Get
> | > things in order, you'll see the light :-)
> | You're looking at it as an implementer.
> No.
> You're not in my mind and you have no clue about how I'm looking at
> it. As a matter of fact, I'm looking at it as if I were a user and
> have no knowledge about how compilers implement C++.
But a user who is used to how compilers work in general. Maybe not
formally, but from having used them. You are still using additional
knowledge which is not explicitly stated, and cannot be deducted from
the English in the standard.
> | The standard says that the expression uses a variable.
> Great!
> | An object.
> Using a variable is not the same as using an object. An object is a
> region of storage. A variable is an association of a name and a
> variable.
A variable is an association of a name and a variable? That sounds a
bit recursive to me. I'm sure there's a typo in it somewhere. But I'm
not sure where; I would have said that a variable is an association of a
name and an object (or an object with a type). But if that is what you
meant, then you would be agreeing with me, that a variable is an object.
> | And thus, which can be declared without being defined,
> You don't declare objects; you declare names.
And a name refers to something.
> Names are interpreted according to their declarations (and attributes
> found therein). Declarations are found by name lookup.
Quite. So if I look up the name, and that name declares an object, and
that object is const, and has an integral type, and is initialized
itself with an integral constant expression, then we can use it in an
integral constant expression.
You don't initialize names. You initialize objects. Saying that a name
is initialized to ... doesn't make sense (at least to me). Saying that
the object declared by the name is initialized does, but then, we are
back to talking about objects.
> | and whose actual initializer might only be specified in another
> | compilation unit.
> So, if it is not there, name lookup cannot find it.
Name lookup never finds an initializer. If finds a name, which is part
of a declaration. In this case, the declaration declares the existance
of a variable. And object. Which may or may not be initialized, but we
can't necessarily know that from the declaration. We can only know that
if the declaration happens also to be a definition.
> Therefore, the interpretation of the name at point of use cannot infer
> "constant expression"ness. QED.
The interpretation of the name is never sufficient to infer "constant
expression"ness. You have to determine what the name refers to. If it
refers to a const variable or a static data member of integral or
enumeration type, it might be a constant expression. If that variable
(the object) is initialized by an integral constant-expression, then it
can be used itself in an integral constant-expression.
According to what is written in the standard, anyway. We both know that
in reality, it can't be unless the initialization is also visible to the
compiler at that point.
[...]
> And I really meant clause 3, because I feel johnchx2 (or you) would
> greatly improve your understanding of the issue through reading it in
> its entirety -- even if you might feel bored.
Well, I will admit that you had a good suggestion there. Right off the
bat, paragraph 4: "a variable is introduced by the declaration of an
object. The variable's name denotes the object." So a declaration is
sufficient to have a variable; we don't need the definition. And the
variable's name denotes the object; i.e. when I use the name of the
variable, I am refering to the object. Still, it would seem that we are
dealing with a name,object pair, and not just the object. (I presume
that that is the point you are trying to make.)
Further on ( 3.5), I read that "A name is said to have linkagne when it
might denote the same object, reference, function, type, template,
namespace or value as a name introduced by a declaration in aother
scope." If I understand your point correctly, each "declaration" is a
different "variable", even if it refers to the same object, because the
names are "different". So we have to find the initialization in the
"variable", that is, the declaration, which introduced the name.
If that is what you are trying to say, then I think I see what you are
getting at. I'm still not convinced, however. I think that this
interpretation introduces more problems than it solves. For example:
extern int const i ;
int const i = 5 ;
We both agree, I'm sure, that that is fully legal C++ (supposing it
occurs at namespace scope, of course). But there are two declarations.
Are they the same variable, or do I have two variables. And supposing I
have two variables (which would seem to be the consequence of what you
are saying), and that they refer to the same object (which is, I hope,
the case), then which "variable" will be found during name lookup?
And an interesting question. Is the following legal?
extern int const i ;
char a[ i ] ;
int const i = 5 ;
I'll admit that I'm even more confused than before. If I have two
variables, then I dont find the one with the initialization on name
lookup. If I have only one, of course, it has the required initializer.
Now let's try:
int const i = 5 ;
void f()
{
extern int const i ;
char a[ i ] ;
}
Legal? How many variables?
My compilers disagree. (Sun CC rejects it, g++ accepts it.) So I guess
I'm not the only one confused. Historically, I would have thought that
the intention was that it be legal, but now, I'm really not sure. (If
my original interpretation of the end of clause 5 is correct, then the
answer is obvious, but we both agree that regardless of what it actually
says, that interpretation cannot be what was meant.)
Given that, how is this different from:
struct S
{
static int const i ;
} ;
int const S::i = 5 ;
char a[ i ] ;
I have always been convinced that this was legal, although admittedly
because some early compiler accepted it. This time, Sun CC also accepts
it. Although as I say, I don't really see how it is different from the
preceding case.
I don't have the time right now to come up with any more example. But I
will say, you've given me food for thought.
--
James Kanze GABI Software http://www.gabi-soft.fr
Conseils en informatique orient e objet/
Beratung in objektorientierter Datenverarbeitung
9 place S mard, 78210 St.-Cyr-l' cole, France, +33 (0)1 30 23 00 34
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: kanze@gabi-soft.fr
Date: Tue, 31 Aug 2004 04:21:35 GMT Raw View
llewelly.at@xmission.dot.com (llewelly) wrote in message
news:<86k6vmbckc.fsf@Zorthluthik.local.bar>...
> kanze@gabi-soft.fr writes:
> > invalid@bigfoot.com (Bob Hairgrove) wrote in message
> > news:<vojli0huf4bc9g6hgpnbsaean3t6fv8hdu@4ax.com>...
> >> On Tue, 24 Aug 2004 02:47:07 GMT, kanze@gabi-soft.fr wrote:
> >> >An interesting question has come up in the German newsgroup, and
> >> >to be frank, I'm not sure of the correct answer. Is:
> >> > int const myNull = 0 ;
> >> >a null pointer constant? I had always supposed it was, but
> >> >careful reading of the standard ( 4.10/1) says that "A null
> >> >pointer constant is an integral constant expression rvalue of
> >> >integer type that evaluates to zero." Given the above, "myNull" is
> >> >not an rvalue, and so not a null pointer constant. According to
> >> >other posters, most compilers, including Comeau, accept it; I seem
> >> >to have read somewhere that Stroustrup says it's one somewhere as
> >> >well. On the other hand, g++ (3.4.0) rejects it, and the standard
> >> >does say rvalue, which would seem to support g++.
> >> >Am I overlooking something? And if not, is it intentional?
> >> >(Also, while I'm at it: can an integral constant expression not
> >> >have integer type?)
> >> If myNull is used on the right-hand side of an assignment, it is
> >> implicitly converted to an rvalue according to 3.10, paragraph 7:
> >> "Whenever an lvalue appears in a context where an rvalue is
> >> expected, the lvalue is converted to an rvalue (...)". This would
> >> happen even if myInt were not const, of course.
> > No problem. If we assign myNull to an int, the implicit conversion
> > takes place.
> > The problem is that we are not assigning myNull to an int, but to a
> > pointer. And that there is no implicite conversion int->pointer.
> > To initialize a pointer with an int, the int must be a null pointer
> > constant. And the definition for null pointer constant says
> > explicitly that it must be an rvalue.
> > The real question is: does an rvalue to lvalue conversion take place
> > in this case, and if it does, why does the standard explicitly say
> > rvalue here.
> >> What is the error shown by g++ 3.4.0 and the context in which it
> >> happens?
> > #include <cstddef>
> > void f( void* ) ;
> > int
> > main()
> > {
> > int const myNull = 0 ;
> > f( myNull ) ;
> > return 0 ;
> > }
> > G++ 3.4.0 says:
> > nullptr.cc: In function `int main()':
> > nullptr.cc:10: error: invalid conversion from `int' to `void*'
> > nullptr.cc:10: error: initializing argument 1 of `void f(void*)'
> > G++ 2.95.2 accepts it, so presumably, they added the error check
> > explicitly, because they read the standard literally.
> [snip]
> If they did so, they did so mistakenly:
> http://www.open-std.org/JTC1/SC22/WG21/docs/cwg_closed.html#456
Which is interesting in its own right. First, the clarification is very
recent (March 2004), and second, it doesn't seem to address the
question: what does the word "rvalue" mean in the definition of a null
pointer constant -- given similar wording without the word rvalue in the
C standard, and I think in Stroustrup and earlier drafts of the standard
as well (although I really should check before saying that:-)), the only
conclusion I can draw is that someone added that word for a purpose, and
the only purpose I can see is to exclude the rvalue to lvalue
conversion.
The "argument" presented at the end of the defect report is in any case
fallicious. The contexts they show where the lvalue to rvalue
conversion is taking place don't specifically say that an rvalue is
required.
Finally, of course, it indicates that g++ did make the change
intentionally, because of the word "rvalue" in the definition of a null
pointer constant. (And probably knowing, or suspecting, that it would
break some poor users code, and gloating over the fact.)
--
James Kanze GABI Software http://www.gabi-soft.fr
Conseils en informatique orient e objet/
Beratung in objektorientierter Datenverarbeitung
9 place S mard, 78210 St.-Cyr-l' cole, France, +33 (0)1 30 23 00 34
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: johnchx2@yahoo.com (johnchx)
Date: Sat, 28 Aug 2004 21:31:01 GMT Raw View
gdr@cs.tamu.edu (Gabriel Dos Reis) wrote in message news:<m37jrkbsn6.fsf@merlin.cs.tamu.edu>...
> johnchx2@yahoo.com (johnchx) writes:
>
> [...]
>
> | I think that's correct, but it may be a defect in the standard.
> | Consider:
> |
> |
> | extern const int i; // defined in another translation unit
> |
> | int main () {
> | void* p = i;
> | }
> |
> | The validity of the assignment depends on the availability of the
> | conversion from const int to pointer type, which in turn depends on
> | the *value* of i.
>
> The validity of the assignment depends on the presence of the
> initializer.
No, it also depends on the *value* of the initializer. That seems to
me to be by far the more interesting wrinkle here.
> At the point of use of "i" in main(), all available
> declarations for "i" do no provide an initializer, therefore it cannot
> be deemed integral constant.
Which would make perfect sense. In fact, I don't know how else you'd
approach the implementation of integral constant expressions while
preserving separate compilation. However, I'm not sure that's
actually what the standard says.
Of course, "What else could they possibly mean?" is often a perfectly
valid principle for interpreting otherwise ambiguous language in the
standard, and by that measure I'm quibbling about nothing. :-)
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: gdr@cs.tamu.edu (Gabriel Dos Reis)
Date: Sun, 29 Aug 2004 20:12:57 GMT Raw View
johnchx2@yahoo.com (johnchx) writes:
| gdr@cs.tamu.edu (Gabriel Dos Reis) wrote in message news:<m37jrkbsn6.fsf@merlin.cs.tamu.edu>...
| > johnchx2@yahoo.com (johnchx) writes:
| >
| > [...]
| >
| > | I think that's correct, but it may be a defect in the standard.
| > | Consider:
| > |
| > |
| > | extern const int i; // defined in another translation unit
| > |
| > | int main () {
| > | void* p = i;
| > | }
| > |
| > | The validity of the assignment depends on the availability of the
| > | conversion from const int to pointer type, which in turn depends on
| > | the *value* of i.
| >
| > The validity of the assignment depends on the presence of the
| > initializer.
|
| No, it also depends on the *value* of the initializer. That seems to
| me to be by far the more interesting wrinkle here.
Yes, but the point is that you get that information from the
declarations (given by name lookup), hence the initializer. Get
things in order, you'll see the light :-)
| > At the point of use of "i" in main(), all available
| > declarations for "i" do no provide an initializer, therefore it cannot
| > be deemed integral constant.
|
| Which would make perfect sense. In fact, I don't know how else you'd
| approach the implementation of integral constant expressions while
| preserving separate compilation. However, I'm not sure that's
| actually what the standard says.
The stanard says that a declaration introduces interpretation and
attributes for a name. It also says that only after name lookup,
function overload resolution (if applicable) and access checking have
succeeded are the attributes introduced by the name's declaration used
further in expression processing. Since name lookup concerns itself
with only the declarations available in the context of of use, I
consider the issue (if there were any) to be resolved.
| Of course, "What else could they possibly mean?" is often a perfectly
| valid principle for interpreting otherwise ambiguous language in the
| standard, and by that measure I'm quibbling about nothing. :-)
It is hard for me to see whether you're quibbling or being serious.
In the latter case, my recommendation would be to read clause 3 of the
standard text.
--
Gabriel Dos Reis
gdr@cs.tamu.edu
Texas A&M University -- Computer Science Department
301, Bright Building -- College Station, TX 77843-3112
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: kanze@gabi-soft.fr
Date: Mon, 30 Aug 2004 17:28:40 GMT Raw View
gdr@cs.tamu.edu (Gabriel Dos Reis) wrote in message
news:<m3d61cbss4.fsf@merlin.cs.tamu.edu>...
> llewelly.at@xmission.dot.com (llewelly) writes:
> [...]
> | There was a bugzilla item opened on this bug some time back, and it
> | was closed as not a bug on the same logic you use:
> | http://gcc.gnu.org/bugzilla/show_bug.cgi?id=13867
> That was a mistake. See
> http://gcc.gnu.org/bugzilla/show_bug.cgi?id=16489
So the people at g++ either disagree, or have changed their mind:-).
At any rate, would it be acceptable to consider the word "rvalue" in
4.10 as a defect, and have it removed. It apparently caused some
confusion to some of the implementors at g++, at least for a time, and
made me unsure of what I was sure I knew as well. (On the other hand, I
was also sure I knew that an enum constant evaluating to zero was a null
pointer constant. Apparently, it isn't, and that is intentional.
Although there too, not all compilers agree.)
--
James Kanze GABI Software http://www.gabi-soft.fr
Conseils en informatique orient e objet/
Beratung in objektorientierter Datenverarbeitung
9 place S mard, 78210 St.-Cyr-l' cole, France, +33 (0)1 30 23 00 34
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: kanze@gabi-soft.fr
Date: Mon, 30 Aug 2004 17:29:14 GMT Raw View
gdr@cs.tamu.edu (Gabriel Dos Reis) wrote in message
news:<m3oekuowu9.fsf@merlin.cs.tamu.edu>...
> johnchx2@yahoo.com (johnchx) writes:
> | gdr@cs.tamu.edu (Gabriel Dos Reis) wrote in message
> | news:<m37jrkbsn6.fsf@merlin.cs.tamu.edu>...
> | > johnchx2@yahoo.com (johnchx) writes:
> | > [...]
> | > | I think that's correct, but it may be a defect in the standard.
> | > | Consider:
> | > | extern const int i; // defined in another translation unit
> | > | int main () {
> | > | void* p = i;
> | > | }
> | > | The validity of the assignment depends on the availability of
> | > | the conversion from const int to pointer type, which in turn
> | > | depends on the *value* of i.
> | > The validity of the assignment depends on the presence of the
> | > initializer.
> | No, it also depends on the *value* of the initializer. That seems
> | to me to be by far the more interesting wrinkle here.
> Yes, but the point is that you get that information from the
> declarations (given by name lookup), hence the initializer. Get
> things in order, you'll see the light :-)
You're looking at it as an implementer. The standard says that the
expression uses a variable. An object. And thus, which can be declared
without being defined, and whose actual initializer might only be
specified in another compilation unit.
The actual meaning of the phrase, strictly interpreted, in English, is
clear. Common sense, of course, tells us that it is not what we want,
but since when does common sense have anything to do with reading a
standard.
[...]
> It is hard for me to see whether you're quibbling or being serious.
> In the latter case, my recommendation would be to read clause 3 of the
> standard text.
I'm not sure what you mean by clause 3. There is a clause 3 in many of
the chapters of the standard, and if you mean chapter 3, you'll have to
be more precise -- chapter 3 is large, and covers a number of issues.
As far as I can see, there is definitly a defect in the standard. In
practice, it isn't a serious one, because everyone simple implements
what was meant, and not what was said. Still, I would think that is
should be corrected when the occasion presents itself.
--
James Kanze GABI Software http://www.gabi-soft.fr
Conseils en informatique orient e objet/
Beratung in objektorientierter Datenverarbeitung
9 place S mard, 78210 St.-Cyr-l' cole, France, +33 (0)1 30 23 00 34
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: kanze@gabi-soft.fr
Date: Mon, 30 Aug 2004 17:58:12 GMT Raw View
gdr@cs.tamu.edu (Gabriel Dos Reis) wrote in message
news:<m36573q17s.fsf@merlin.cs.tamu.edu>...
> johnchx2@yahoo.com (johnchx) writes:
> [...]
> | I was actually surprised not to find language in the standard
> | outlawing this, since "everybody knows" that the value of an
> | integral constant expression has to be availabe to the compiler at
> | compile time. And I suspect that it would be easy to drop in a line
> | or two of standardese to close the loophole. (I also suspect that
> | I'm just overlooking something, which someone will point me to at
> | any moment....)
> I suspect you're missing the fact that interpretation of names is
> based on the set of declarations available at use point.
I suspect that you are basing your argument on what is blatently obvious
(especially to an implementer) but not in the standard:-). Now that he
raised the point, I vaguely seem to remember having brought it up some
time ago as well. The standard says "An integral constant-expression
can only involve [...] const variables or static data members of
integral or enumeration types initialized with constant expressions,
[...]". There's not the slightest requirement that the declaration
containing the initialization be visible (although I'm sure we all agree
that this was the intent).
--
James Kanze GABI Software http://www.gabi-soft.fr
Conseils en informatique orient e objet/
Beratung in objektorientierter Datenverarbeitung
9 place S mard, 78210 St.-Cyr-l' cole, France, +33 (0)1 30 23 00 34
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: llewelly.at@xmission.dot.com (llewelly)
Date: Thu, 26 Aug 2004 17:41:53 GMT Raw View
kanze@gabi-soft.fr writes:
> invalid@bigfoot.com (Bob Hairgrove) wrote in message
> news:<qobni012n63aa5q1thvj8csir125e7knhi@4ax.com>...
>> On Tue, 24 Aug 2004 20:08:41 GMT, falk.tannhauser@crf.canon.fr (Falk
>> Tannh user) wrote:
>
>> >Bob Hairgrove wrote:
>
>> >> What is the error shown by g++ 3.4.0 and the context in which it
>> >> happens?
>
>> >$ cat 0.cxx
>> >int const myNull =3D 0;
>> >void const* pv =3D myNull;
>> >double* pd =3D myNull;
>> >void (*pf)() =3D myNull;
>
>> >$ g++ --version
>> >g++ (GCC) 3.3.3 (cygwin special)
>> >Copyright (C) 2003 Free Software Foundation, Inc.
>> >[snip]
>
>> >$ g++ -c 0.cxx
>> >0.cxx:2: error: invalid conversion from `int' to `const void*'
>> >0.cxx:3: error: invalid conversion from `int' to `double*'
>> >0.cxx:4: error: invalid conversion from `int' to `void (*)()'
>> >$=20
>
>> >Same problem for "powerpc-rtems-g++ (GCC) 3.2.3". However, it
>> >compiles without problems on g++ 2.95.4 and 3.0.4 under Linux. I
>> >have no access to g++ 3.4.0.
>
>> Seems to me that this is definitely not conforming behavior according
>> to the current standard. "int const MyNull" is definitely a constant
>> integral value (see 5.9 and 4.10 of the standard), and the lvalue
>> should be implicitly converted to an rvalue here (see 3.10).
>
> But that is exactly the question. Should the lvalue be converted to an
> rvalue? The text in =A74.10/1 seems to say that the expression itself
> must be an rvalue, not that it must be something convertable into an
> rvalue. If an lvalue is also acceptable, why the word "rvalue" in the
> definition.
>
> Note too that the definition insists on integer type. An integral
> constant expression can have an enum type, but apparently, something
> like "enum { myNull =3D 0 } ;" does not define a null pointer constant
> either.
>
> Since I don't know what the original authors actually had in mind when
> they formulated that paragraph, I'm asking here. I have my opinion as
> to what the standard actually says (it actually seems pretty clear), bu=
t
> I'd like an authorative answer as to whether this is what it was
> actually meant to say (or whether I've missed something important).
>
> I'm also curious whether this is a "regression error" in g++, or whethe=
r
> they did it intentionally, because they read the same sentence in the
> standard that I did. I rather suspect the latter, especially as "myNul=
l
> + 0" is treated as a null pointer constant, but of course, only the
> people who made the change in g++ can say for sure.
[snip]
There was a bugzilla item opened on this bug some time back, and it
was closed as not a bug on the same logic you use:
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=3D13867=20
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: kanze@gabi-soft.fr
Date: Thu, 26 Aug 2004 17:42:19 GMT Raw View
invalid@bigfoot.com (Bob Hairgrove) wrote in message
news:<nqepi01oa5gsrvcriagh12gmmjcg61kk08@4ax.com>...
> On Wed, 25 Aug 2004 04:27:46 GMT, kanze@gabi-soft.fr wrote:
> >> If myNull is used on the right-hand side of an assignment, it is
> >> implicitly converted to an rvalue according to 3.10, paragraph 7:
> >> "Whenever an lvalue appears in a context where an rvalue is
> >> expected, the lvalue is converted to an rvalue (...)". This would
> >> happen even if myInt were not const, of course.
> >No problem. If we assign myNull to an int, the implicit conversion
> >takes place.
> >The problem is that we are not assigning myNull to an int, but to a
> >pointer. And that there is no implicite conversion int->pointer. To
> >initialize a pointer with an int, the int must be a null pointer
> >constant. And the definition for null pointer constant says
> >explicitly that it must be an rvalue.
> >The real question is: does an rvalue to lvalue conversion take place
> >in this case, and if it does, why does the standard explicitly say
> >rvalue here.
> I believe it should take place, but only in the special case where the
> lvalue has the value zero (or evaluates to 0). At least that is how I
> understand it. After all, paragraph 7 of section 3.10 says:
> "Whenever an lvalue appears in a context where an rvalue is expected,
> the lvalue is converted to an rvalue; see 4.1, 4.2 and 4.3".
Agreed. This paragraph does seem conclusive. (I suppose one might
argue that we only expect an rvalue because it is a null pointer
constant, that it isn't a null pointer constant until the conversion
takes place, and that the conversion doesn't take place until we expect
an rvalue, but that sounds rather farfetched to me.)
> Now 4.1, 4.2 and 4.3 don't seem to shed any light on the subject, so I
> assume that the authors of the standard mean exactly what they have
> written.
Now I'm left with the question, why does 4.10/1 insist on rvalue, if
you can use an lvalue as well?
--
James Kanze GABI Software http://www.gabi-soft.fr
Conseils en informatique orient e objet/
Beratung in objektorientierter Datenverarbeitung
9 place S mard, 78210 St.-Cyr-l' cole, France, +33 (0)1 30 23 00 34
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: llewelly.at@xmission.dot.com (llewelly)
Date: Thu, 26 Aug 2004 19:25:50 GMT Raw View
kanze@gabi-soft.fr writes:
> invalid@bigfoot.com (Bob Hairgrove) wrote in message
> news:<vojli0huf4bc9g6hgpnbsaean3t6fv8hdu@4ax.com>...
>
>> On Tue, 24 Aug 2004 02:47:07 GMT, kanze@gabi-soft.fr wrote:
>
>> >An interesting question has come up in the German newsgroup, and to
>> >be frank, I'm not sure of the correct answer. Is:
>> > int const myNull = 0 ;
>> >a null pointer constant? I had always supposed it was, but careful
>> >reading of the standard ( 4.10/1) says that "A null pointer constant
>> >is an integral constant expression rvalue of integer type that
>> >evaluates to zero." Given the above, "myNull" is not an rvalue, and
>> >so not a null pointer constant. According to other posters, most
>> >compilers, including Comeau, accept it; I seem to have read somewhere
>> >that Stroustrup says it's one somewhere as well. On the other hand,
>> >g++ (3.4.0) rejects it, and the standard does say rvalue, which would
>> >seem to support g++.
>
>> >Am I overlooking something? And if not, is it intentional?
>
>> >(Also, while I'm at it: can an integral constant expression not have
>> >integer type?)
>
>> If myNull is used on the right-hand side of an assignment, it is
>> implicitly converted to an rvalue according to 3.10, paragraph 7:
>> "Whenever an lvalue appears in a context where an rvalue is expected,
>> the lvalue is converted to an rvalue (...)". This would happen even if
>> myInt were not const, of course.
>
> No problem. If we assign myNull to an int, the implicit conversion
> takes place.
>
> The problem is that we are not assigning myNull to an int, but to a
> pointer. And that there is no implicite conversion int->pointer. To
> initialize a pointer with an int, the int must be a null pointer
> constant. And the definition for null pointer constant says explicitly
> that it must be an rvalue.
>
> The real question is: does an rvalue to lvalue conversion take place in
> this case, and if it does, why does the standard explicitly say rvalue
> here.
>
>> What is the error shown by g++ 3.4.0 and the context in which it
>> happens?
>
> #include <cstddef>
>
> void f( void* ) ;
>
> int
> main()
> {
> int const myNull = 0 ;
> f( myNull ) ;
> return 0 ;
> }
>
> G++ 3.4.0 says:
> nullptr.cc: In function `int main()':
> nullptr.cc:10: error: invalid conversion from `int' to `void*'
> nullptr.cc:10: error: initializing argument 1 of `void f(void*)'
>
> G++ 2.95.2 accepts it, so presumably, they added the error check
> explicitly, because they read the standard literally.
[snip]
If they did so, they did so mistakenly:
http://www.open-std.org/JTC1/SC22/WG21/docs/cwg_closed.html#456
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: falk.tannhauser@crf.canon.fr (=?ISO-8859-1?Q?Falk_Tannh=E4user?=)
Date: Thu, 26 Aug 2004 19:25:58 GMT Raw View
johnchx wrote:
>>=20
> extern const int i; // defined in another translation unit
>=20
> int main () {
> void* p =3D i;
> }
>=20
> The validity of the assignment depends on the availability of the
> conversion from const int to pointer type, which in turn depends on
> the *value* of i.
I don't think that 'i' qualifies as a constant expression in
the sense of =A7 5.19/1 - you can't do
extern int const i;
char foo[i];
either - there is generally no way for the compiler to determine
if 'i' was actually initialised with a constant expression as
required by =A7 5.19/1, since
int const i =3D static_cast<int>(std::time(0));
or
int const i =3D std::rand();
are valid definitions of 'i'.
Falk
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: invalid@bigfoot.com (Bob Hairgrove)
Date: Thu, 26 Aug 2004 20:22:31 GMT Raw View
On Thu, 26 Aug 2004 06:18:56 GMT, bjarne@gmail.com (Bjarne Stroustrup)
wrote:
>kanze@gabi-soft.fr wrote in message
>>
>> > On Tue, 24 Aug 2004 02:47:07 GMT, kanze@gabi-soft.fr wrote:
>>
>> > >An interesting question has come up in the German newsgroup, and to
>> > >be frank, I'm not sure of the correct answer. Is:
>> > > int const myNull = 0 ;
>> > >a null pointer constant?
>
>Yes.
>
>> ... On the other hand,
>> > >g++ (3.4.0) rejects it, and the standard does say rvalue, which would
>> > >seem to support g++.
>>
>
>It's a bug in GCC 3.4.0
>
> -- Bjarne Stroustrup; http://www.research.att.com/~bs
"johnchx" has brought up an interesting point in this same thread
which has started me thinking:
What if myNull is defined in a different translation unit? How can the
compiler resolve the value at compile time?
I think his proposal to restrict things to variables in the current
translation unit would at least have the merit of making things a lot
easier on implementors (especially since myNull could be defined in a
shared library). OTOH, his restriction would remove much of the
incentive for declaring myNull this way in the first place (which IMHO
might not be a bad idea ... using the literal "0" everywhere seems
good enough to me).
Or is this something which is already covered somewhere by the
standard?
--
Bob Hairgrove
NoSpamPlease@Home.com
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: kanze@gabi-soft.fr
Date: Wed, 25 Aug 2004 04:27:46 GMT Raw View
invalid@bigfoot.com (Bob Hairgrove) wrote in message
news:<vojli0huf4bc9g6hgpnbsaean3t6fv8hdu@4ax.com>...
> On Tue, 24 Aug 2004 02:47:07 GMT, kanze@gabi-soft.fr wrote:
> >An interesting question has come up in the German newsgroup, and to
> >be frank, I'm not sure of the correct answer. Is:
> > int const myNull = 0 ;
> >a null pointer constant? I had always supposed it was, but careful
> >reading of the standard ( 4.10/1) says that "A null pointer constant
> >is an integral constant expression rvalue of integer type that
> >evaluates to zero." Given the above, "myNull" is not an rvalue, and
> >so not a null pointer constant. According to other posters, most
> >compilers, including Comeau, accept it; I seem to have read somewhere
> >that Stroustrup says it's one somewhere as well. On the other hand,
> >g++ (3.4.0) rejects it, and the standard does say rvalue, which would
> >seem to support g++.
> >Am I overlooking something? And if not, is it intentional?
> >(Also, while I'm at it: can an integral constant expression not have
> >integer type?)
> If myNull is used on the right-hand side of an assignment, it is
> implicitly converted to an rvalue according to 3.10, paragraph 7:
> "Whenever an lvalue appears in a context where an rvalue is expected,
> the lvalue is converted to an rvalue (...)". This would happen even if
> myInt were not const, of course.
No problem. If we assign myNull to an int, the implicit conversion
takes place.
The problem is that we are not assigning myNull to an int, but to a
pointer. And that there is no implicite conversion int->pointer. To
initialize a pointer with an int, the int must be a null pointer
constant. And the definition for null pointer constant says explicitly
that it must be an rvalue.
The real question is: does an rvalue to lvalue conversion take place in
this case, and if it does, why does the standard explicitly say rvalue
here.
> What is the error shown by g++ 3.4.0 and the context in which it
> happens?
#include <cstddef>
void f( void* ) ;
int
main()
{
int const myNull = 0 ;
f( myNull ) ;
return 0 ;
}
G++ 3.4.0 says:
nullptr.cc: In function `int main()':
nullptr.cc:10: error: invalid conversion from `int' to `void*'
nullptr.cc:10: error: initializing argument 1 of `void f(void*)'
G++ 2.95.2 accepts it, so presumably, they added the error check
explicitly, because they read the standard literally.
--
James Kanze GABI Software http://www.gabi-soft.fr
Conseils en informatique orient e objet/
Beratung in objektorientierter Datenverarbeitung
9 place S mard, 78210 St.-Cyr-l' cole, France, +33 (0)1 30 23 00 34
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: kanze@gabi-soft.fr
Date: Wed, 25 Aug 2004 17:17:02 GMT Raw View
invalid@bigfoot.com (Bob Hairgrove) wrote in message
news:<qobni012n63aa5q1thvj8csir125e7knhi@4ax.com>...
> On Tue, 24 Aug 2004 20:08:41 GMT, falk.tannhauser@crf.canon.fr (Falk
> Tannh user) wrote:
> >Bob Hairgrove wrote:
> >> What is the error shown by g++ 3.4.0 and the context in which it
> >> happens?
> >$ cat 0.cxx
> >int const myNull = 0;
> >void const* pv = myNull;
> >double* pd = myNull;
> >void (*pf)() = myNull;
> >$ g++ --version
> >g++ (GCC) 3.3.3 (cygwin special)
> >Copyright (C) 2003 Free Software Foundation, Inc.
> >[snip]
> >$ g++ -c 0.cxx
> >0.cxx:2: error: invalid conversion from `int' to `const void*'
> >0.cxx:3: error: invalid conversion from `int' to `double*'
> >0.cxx:4: error: invalid conversion from `int' to `void (*)()'
> >$
> >Same problem for "powerpc-rtems-g++ (GCC) 3.2.3". However, it
> >compiles without problems on g++ 2.95.4 and 3.0.4 under Linux. I
> >have no access to g++ 3.4.0.
> Seems to me that this is definitely not conforming behavior according
> to the current standard. "int const MyNull" is definitely a constant
> integral value (see 5.9 and 4.10 of the standard), and the lvalue
> should be implicitly converted to an rvalue here (see 3.10).
But that is exactly the question. Should the lvalue be converted to an
rvalue? The text in 4.10/1 seems to say that the expression itself
must be an rvalue, not that it must be something convertable into an
rvalue. If an lvalue is also acceptable, why the word "rvalue" in the
definition.
Note too that the definition insists on integer type. An integral
constant expression can have an enum type, but apparently, something
like "enum { myNull = 0 } ;" does not define a null pointer constant
either.
Since I don't know what the original authors actually had in mind when
they formulated that paragraph, I'm asking here. I have my opinion as
to what the standard actually says (it actually seems pretty clear), but
I'd like an authorative answer as to whether this is what it was
actually meant to say (or whether I've missed something important).
I'm also curious whether this is a "regression error" in g++, or whether
they did it intentionally, because they read the same sentence in the
standard that I did. I rather suspect the latter, especially as "myNull
+ 0" is treated as a null pointer constant, but of course, only the
people who made the change in g++ can say for sure.
For what it's worth, even g++ 2.95.2 and VC++ 6.0 reject the enum,
although Sun CC accepts it. So even compiler implementors don't seem to
be completely in agreement. Given the following program:
void f( void* ) ;
void
g()
{
int const myNull = 0 ;
f( myNull ) ; // line 8
f( myNull + 0 ) ; // line 9
}
void
h()
{
enum { myNull = 0 } ;
f( myNull ) ; // line 16
f( myNull + 0 ) ; // line 17
}
One compiler I have access to (Sun CC 5.1) compiles it without errors,
two (g++ 2.95.2 and VC++ 6.0) give an error on line 16 only, and one
(g++ 3.4.0) gives errors on both line 8 and line 16.
I don't know if it is worth mentionning, but in C, line 16 IS a legal
null pointer constant, because enum constants in C have type int. It's
entirely possible that Sun CC accepts it simply for reasons of backwards
compatibility. (Sun CC does a lot of things for reasons of backwards
compatibility.)
Finally (just to open another can of worms), there is a problem if we
accept the rvalue to lvalue conversion -- the conversion strips away the
const. Frankly, I'm not sure what the implications of this really
are:-). (Probably nothing, really, since 5.19/1 is pretty clear that
such a variable can be used in a integral constant expression. But I
like the idea that a non const type can result in a constant
expression. It's along the same lines as the fact that a null pointer
constant cannot have a pointer type:-).)
--
James Kanze GABI Software http://www.gabi-soft.fr
Conseils en informatique orient e objet/
Beratung in objektorientierter Datenverarbeitung
9 place S mard, 78210 St.-Cyr-l' cole, France, +33 (0)1 30 23 00 34
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: johnchx2@yahoo.com (johnchx)
Date: Wed, 25 Aug 2004 17:23:54 GMT Raw View
invalid@bigfoot.com (Bob Hairgrove) wrote
> >Bob Hairgrove wrote:
> >>
> >> What is the error shown by g++ 3.4.0 and the context in which it
> >> happens?
> >
> >$ cat 0.cxx
> >int const myNull = 0;
> >void const* pv = myNull;
> >double* pd = myNull;
> >void (*pf)() = myNull;
> >
> >$ g++ --version
> >g++ (GCC) 3.3.3 (cygwin special)
> >Copyright (C) 2003 Free Software Foundation, Inc.
> >[snip]
> >
> >$ g++ -c 0.cxx
> >0.cxx:2: error: invalid conversion from `int' to `const void*'
> >0.cxx:3: error: invalid conversion from `int' to `double*'
> >0.cxx:4: error: invalid conversion from `int' to `void (*)()'
> >$
> >
> >Same problem for "powerpc-rtems-g++ (GCC) 3.2.3". However,
> >it compiles without problems on g++ 2.95.4 and 3.0.4 under Linux.
> >I have no access to g++ 3.4.0.
> >
> >Falk
>
> Seems to me that this is definitely not conforming behavior according
> to the current standard. "int const MyNull" is definitely a constant
> integral value (see 5.9 and 4.10 of the standard), and the lvalue
> should be implicitly converted to an rvalue here (see 3.10).
>
I think that's correct, but it may be a defect in the standard.
Consider:
extern const int i; // defined in another translation unit
int main () {
void* p = i;
}
The validity of the assignment depends on the availability of the
conversion from const int to pointer type, which in turn depends on
the *value* of i.
Off the top of my head, I can't think of any other situation in which
the existence of an implicit conversion from type T1 to type T2
depends on the value of the particular object of type T1 under
consideration.
It looks like there are two issues here:
(1) Wouldn't it make sense to restrict the use of const variables
to variables defined in the current translation unit?
(2) The idea of making the "type-correctness" of a statement or
expression dependent on the value of one of the operands seems
just wrong. It's against nature. (The solution would be a
first-class null pointer constant built into the language,
which, I gather, is currently under consideration.)
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: invalid@bigfoot.com (Bob Hairgrove)
Date: Thu, 26 Aug 2004 00:05:27 GMT Raw View
On Wed, 25 Aug 2004 04:27:46 GMT, kanze@gabi-soft.fr wrote:
>> If myNull is used on the right-hand side of an assignment, it is
>> implicitly converted to an rvalue according to 3.10, paragraph 7:
>> "Whenever an lvalue appears in a context where an rvalue is expected,
>> the lvalue is converted to an rvalue (...)". This would happen even if
>> myInt were not const, of course.
>
>No problem. If we assign myNull to an int, the implicit conversion
>takes place.
>
>The problem is that we are not assigning myNull to an int, but to a
>pointer. And that there is no implicite conversion int->pointer. To
>initialize a pointer with an int, the int must be a null pointer
>constant. And the definition for null pointer constant says explicitly
>that it must be an rvalue.
>
>The real question is: does an rvalue to lvalue conversion take place in
>this case, and if it does, why does the standard explicitly say rvalue
>here.
I believe it should take place, but only in the special case where the
lvalue has the value zero (or evaluates to 0). At least that is how I
understand it. After all, paragraph 7 of section 3.10 says:
"Whenever an lvalue appears in a context where an rvalue is expected,
the lvalue is converted to an rvalue; see 4.1, 4.2 and 4.3".
Now 4.1, 4.2 and 4.3 don't seem to shed any light on the subject, so I
assume that the authors of the standard mean exactly what they have
written.
Interestingly enough, in "TC++PL" section 5.1.1 "Zero" (3rd edition,
page 88) Bjarne Stroustrup recommends declaring NULL like this:
const int NULL = 0;
instead of using a macro, or else using a literal value of 0. I
believe that this makes the *intention* of the standard quite clear.
--
Bob Hairgrove
NoSpamPlease@Home.com
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: bjarne@gmail.com (Bjarne Stroustrup)
Date: Thu, 26 Aug 2004 06:18:56 GMT Raw View
kanze@gabi-soft.fr wrote in message
>
> > On Tue, 24 Aug 2004 02:47:07 GMT, kanze@gabi-soft.fr wrote:
>
> > >An interesting question has come up in the German newsgroup, and to
> > >be frank, I'm not sure of the correct answer. Is:
> > > int const myNull = 0 ;
> > >a null pointer constant?
Yes.
> ... On the other hand,
> > >g++ (3.4.0) rejects it, and the standard does say rvalue, which would
> > >seem to support g++.
>
It's a bug in GCC 3.4.0
-- Bjarne Stroustrup; http://www.research.att.com/~bs
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: gdr@cs.tamu.edu (Gabriel Dos Reis)
Date: Fri, 27 Aug 2004 19:19:43 GMT Raw View
kanze@gabi-soft.fr writes:
[...]
| > What is the error shown by g++ 3.4.0 and the context in which it
| > happens?
|
| #include <cstddef>
|
| void f( void* ) ;
|
| int
| main()
| {
| int const myNull = 0 ;
| f( myNull ) ;
| return 0 ;
| }
|
| G++ 3.4.0 says:
| nullptr.cc: In function `int main()':
| nullptr.cc:10: error: invalid conversion from `int' to `void*'
| nullptr.cc:10: error: initializing argument 1 of `void f(void*)'
As I said elsewhere, that was an -unintended- behaviour. A regression.
| G++ 2.95.2 accepts it, so presumably, they added the error check
| explicitly, because they read the standard literally.
No, it was a fallaout for something else, not a behaviour that was intended.
--
Gabriel Dos Reis
gdr@cs.tamu.edu
Texas A&M University -- Computer Science Department
301, Bright Building -- College Station, TX 77843-3112
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: gdr@cs.tamu.edu (Gabriel Dos Reis)
Date: Sat, 28 Aug 2004 02:52:35 GMT Raw View
kanze@gabi-soft.fr writes:
[...]
| > Seems to me that this is definitely not conforming behavior according
| > to the current standard. "int const MyNull" is definitely a constant
| > integral value (see 5.9 and 4.10 of the standard), and the lvalue
| > should be implicitly converted to an rvalue here (see 3.10).
|
| But that is exactly the question. Should the lvalue be converted to an
| rvalue?
Yes, because myNull is used in a context where an rvalue is expected
and lvalue->rvalue automatically happens in such contexts.
[...]
| I'm also curious whether this is a "regression error" in g++, or whether
It is. While having the null discussion on fr.comp.lang.c last early
July, Bjarne brought to my attention that GCC was misbehaving on that
very same example. I immediately reported the regression and it got
fixed for GCC-3.4.2.
| they did it intentionally, because they read the same sentence in the
| standard that I did.
That never was an intentional behaviour.
--
Gabriel Dos Reis
gdr@cs.tamu.edu
Texas A&M University -- Computer Science Department
301, Bright Building -- College Station, TX 77843-3112
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: johnchx2@yahoo.com (johnchx)
Date: Sat, 28 Aug 2004 02:53:38 GMT Raw View
falk.tannhauser@crf.canon.fr (Falk Tannh user) wrote
> johnchx wrote:
> >>
> > extern const int i; // defined in another translation unit
> >
> > int main () {
> > void* p = i;
> > }
> >
> > The validity of the assignment depends on the availability of the
> > conversion from const int to pointer type, which in turn depends on
> > the *value* of i.
>
> I don't think that 'i' qualifies as a constant expression in
> the sense of 5.19/1 - you can't do
> extern int const i;
> char foo[i];
> either - there is generally no way for the compiler to determine
> if 'i' was actually initialised with a constant expression as
> required by 5.19/1, since
> int const i = static cast<int>(std::time(0));
> or
> int const i = std::rand();
> are valid definitions of 'i'.
>
Just because it's manifestly impossible doesn't mean that the standard
doesn't require it. :-)
I was actually surprised not to find language in the standard
outlawing this, since "everybody knows" that the value of an integral
constant expression has to be availabe to the compiler at compile
time. And I suspect that it would be easy to drop in a line or two of
standardese to close the loophole. (I also suspect that I'm just
overlooking something, which someone will point me to at any
moment....)
I think the bigger picture issue is the essential "uncleanness" of
making the type-correctness of something depend on a value. You can
convert an int to a pointer, but only if it's the *magic* int?
I have the impression that this uglyness exists only to allow us to
write:
foo* p = 0;
because there's simply no other way to write down the notion "null
pointer" (and that's how C does it). I gather that the committee is
working on a proposal for a real name for the null pointer (nullptr)
which should allow us to deprecate this strangeness:
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2004/n1601.pdf
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: gdr@cs.tamu.edu (Gabriel Dos Reis)
Date: Sat, 28 Aug 2004 03:34:48 GMT Raw View
llewelly.at@xmission.dot.com (llewelly) writes:
[...]
| There was a bugzilla item opened on this bug some time back, and it
| was closed as not a bug on the same logic you use:
| http://gcc.gnu.org/bugzilla/show_bug.cgi?id=13867
That was a mistake. See
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=16489
--
Gabriel Dos Reis
gdr@cs.tamu.edu
Texas A&M University -- Computer Science Department
301, Bright Building -- College Station, TX 77843-3112
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: gdr@cs.tamu.edu (Gabriel Dos Reis)
Date: Sat, 28 Aug 2004 03:35:15 GMT Raw View
johnchx2@yahoo.com (johnchx) writes:
[...]
| I think that's correct, but it may be a defect in the standard.
| Consider:
|
|
| extern const int i; // defined in another translation unit
|
| int main () {
| void* p = i;
| }
|
| The validity of the assignment depends on the availability of the
| conversion from const int to pointer type, which in turn depends on
| the *value* of i.
The validity of the assignment depends on the presence of the
initializer. At the point of use of "i" in main(), all available
declarations for "i" do no provide an initializer, therefore it cannot
be deemed integral constant.
Forget about null pointer. Consider
extern const i;
enum E { e = i };
--
Gabriel Dos Reis
gdr@cs.tamu.edu
Texas A&M University -- Computer Science Department
301, Bright Building -- College Station, TX 77843-3112
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: gdr@cs.tamu.edu (Gabriel Dos Reis)
Date: Sat, 28 Aug 2004 06:12:06 GMT Raw View
johnchx2@yahoo.com (johnchx) writes:
[...]
| I was actually surprised not to find language in the standard
| outlawing this, since "everybody knows" that the value of an integral
| constant expression has to be availabe to the compiler at compile
| time. And I suspect that it would be easy to drop in a line or two of
| standardese to close the loophole. (I also suspect that I'm just
| overlooking something, which someone will point me to at any
| moment....)
I suspect you're missing the fact that interpretation of names is
based on the set of declarations available at use point.
--
Gabriel Dos Reis
gdr@cs.tamu.edu
Texas A&M University -- Computer Science Department
301, Bright Building -- College Station, TX 77843-3112
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: gdr@cs.tamu.edu (Gabriel Dos Reis)
Date: Sat, 28 Aug 2004 16:10:03 GMT Raw View
invalid@bigfoot.com (Bob Hairgrove) writes:
| "johnchx" has brought up an interesting point in this same thread
| which has started me thinking:
|
| What if myNull is defined in a different translation unit? How can the
| compiler resolve the value at compile time?
If there is no declaration with the right initializer at the point of
use, it is no integral constant expression.
[...]
| Or is this something which is already covered somewhere by the
| standard?
Interpretation of names used in the program is according to the set of
declarations available at use point, which is the process taken care
of by name lookup rules.
--
Gabriel Dos Reis
gdr@cs.tamu.edu
Texas A&M University -- Computer Science Department
301, Bright Building -- College Station, TX 77843-3112
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]