Re: fun with ?:

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Tue, May 22, 2007 at 06:03:31PM -0700, Josh Triplett wrote:
> > Usual sparse constant folding is _almost_ OK, provided that we play a bit
> > with evaluate_expression() and let it decide if subexpression is an integer
> > constant expression.  No prototype changes, we just get a global flag
> > and save/restore it around sizeof argument handling and several other
> > places.  It's actually pretty easy.  And if we get "it is an integer
> > constant expression", well, then caller can call expand stuff.
> 
> Sounds reasonable to me.  Possibly better written as some kind of generic
> parse-tree-walking operation, but this approach should work fine.

Hrm...  Actually, "global flag" approach doesn't work at all, since we
mishandle already-evaluated subtrees (happens with inlined functions).

AFAICS, here's what we can do with relatively little PITA:

	Split some of the EXPR_... cases in two; additional variant
would differ by | EXPR_INT_CONST, which would be 1U<<31 (let's call it
i-bit).  EXPR_CAST gets split in three - normal, EXPR_CAST with i-bit
and EXPR_CAST with f-bit (1U<<30).

At parse time, do the following:
	* EXPR_VALUE, EXPR_TYPE, EXPR_SIZEOF, EXPR_PTRSIZEOF and EXPR_ALIGNOF
get i-bit.
	* EXPR_COMPARE, EXPR_BINOP, EXPR_LOGICAL, EXPR_CONDITIONAL,
EXPR_PREOP with !, + , -, ~ or ( and EXPR_CAST get i-bit if all their
arguments have it.
	* EXPR_CAST also gets both i- and f-bit if its argument is EXPR_FVALUE,
possibly wrapped into some EXPR_PREOP[(].

That won't really complicate the parser.  Now, at that point i-bit
is weaker than "subexpression is an integer constant expression", but not
by much - the only things we are missing are "it typechecks OK" and "all
casts are to integer types" (note that sizeof(VLA) would have to be caught
when we start handling those; as it is, it fails typechecking, plain and
simple).

So what we do at evaluate_expression() is simple - we remove some i-bits.
Rules:
	* EXPR_COMPARE, EXPR_BINOP, EXPR_LOGICAL, EXPR_CONDITIONAL, EXPR_PREOP:
lose i-bit if some argument doesn't have it after evaluation.
	* EXPR_IMPLIED_CAST to an integer type inherits i-bit from argument.
	* EXPR_CAST loses i-bit if the type we are casting to is not an
integer one; it also loses i-bit if evaluated argument doesn't have i-bit
*and* EXPR_CAST itself doesn't have f-bit.
	* in cannibalizing EXPR_PREOP in &*p and *&p simplifications,
keep the (lack of) i-bit and f-bit on the overwritten node.

In expand_expression() we keep i-bit through the replacement.

That's it.  Now, "has i-bit after evaluate_expression()" == "expression
is an integer constant one".

Now, we do the following:
	* static struct symbol null_ctype, initialized to SYM_PTR over
void.
	* evaluation of EXPR_CAST with target type being a pointer to void
and argument bearing an i-bit should check if argument is in fact 0; if
it is, replace the node with EXPR_VALUE[0] and &null_ctype as type.
	* int is_null_pointer_constant(expr) - return 1 if type is &null_ctype,
2 if argument bears i-bit and is in fact 0, return 0 otherwise.
	* have degenerate() turn &null_ctype into a normal pointer to void
	* callers of degenerate() in contexts where we care about null
pointer constants (?:, assignment, argument of function call, pointer
comparison, cast) should do is_null_pointer_constant() first.  Act accordingly,
warn if it had returned 2.  Note that we can't blindly generate a warning
in is_null_pointer_constant() - sometimes 0 is simply 0 and we don't want it
to become a pointer at all, let alone generate any warnings.

AFAICS, that will do the right thing with little pain.  I'm not all that
happy about splitting EXPR_... (in effect, stealing bit from expr->type);
perhaps reducing the size of expr->type and adding expr->flags would be
better.  Hell knows...

Comments?
-
To unsubscribe from this list: send the line "unsubscribe linux-sparse" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Newbies FAQ]     [LKML]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Trinity Fuzzer Tool]

  Powered by Linux