Discussion:
Confused about the implementation of static int isnullptr(Tree e) , any help?
(too old to reply)
Thimble Liu
2020-04-14 13:58:41 UTC
Permalink
I'm reading the code of lcc, and also the book. And I'm stucking at the function isnullptr(Tree e), in file enode.c. The function is below:

static int isnullptr(e) Tree e; {
return (isint(e->type) && generic(e->op) == CNST
&& cast(e, unsignedtype)->u.v.u == 0)
|| (isvoidptr(e->type) && e->op == CNST+P
&& e->u.v.p == NULL);
}


I've checked the ANSI C standard about the null pointer and the null pointer constant, and still can't see how the return of isnullptr connect about the standard about null pointer or null pointer constant.

I also read the code of cast, does (isvoidptr(e->type) && e->op == CNST+P && e->u.v.p == NULL) implies that "a integer constant expression which value is 0 cast to type void *"? If so, why the op->e should be CNSP+P, as the code of lex.c suggested 0 is processed into a CNST+I tree? Is it caused by constant folding?

Really hope to get help! Thanks!
jacobnavia
2020-04-14 21:50:48 UTC
Permalink
Post by Thimble Liu
static int isnullptr(e) Tree e; {
return (isint(e->type) && generic(e->op) == CNST
&& cast(e, unsignedtype)->u.v.u == 0)
|| (isvoidptr(e->type) && e->op == CNST+P
&& e->u.v.p == NULL);
}
I've checked the ANSI C standard about the null pointer and the null pointer constant, and still can't see how the return of isnullptr connect about the standard about null pointer or null pointer constant.
I also read the code of cast, does (isvoidptr(e->type) && e->op == CNST+P && e->u.v.p == NULL) implies that "a integer constant expression which value is 0 cast to type void *"? If so, why the op->e should be CNSP+P, as the code of lex.c suggested 0 is processed into a CNST+I tree? Is it caused by constant folding?
Really hope to get help! Thanks!
There are two arms in the condition above:

1:

isint(e->type) &&
generic(e->op) == CNST &&
cast(e, unsignedtype)->u.v.u == 0)

An integer constant of value zero can be used as a null pointer

2:

isvoidptr(e->type) &&
e->op == CNST+P &&
e->u.v.p == NULL

A pointer with type constant and value zero

The zero is read as an integer, yes, but it can be later cast into a
void pointer or used to return a NULL value.

for instance

char *fn(void)
{
return 0;
}


P.S. There is no constant folding in the original lcc. I added that
feature much later.
Thimble Liu
2020-04-15 03:05:35 UTC
Permalink
Post by Thimble Liu
Post by Thimble Liu
static int isnullptr(e) Tree e; {
return (isint(e->type) && generic(e->op) == CNST
&& cast(e, unsignedtype)->u.v.u == 0)
|| (isvoidptr(e->type) && e->op == CNST+P
&& e->u.v.p == NULL);
}
I've checked the ANSI C standard about the null pointer and the null pointer constant, and still can't see how the return of isnullptr connect about the standard about null pointer or null pointer constant.
I also read the code of cast, does (isvoidptr(e->type) && e->op == CNST+P && e->u.v.p == NULL) implies that "a integer constant expression which value is 0 cast to type void *"? If so, why the op->e should be CNSP+P, as the code of lex.c suggested 0 is processed into a CNST+I tree? Is it caused by constant folding?
Really hope to get help! Thanks!
isint(e->type) &&
generic(e->op) == CNST &&
cast(e, unsignedtype)->u.v.u == 0)
An integer constant of value zero can be used as a null pointer
isvoidptr(e->type) &&
e->op == CNST+P &&
e->u.v.p == NULL
A pointer with type constant and value zero
The zero is read as an integer, yes, but it can be later cast into a
void pointer or used to return a NULL value.
for instance
char *fn(void)
{
return 0;
}
P.S. There is no constant folding in the original lcc. I added that
feature much later.
Thank you very much for reply!
I understand that a pointer to type constant and value zero is a null pointer, but the second arm of that condition still makes me confused.
I don't understand how a integer constant 0 cast to void *, can result a tree which op is CNST+P, and u.v.p field equal to NULL.
I think cast a integer constant 0 to type void * should result a tree that its return type is void * and op is still CNST+I and value field should be integer 0, am I right?

When I'was readingthe code of cast, I didn't see codes about changing the op of the tree, I think function cast is done by function retype() and simplify(). retype() doesn't change the op of the tree. Is condition 2 due to function simplify()?
jacobnavia
2020-04-15 13:02:13 UTC
Permalink
Post by Thimble Liu
I don't understand how a integer constant 0 cast to void *, can result a tree which op is CNST+P, and u.v.p field equal to NULL.
I think that if you write:

char *p = 0x40407865;

You are making a pointer out of a constant. That wouldn't be the NULL
pointer since its value would be different from zero, hence the second
condition.
Keith Thompson
2020-04-15 19:47:51 UTC
Permalink
Post by jacobnavia
Post by Thimble Liu
I don't understand how a integer constant 0 cast to void *, can
result a tree which op is CNST+P, and u.v.p field equal to NULL.
char *p = 0x40407865;
You are making a pointer out of a constant. That wouldn't be the NULL
pointer since its value would be different from zero, hence the second
condition.
Right. Expanding on that a bit, the C standard defines a "null
pointer constant" as "An integer constant expression with the value
0, or such an expression cast to type void *". So
char *p = 0;
sets p to a null pointer value, and
char *p = (char*)0x40407865;
sets p to some implementation-defined value (almost certainly not a null
pointer), but
int zero = 0;
char *p = (char*)zero;
doesn't necessarily set p to a null pointer value. It *probably*
will (and lcc might even guarantee it), but the the language
doesn't guarantee it, because there is no null pointer constant.
(Even "const int zero = 0;" wouldn't make `zero` or `(char*)zero`
a null pointer constant.)

Note that I'm only talking about what the C standard says. I know
practically nothing about lcc internals. lcc, I'm fairly sure,
represents a null pointer as all-bits-zero, which is the case for all
or almost all actual compilers but is not required by the language.
--
Keith Thompson (The_Other_Keith) Keith.S.Thompson+***@gmail.com
Working, but not speaking, for Philips Healthcare
void Void(void) { Void(); } /* The recursive call of the void */
Loading...