| Commit message (Collapse) | Author | Age | Files | Lines |
|
|
|
|
|
|
|
| |
A follow up change to parse the wide char string.
It currently only parse and store it like normal strings.
Need more change to reflect the base type and size etc.
Signed-off-by: Christopher Li <sparse@chrisli.org>
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Keep storage class (and "is it inline") explicitly in decl_state;
translate to modifiers only when we are done with parsing. That
avoids the need to separate MOD_STORAGE bits while constructing
the type (e.g. in alloc_indirect_symbol(), etc.). It also allows
to get rid of MOD_FORCE for good - instead of passing it to typename()
we pass an int * and let typename() tell whether we'd got a force-cast.
Indication of force-cast never makes it into the modifier bits at all.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Christopher Li <chrisl@hera.kernel.org>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Doing lookup_symbol() with NS_TYPEDEF will happily skip the redeclarations
of the same identifier with NS_SYMBOL. We need to check that we are not
dealing with something like
typedef int T;
void f(int T)
{
static T a; /* not a valid declaration - T is not a typedef name */
or similar (e.g. enum member shadowing a typedef, etc.).
While we are at it, microoptimize similar code in lookup_type() - instead
of sym->namespace == NS_TYPEDEF we can do sym->namespace & NS_TYPEDEF;
the former will turn into "fetch 32bit value, mask all but 9 bits, compare
with NS_TYPEDEF", the latter - "check that one bit in 32bit value is set".
We never mix NS_TYPEDEF with anything in whatever->namespace, so the
tests are equivalent.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Christopher Li <sparse@chrisli.org>
|
|
|
|
| |
Signed-off-by: Josh Triplett <josh@freedesktop.org>
|
|
|
|
|
|
|
| |
expression.h didn't work if included alone, before any other headers; fix that
by having it include the headers it needs.
Signed-off-by: Josh Triplett <josh@freedesktop.org>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Turn FORCE_MOD into storage class specifier (that's how it's
actually used and that makes for much simpler logics).
Introduce explicit EXPR_FORCE_CAST for forced casts; handle it
properly.
Kill the idiocy in get_as() (we end up picking the oddest things
for address space - e.g. if we have int __attribute__((address_space(1))) *p,
we'll get warnings about removal of address space when we do things like
(unsigned short)*p. Fixed. BTW, that had caught a bunch of very odd
bogosities in the kernel and eliminated several false positives in there.
As the result, get_as() is gone now and evaluate_cast() got simpler.
Kill the similar idiocy in handling pointer assignments; while we are at it,
fix the qualifiers check for assignments to/from void * (you can't assign
const int * to void * - qualifiers on the left side should be no less than
on the right one; for normal codepath we get that checked, but the special
case of void * skips these checks).
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
AFAICS, that should do null pointer constants right. We assign
special instance of void * (&null_ctype) to (void *)<zero integer
constant expression> and replace it with normal void * when we
don't want null pointer constant. is_zero_constant() checks if
we have an integer constant expression, does conservative expand
(i.e. instead of generating an error on 1/0, etc. leaves the
node unreplaced) and checks if we have reduced the sucker to
EXPR_VALUE[0] without comma taint.
Implemented all (AFAICS) special cases involving null pointer
constants; most changes in evaluate_compare() and evaluate_conditional().
Both are still incomplete; handling of qualifiers is still missing,
but that's a separate story.
Note that we get two new sets of warnings on the kernel build; one is
due to wrong size_t (handled in the next patch; didn't show up until
now since we didn't warn on comparison of pointers to incompatible
types) and another is a pile of warnings about integer 0 used as NULL
on
if (p == 0)
where p is a pointer. Additionally, there's an idiotic
(p>0)
in one place (again, p is a pointer). Bugger if I know how gcc doesn't
warn on that one, it's certainly a standard violation and bloody pointless
even as extension...
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
|
|
|
|
|
|
|
|
|
|
| |
Treat it as normal binary operation, taint the value, check the taint.
We can do other kind of value tainting with the same infrastructure
as well...
Review and testing would be welcome; AFAICS, it works, but...
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Hopefully correct handling of integer constant expressions. Please, review.
Rules:
* two new flags for expression: int_const_expr and float_literal.
* parser sets them by the following rules:
* EXPR_FVALUE gets float_literal
* EXPR_VALUE gets int_const_expr
* EXPR_PREOP[(] inherits from argument
* EXPR_SIZEOF, EXPR_PTRSIZEOF, EXPR_ALIGNOF get int_const_expr
* EXPR_BINOP, EXPR_COMPARE, EXPR_LOGICAL, EXPR_CONDITIONAL,
EXPR_PREOP[+,-,!,~]: get marked int_const_expr if all their
arguments are marked that way
* EXPR_CAST gets marked int_const_expr if argument is marked
that way; if argument is marked float_literal but not
int_const_expr, we get both flags set.
* EXPR_TYPE also gets marked int_const_expr (to make it DTRT
on the builtin_same_type_p() et.al.)
* EXPR_OFFSETOF gets marked int_const_expr
When we get an expression from parser, we know that having int_const_expr on
it is almost equivalent to "it's an integer constant expression". Indeed,
the only checks we still have not done are that all casts present in there
are to integer types, that expression is correctly typed and that all indices
in offsetof are integer constant expressions. That belongs to evaluate_expression()
and is easily done there.
* evaluate_expression() removes int_const_expr from some nodes:
* EXPR_BINOP, EXPR_COMPARE, EXPR_LOGICAL, EXPR_CONDITIONAL,
EXPR_PREOP: if the node is marked int_const_expr and some
of its arguments are not marked that way once we have
done evaluate_expression() on them, unmark our node.
* EXPR_IMLICIT_CAST: inherit flags from argument.
* cannibalizing nodes in *& and &* simplifications: unmark
the result.
* EXPR_CAST: unmark if we are casting not to an integer type.
Unmark if argument is not marked with int_const_expr after
evaluate_expression() on it *and* our node is not marked
float_literal (i.e. (int)0.0 is fine with us).
* EXPR_BINOP created (or cannibalizing EXPR_OFFSETOF) by
evaluation of evaluate_offsetof() get int_const_expr
if both arguments (already typechecked) have int_const_expr.
* unmark node when we declare it mistyped.
That does it - after evaluate_expression() we keep int_const_expr only if
expression was a valid integer constant expression.
Remaining issue: VLA handling. Right now sparse doesn't deal with those in
any sane way, but once we start handling their sizeof, we'll need to check
that type is constant-sized before marking EXPR_SIZEOF int_const_expr.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
|
|
|
|
| |
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
|
|
|
|
|
|
|
|
|
| |
Remaining known problems:
* size of array is still miscalculated in cases with missing braces
* expand still mishandles [0 ... 1].a et.al.
* expand still doesn't deal with overlaps correctly.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
|
|
|
|
|
|
|
|
|
|
|
| |
This removes the list of symbols for block statements, and instead makes
a declaration be a statement of its own.
This is necessary to correctly handle the case of mixed statements and
declarations correctly, since the order of declarations and statements
is meaningful.
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
|
|
|
|
|
|
| |
This is what we do for most enums, making it clear
that a zero means "uninitialized", since that easily
happens with our zeroing allocator.
|
|
|
|
|
|
|
|
|
| |
It's disgusting how intimate lib.c is with all the types,
and this is slowly trying to split things up a bit. Now
the intimate part is in allocate.c, but maybe we can get
to the point where each allocation user just declares its
own allocation strategy, and just uses the generic routines
in allocate.c
|
|
|
|
|
|
| |
Needed for pointer inc/dec. These things are all supposed to be
all set by the type evaluation phase, so that later parts don't
need to worry.
|
|
|
|
|
| |
Not only do all users want it, the list of used symbols
is not stable until after the tree has been evaluated.
|
|
|
|
|
|
|
|
|
| |
I used to think I needed it. That's no longer the case: we just
follow the "bit_offset" in the type information.
There may be cases where we inadvertently cast the information
away, and those places will break now, but that's a bug really,
not an excuse for EXPR_BITFIELD.
|
|
|
|
|
|
| |
This also makes our evaluation simplification only happen
for the implied ones. If you put an explicit cast somewhere,
it does _not_ get combined with an implied one.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
returns the size of the underlying object.
This is different from "sizeof(*expr)" for arrays, where
the array would degenerate to a pointer to one member, and
thus "sizeof(*expr)" gives the size of one entry in the
array.
Why do this? It's useful for things like
#define memset(a,b,c) ({ \
(void) __builtin_warning(__sizeof_ptr__(a) > 1, __sizeof_ptr__(a) != (c), "check memset size"); \
memset(a, b, c); })
where we really want to check the size of the object we're
doing the "memset()" on, but the regular sizeof() just doesn't
cut it.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
positional markers be hierarchical rather than a flat list.
This makes the data structure a bit more complex, but it simplifies
some of the code, and makes it possible to evaluate complex initializers
without going insane.
In particular, we how support
struct xxxx var = {
.a.b[10] = 1;
};
which we couldn't handle at all before (it had to
be written as
struct xxxx var = {
.a = {
.b = { [10] = 1; }
}
}
or similar.
The new code changes all array indexes and structure members
to EXPR_POS expressions offset from the "outer" scope (either
start of the symbol, or an outer EXPR_POS).
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Handling of non-lvalue compound objects:
We introduce a new primitive - EXPR_SLICE. Meaning is "that many bits
from that offset in that non-lvalue struct or union". It is used when
we try to get a member out of a non-lvalue struct or union (subsequent .<field>
just narrow the slice). And as far as scalar, struct and union fields count,
that's it. The only subtle point is handling of array fields. And there
I'm doing what C99 requires - they *do* decay to real, honest pointers,
causing a copy of object to memory if needed. We get an anonymous object
that lives until the next sequence point; optimizer is certainly free to
get rid of it completely if it can make do with the value we'd copied there.
Note that you _are_ allowed to say
foo().a[1] = 0;
It doesn't make sense, since the value you've assigned will be immediately
lost (and any optimizer will turn that into f()), but it is legitimate and
it avoids a *lot* of PITA in describing semantics.
It covers only array decay - any other member of non-lvalue struct or union
is *not* an lvalue and in
struct foo {int x; int y[2];};
struct foo a(void);
...
a().x = 0; /* not allowed, non-lvalue */
a().y[0] = 1; /* allowed, but pointless */
you will get an error from the first assignment, but not from the second
one.
Signed-off-by: Al Viro <viro@parcelfarce.linux.org.uk>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
|
|
|
|
|
| |
Make linearize.h show the right ops for the logical (as opposed to
binary) and/or EXPR_BINOP.
|
|
|
|
|
|
|
|
|
| |
expression.
This is just a very high-level cost, mainly distinguishing
between "safe" and "unsafe" operations, so that we can
determine if we can turn a C conditional into a select
statement, or a logical op into one without short-ciruiting.
|
|
|
|
|
|
| |
It's the same as a regular C conditional, except you could
evaluate both sides first. Right now we treat it exactly
the same as an EXPR_CONDITIONAL.
|
|
|
|
| |
FP handling added, everything straightforward by now.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
This teaches sparse what __alignof__ really means, instead of just using
the same code as "__sizeof__"
It gets rid of the warnings in ebtables that does:
struct ebt_entries {
...
char data[0] __attribute__ ((aligned (__alignof__(struct ebt_replace)));
};
Which caused warning because sparse was evaluating __alignof__ as the same as sizeof,
and sizeof was 57 (ie non-power of 2).
This is just based on the existing code and a peek at the data
structures in expression and symbol.
|
|
|
|
|
|
|
|
|
|
| |
comparisons etc:
if (typeof(a) == int) {
...
(although right now I don't actually do the proper comparison
expansion and all comparisons return "true").
|
|
|
|
|
|
|
|
| |
to look up types.
This makes up get the proper nesting characteristics
in case you mix typedefs and regular symbols with the
same name.
|
|
|
|
|
|
| |
This doesn't actually get them _right_, but as long as they
end up being constant when used, we at least silently ignore
them until then.
|
|
|
|
| |
isn't the sole copyright owner these days.
|
|
|
|
|
|
|
|
|
|
| |
in order to see NULL pointer expressions immediately.
We want NULL pointers to be visible as such at type check time,
long before we do the full expansion/simplification phase.
A NULL pointer is a weaker type than a normal (void *), since
it has no context or address space associated with it, for example.
|
|
|
|
|
|
|
|
|
|
| |
does type evaluation, the second one does value evaluation
and inline expansion.
This has the advantage that by the time we do value evaluation
and inline expansion, we have traversed the tree fully once,
which allows us to take advantage of function-global information,
ie we know whether symbols have ever been accessed etc.
|
|
|
|
|
|
| |
This patch removes the type-names on the anonymous structures. This
fixes compilation when using gcc-3.3 (Debian). Credit for identifying
the fix goes to Arnaldo Carvalho de Melo <acme@conectiva.com.br>.
|
|
|
|
|
|
|
|
| |
(&&label) and computed goto (goto *expr).
Add label ctype for __label__ identifier. This is still quite broken
(it should create a block-symbol in the NS_LABEL namespace, right now
it creates a regular symbol).
|
|
|
|
|
| |
not evaluation. We have nasty recursion issues otherwise.
|
|
|
|
| |
preparing for a public release.
|
|
|
|
|
|
|
|
| |
the initializer expression list as EXPR_POS expressions so
that a back-end can DTRT.
Show complex initializers now that we've calculated the offsets
of the expressions.
|
|
|
|
|
|
| |
Use the "used_list" to build up the symbol tree, so that we
automatically get new symbols that get discovered during
evaluation.
|
|
|
|
|
|
|
|
|
|
| |
Make the pre-processor use the expression evaluator, so that
it actually gets all the signed/unsigned comparisons right
etc.
Make logical expressions an expression type of their own.
They have some very special behaviour both type-wise and
evaluation-wise (the short-circuiting thing).
|
| |
|
|
|
|
| |
the real one when it goes out the door.
|
|
|
|
|
|
| |
(or NULL) rather than just 1 (or 0).
Make "examine_symbol_type()" follow 'typeof's, and return the result.
|
|
|
|
|
|
| |
expressions, post-op expressions.
Move some of the evaluation functions from test-parsing.c to evaluate.c
|
|
|
|
|
|
|
|
| |
Now constant expressions (strings, integers and fp constants)
are evaluated at parse-time into the proper EXPR_xxx type.
Remove "struct token" from "struct statement", which really only
wanted to know the position. So replace it with "struct position".
|
|
|
|
| |
type discovery (initializers are not independent expressions).
|
|
|
|
| |
add them to the parse tree. We now do.
|
|
|
|
| |
and evaluate their type to be arrays of char rather than just a pointer.
|
| |
|
|
|
|
|
|
|
| |
to it, instead of having everybody have pointers to "struct token"
only because they wanted to have the position.
Fix array addition type degeneration.
|
|
|
|
|
|
| |
so that a EXPR_VALUE expression never contains extra bits that
won't be used. It's just less confusing that way (but realize that
we always keep the value unsigned, even if the _type_ is signed).
|