| Age | Commit message (Collapse) | Author | Files | Lines |
|
Examination of a pointer type doesn't examine the corresponding
base type (this base type may not yet be complete). So, this
examination must be done later, when the base type is needed.
However, in some cases it's possible to call evaluate_dereference()
while the base type is still unexamined.
Fix this by adding the missing examine_symbol_type() on the base type.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Expressions involving the logical-not '!' does not
call degenerate().
Since the result type is always 'int' and thus independent
of the expression being negated, this has no effect on the
type-checking but the linearization is wrong.
For example, code like:
int foo(void)
{
if (!arr) return 1;
return 0;
}
generates:
foo:
load %r6 <- 0[arr]
seteq.32 %r7 <- VOID, $0
ret.32 %r7
The 'load' being obviously wrong.
Fix this by adding the missing degenerate().
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
'fix-volatile-simplification', 'struct-asm-ops', 'restricted-pointers', 'fix-f2i-casts', 'symaddr-description', 'flush-stdout' and 'diet-simple' into tip
|
|
This is slightly shorter (and thus may avoid long lines) and
facilitate the introduction of MOD_RETRICT in a later patch.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
ASM operands have the following syntax:
[<ident>] "<constraint>" '(' <expr> ')'
For some reasons, during parsing this is stored
as a sequence of 3 expressions. This has some serious
disadvantages though:
- <ident> has not the type of an expression
- it complicates processing when compared to having a specific
struct for it (need to loop & maintain some state).
- <ident> is optional and stored as a null pointer when not present
which is annoying, for example, if null pointers are used internally
in ptr-lists to mark removed pointers.
Fix this by using a specific structure to store the 3 elements
of ASM operands.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
|
|
Conditional expressions whose second & third operands
have non-compatible types are not conform to the C standard
and sparse emit a warning for them and return the expression
as being erroneous. In consequence, such expressions are not
given a type. This, in turn, makes that some further processing
cannot be done (correctly).
It seems that neither GCC nor clang emit a warning when
there is a type mismatch but the condition is a constant.
In the case we're interested here (the slow compilation of a file)
the operation that cannot be done is the expansion its operands.
This, in turn and among other things, makes that builtins like
__builtin_constant_p() are not evaluated with disatrous consequence
for the amount of work done in the next phases.
Fix this by giving to conditional expressions with constant
condition the same type as the operand selected by the conditional
(but keeping the warning) as GCC & clang seems to do.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
sparse use lazy type evaluation. This evaluation is done
via the examine_*() functions, which we must insure
to have been called when type information is needed.
However, it seems that this is not done for expressions
with multiple level of dereferencing. There is (at least)
two symptoms:
1) When the inner expression is complex and contains a
typeof: a bogus error message is issued, either
"error: internal error: bad type in derived(11)" or
"error: cannot dereference this type", sometimes followed
by another bogus "warning: unknown expression (...)".
2) This one is only visible with test-linearize but happen
even on a plain double deref: the result of the inner
deref is typeless.
Obviously the first symptom is a consequence of the second one.
Fix this by adding a call to examine_symbol_type() at the
beginning of evaluate_dereference().
Note: This fixes all the 17 "cannot dereference" and 19
"internal error" present on the Linux kernel while using
sparse on a x86-64 allyesconfig (most coming from the call
of rcu_dereference_sched() in cpufreq_update_util()).
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
'implicit-int', 'cgcc-darwin' and 'more-builtin-decls' into rc2
|
|
Currently, once an error is issued, warnings are no more
issued, only others errors are.
It make sense as once an error is encountered things can
be left in an incoherent state and could cause lots of
useless warnings because of this incoherence.
However, it's also quite annoying as even unrelated warnings
are so silenced and potential bugs stay thus hidden.
Fix this by:
- use a specific flag for this: 'has_error'
- make the distinction between the current phase and some previous
phases (but for now we only care about parsing vs evaluation)
- if an error has been issued in a previous phase (at parsing)
warnings are suppressed for the current phase and all future
phases
- if an error is issued in the current phase (evaluation) the
flag is reset after each functions/symbols
For example, with this patch, a typing error in function fa()
will not suppress warnings for function fb(), while a parsing
error will still inhibit all further warnings.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
'fix-missing-reload', 'fix-insert-branch', 'fix-NULL-type', 'testsuite-clean', 'fix-bitfield-init-v3' and 'fdump-linearize' into tip
* fix missing reload
* fix boolean context for OP_AND_BOOL & OP_OR_BOOL
* fix bitfields implicit zero initializer.
* fix: kill old branch in insert_branch()
* returns the correct type when evaluating NULL
* use internal size for __INT_MAX__ & friends
* testsuite: cleanup result files
* add support for '-fdump-linearize[=only]'
* add support for '-fmem-report'
* add support for '-dD'
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Conversion to bool is special in C since this conversion
is essentially the result of the comparison with zero.
As such, some operations which are normally unsafe to
do with restricted types, like casting to an unrestricted
type, are in fact safe to do when converting to bool
and issuing a warning in those case is useless, confusing
and causes people to add useless casts in the code in
order to shut up the warning.
Fix this by catching explicit 'bool <- restricted type' casts
and not emit a warning like for others casts of restricted
type to non-restrictes ones.
Based-on-patch-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
In evaluate_cast(), the expression '(void*)<some zero constant>',
aka 'NULL', is detected and given the type 'null_ctype',
a special kind of pointer type.
However the returned type is the original one: 'void *'.
This doesn't seem to be intented as in all other cases, the
evaluate_...() functions and ultimately evaluate_expression()
always return the type of the expression.
Fix this by returning the type given to the expression: null_ctype.
Reported-by: Dibyendu Majumdar <mobile@majumdar.org.uk>
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Conversion to bool is special in C since this conversion
is essentially the result of the comparison with zero.
As such, some operations which are normally unsafe to
do with restricted types, like casting to an unrestricted
type, are in fact safe to do when converting to bool
and issuing a warning in those case is useless, confusing
and causes people to add useless casts in the code in
order to shut up the warning.
Fix this by catching such 'bool <- restricted type' conversion
and avoid such warnings.
CC: Al Viro <viro@zeniv.linux.org.uk>
Originally-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Evaluating the return type of a function is a bit complicated.
For user-defined functions this is done inside evaluate_call()
but for builtin function which have an ->evaluate() method it's
this method that must set it. That's quite easy if the return
type is fixed, like 'int' for example, but less so for genearic
functions or when we simply want to keep the given by the
prototype.
To make things more easy for the last case, set by default
the return type as given by the corresponding symbol (the
prototype thus) *before* calling the evaluate method.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
In evaluate_call(), argumenst are evaluated an a diagnostic
is emitted if the number of args is not what is expected.
Good.
However, the processing continues nevertheless.
If too much args were given, this doesn't matter much
but if too few are given we need to check a bit everywhere
for possible NULL args.
Avoid this by returning early an error if there was too few
arguments.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
The expression parsing code builds an EXPR_COMPARE expression around two
EXPR_TYPE expressions for __builtin_types_compatible_p().
The EXPR_TYPE expressions are tagged as being integer constant expressions
in order to trick the generic comparison evaluation code into flagging the
result as an integer constant expression again.
Avoid this trickery by making evaluate_compare() unconditionally tag a
comparison between types as an integer constant expression.
Signed-off-by: Nicolai Stange <nicstange@gmail.com>
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Toplevel compound literals have got static storage duration
[6.5.2.5(6)].
This implies that
1. their addresses are address constants [6.6(9)] and
2. their initializers must contain constant expressions only
[6.5.2.5(3), 6.7.8(4)] .
Flag the anonymous symbol created at expression parsing time as having
static storage duration if the compound literal occurs at top level
scope.
Flag the whole expression as being an address constant at evaluation
time if its corresponding anonymous symbol had been previously marked
as having static storage duration.
Signed-off-by: Nicolai Stange <nicstange@gmail.com>
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
The official constraints on constant expressions [6.6] are insanely
strict in that they do not allow some constructs commonly used in the
wild.
Relax them by treating
- address constants cast to different pointer type as address constants
again,
- address constants cast to arithmetic type as arithmetic constant
expressions
- conditional expressions whose true and false branches both yield
address constants as address constants,
- and conditional expressions whose condition is an address constant
as an constant expression to the extent their true and false branches
allow.
Signed-off-by: Nicolai Stange <nicstange@gmail.com>
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Currently, the determination of a __builtin_offsetof() expressions'
constness flags is done in two steps:
- Several flags are speculatively set at expression parsing time
- and possibly cleared again at evaluation if the member expression
includes a non-const array index like in
__builtin_offsetof(struct A, a.b[non_const_foo])
For consistency with other expression types' evaluation, defer the
determination of a __builtin_offsetof() expression's constness to
evaluation time, too.
Furthermore, carry an array index expression's constness flags
through the implicit cast to size_t type.
Signed-off-by: Nicolai Stange <nicstange@gmail.com>
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Introduce support for recognizing string literals as address constants.
Make evaluate_string() unconditionally tag the *-preop wrapped symbol
expression as being an address constant.
Signed-off-by: Nicolai Stange <nicstange@gmail.com>
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
According to 6.6(9), the member access operators "." and "->" may be used
in the creation of address constants.
Uses of both operators amount to the creation of EXPR_DEREF expressions
which are eventually fed into evaluate_offset() at evaluation.
Make evaluate_offset() propagate any address constant flag of the object
containing the referenced member to the newly created pointer addition
expression.
Signed-off-by: Nicolai Stange <nicstange@gmail.com>
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
An address constant +/- an integer constant expression qualifies as an
address constant again.
Furthermore, the array-subscript operator "[]" may be used in the creation
of address constant.
Handle both cases by making evaluate_ptr_add() check whether an integer
constant expression is added to an address constant and tag the result as
being an address constant again if so.
Signed-off-by: Nicolai Stange <nicstange@gmail.com>
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
According to 6.6(9), an address constant may get created by casting
an integer constant to pointer type.
Make evaluate_cast() handle this case, that is tag a cast expression
as being an address constant if the target is a integer constant and
the destination is of pointer type.
Signed-off-by: Nicolai Stange <nicstange@gmail.com>
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Introduce support for recognizing address constants created either
- explicitly by referencing a static storage duration object by means
of the unary & operator,
- implicitly by the use of an expression of array or function type.
Initially tag an expression as being an address constant at the primary
expression level, i.e. upon encountering a symbol designating an object of
static storage duration in primary_expression().
Carry the address constant flag over to the *-preop wrapped expression
created by evaluate_symbol_expression().
When dereferencing such a *-preop wrapped expression, make
evaluate_addressof() keep any address constant flag for the unwrapped
expression.
Signed-off-by: Nicolai Stange <nicstange@gmail.com>
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Initializers of static storage duration objects shall be constant
expressions [6.7.8(4)].
Warn if that requirement is not met and the -Wstatic-initializer-not-const
flag has been given on sparse's command line.
Identify static storage duration objects by having either of
MOD_TOPLEVEL or MOD_STATIC set.
Check an initializer's constness at the lowest possible subobject
level, i.e. at the level of the "assignment-expression" production
in [6.7.8].
Signed-off-by: Nicolai Stange <nicstange@gmail.com>
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
This is a preparatory step for checking the constness
of initializers of static storage duration objects;
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
This function, with a quite long name, not only handle
simple initializer but also complex ones.
So, rename it to the shorter and more correct form.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Address constants [6.6(9)] constitute one of the types of constant
expressions allowed in initializers [6.6(7)] for static storage
duration objects [6.7.8(4)].
Introduce a new flag for tagging expressions which qualify as
being an address constant.
Make sure not to carry over the address constant attribute from
subexpressions for operators that never yield address constants,
i.e. most arithmetic ones, logical ones etc.
Signed-off-by: Nicolai Stange <nicstange@gmail.com>
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Move the whole calculation of conditional expressions' constness flags
to the evaluation phase such that expressions like
0 ? __builtin_choose_expr(0, 0, 0) : 0
0 ? 0 : __builtin_choose_expr(0, 0, 0)
can now be recognized as qualifying as integer constant expressions.
Signed-off-by: Nicolai Stange <nicstange@gmail.com>
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Move the whole calculation of prefix expressions' constness flags to
the evaluation phase such that expressions like
-__builtin_choose_expr(0, 0, 0)
~__builtin_choose_expr(0, 0, 0)
!__builtin_choose_expr(0, 0, 0)
can now be recognized as qualifying as integer constant expressions.
Signed-off-by: Nicolai Stange <nicstange@gmail.com>
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Move the whole calculation of binary operations', compare and logical
expressions' constness flags to the evaluation phase such that expressions
like
0 + __builtin_choose_expr(0, 0, 0)
0 < __builtin_choose_expr(0, 0, 0)
0 && __builtin_choose_expr(0, 0, 0)
can now be recognized as qualifying as integer constant expressions.
Signed-off-by: Nicolai Stange <nicstange@gmail.com>
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Move the whole calculation of cast expressions' constness flags to the
evaluation phase such that expressions like
(int)__builtin_choose_expr(0, 0, 0)
can now be recognized as qualifying as integer constant expressions.
Signed-off-by: Nicolai Stange <nicstange@gmail.com>
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Even if sparse attempted to verify that initializers for static storage
duration objects are constant expressions [6.7.8(4)] (which it
currently does not), it could not tell reliably.
Example:
enum { b = 0 };
static void *c = { (void*)b }; /* disallowed by C99 */
References to enum members are not allowed in address constants [6.6(9)]
and thus, the initializer is not a constant expression at all.
Prepare for a more fine-grained tracking of expression constness in the
sense of C99 [6.4.4, 6.6].
Introduce a broader set of constness tracking flags, resembling the
four types of primary expression constants [6.4.4] (integer, floating,
enumeration, character). Define helper macros to consistently set and
clear these flags as they are not completely independent.
In particular, introduce the following flags for tagging expression constness
at the level of primary expressions:
- CEF_INT: integer constant, i.e. literal
- CEF_FLOAT: floating point constant (former Float_literal flag)
- CEF_ENUM: enumeration constant
- CEF_CHAR: character constant
Introduce the CEF_ICE flag meant for tagging integer constant
expressions. It is equivalent to the former Int_const_expr flag.
Note that CEF_INT, CEF_ENUM and CEF_CHAR flags imply CEF_ICE being set.
Signed-off-by: Nicolai Stange <nicstange@gmail.com>
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Functions and arrays degenerate as pointers in most context
but this wasn't done in the case of conditionals.
As a result the value of the conditional after linearization
was invalid.
Fix this by calling degenerate() in evaluate_conditional().
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Testing the address of an array is quite suspicious:
it's most probably the sign of an error somewhere.
Furthermore, such uses always evaluate to true.
So, add a warning about such use (but only if -Waddress was given).
|
|
Testing the address of a function is quite suspicious:
it's most probably the sign of an error somewhere.
Furthermore, such uses always evaluate to true.
So, add a warning about such use (but only if -Waddress was given).
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
If the operand of a cast to a restricted type is an unrestricted value,
the cast should not produce a warning, since an equivalent implied cast
(e.g. in an initialiser) would not do so.
Also adds a test case (bitwise-cast.c) testing implicit and explicit
conversions of zero and nonzero integers to bitwise type.
Signed-off-by: Edward Cree <ecree@solarflare.com>
Acked-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
Tested-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
Signed-off-by: Christopher Li <sparse@chrisli.org>
|
|
This wasn't done yet, in particular void values was accepted
inside if statements, which lead to strange situations after
linearization.
Implement this simply by calling the newly created is_scalar_type()
in evaluate_conditional() and issuing an appropriate diagnostic
when the check fail.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
Signed-off-by: Christopher Li <sparse@chrisli.org>
|
|
Section 6.3.1.2 of the C standard requires that cast to bool
to be done differently than casting to others integer types:
The casted value need to be compared against '0',
if it compares equal the result is 0, otherwise the result is 1.
But currently, it's treated as the others integer casts: the value is
truncated, keeping only the least significant bit.
For example, when using test-linearize on the following code:
_Bool foo(int a) { return (_Bool) a; }
this instruction is emitted:
scast.1 %r2 <- (32) %arg1
while the correct one is:
setne.1 %r2 <- %arg1, $0
Fix this for explicit and implicit casts.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
Signed-off-by: Christopher Li <sparse@chrisli.org>
|
|
A compound assignment like, for example:
x /= a;
should have the same effect as the operation followed by the
assignment except that the left side should only be evaluated
once. So the statement above (assuming 'x' free of side-effects)
should have the same effect as:
x = x / a;
In particular, the usual conversions should applied. So, if the
type of 'x' and 'a' is, respectively, 'unsigned int' (32 bit) and
'long' (64 bit), the statement above should be equivalent to:
x = (unsigned int) ((long) x / a);
But what is really done currently is something like:
x = x / (unsigned int) a;
In other words, the right-hand side is casted to the same type as the
lhs and the operation is always done with this type, neglecting the
usual conversions and thus forcing the operation to always be done
with the lhs type, here 'unsigned int' instead of 'long'.
For example, with the values:
unsigned int x = 1;
long a = -1;
We have:
x = 1 / (unsigned int) (-1L);
x = 1 / 0xffffffff;
x = 0;
instead of the expected:
x = (unsigned int) ((long)1 / -1L);
x = (unsigned int) (-1L);
x = 0xffffffff;
The patch fix this by first calculating the type corresponding to
the usual conversion and then casting the right-hand side to this
type, which is fine since it's a rvalue anyway.
Later steps will then use the rhs type when doing the operation.
On the example above, the cast will be a no-op and the operation will
be done with the correct type:
x = x / (long) a;
which, at linearization, will become:
x = (unsigned int) ((long) x / (long) a);
and with unneeded casts optimized away:
x = (unsigned int) ((long) x / a);
Which will give us the expected result.
If the types where in the other order, the result will also be done
with the correct type:
long x;
unsigned int a;
...
x /= a;
will become:
x = x / (long) a;
and, at linearization:
x = (long) ((long) x / (long) a);
and with unneeded casts optimized away:
x = (x / (long) a);
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: Ramsay Jones <ramsay@ramsayjones.plus.com>
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
Signed-off-by: Christopher Li <sparse@chrisli.org>
|
|
Following some previous simplification done on the function,
the variable 'orig_type' is now always the same as 'type'.
To avoid possible confusion, only use 'type' and remove
the declaration of 'orig_type'.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
Signed-off-by: Christopher Li <sparse@chrisli.org>
|
|
Was slightly confusing when reading some code.
Better to remove it.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
Signed-off-by: Christopher Li <sparse@chrisli.org>
|
|
When doing a type comparison between functions, in the varidicity part,
the base type of these functions (= their return type) is
wrongly used intead of their own type.
Fix this and add some tests showing this and others cases are
now OK
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
CC: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Christopher Li <sparse@chrisli.org>
|
|
The pure attribute only take effect in function node.
There is no way to make a value itself pure.
Reported-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Signed-off-by: Christopher Li <sparse@chrisli.org>
|
|
I miss a spot when converting array size caculation using
array_element_offet(). "next_designators()" is still using
"n*bit_size" to caculate the element offset. It is wrong
for the case of bool array.
Signed-off-by: Christopher Li <sparse@chrisli.org>
|
|
This code snippet:
static void bar(void const *arg)
{
int (*foo)(void) = arg;
}
produces the following warning:
test.c:4:28: warning: incorrect type in initializer (different modifiers)
test.c:4:28: expected int ( *foo )( ... )
test.c:4:28: got void const *arg
which is caused by the fact that the function pointer 'foo' is not annotated
as being a pointer to const data. However, dereferencing a function pointer
does not produce an lvalue, so a function pointer points to const data by
definition, and we should treat it accordingly.
To avoid producing a warning on the inverse case, i.e.,
static void bar(void)
{
void *foo = bar;
}
we only address the case where the function pointer is the target of
an assignment.
Reviewed-by: Josh Triplett <josh@joshtriplett.org>
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Signed-off-by: Christopher Li <sparse@chrisli.org>
|
|
The "trivial fix" is to just save off the offset in check_designators
(add a new field to the "EXPR_IDENTIFIER" part of "struct expression"
and then pick up that offset in "convert_ident()"
However, that has exactly the same issue with the whole fake
EXPR_IDENTIFIER created by "next_designators()". Now we need to
initialize the offset field there too. And, for the same reason as
before, the field that "next_designator()" picks may not *have* an
identifier, because the next designator may in fact be an anonymous
union.
Anyway, with all that said, maybe this really confusing and hacky
patch would work. It passes my tests. The magic offset calculation in
next_designators() has a big comment about what the heck it is doing,
and otherwise it's a fairly straightforward case of "save offset from
check_designators() time to be used by convert_ident()".
My stupid test-case is this incredibly hacky thing:
struct A {
int aa;
int bb;
};
struct S {
int a;
union {
int b;
int c;
} u[10];
int dummy;
union {
int d;
int e;
};
};
int fn(void)
{
struct S s = {
.a = 1,
.u[2].b = 2,
.dummy = 1,
{ 3 }
};
return s.dummy*1000 + s.d*100 + s.u[2].b*10 + s.a; // 1321
}
where I use "./test-linearize" to verify that the initializer layout
matches the code generation layout (so that 'fn' function *should*
linearize to just a simple "ret.32 $1321", and with this patch it
does).
But I bet this misses some case. However, the current state wrt
initializer offsets really is very broken, so maybe it's ok.
Signed-off-by: Christopher Li <sparse@chrisli.org>
|
|
When layout the array element, the element size should
round up to byte align.
Signed-off-by: Christopher Li <sparse@chrisli.org>
|
|
Ok, this fixes the warning, but we seem to still mess up the actual
initializer. It looks like some later phase gets the offset wrong, so
when we lay things out in memory, we'll put things at offset zero
(which is right for your test-case, but not if there was something
before that anonymous union).
Regardless, that only matters for real code generation, not for using
sparse as a semantic checker, so this patch is correct and is an
improvement.
Reported-by: Hans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Christopher Li <sparse@chrisli.org>
|
|
Noticed this while looking at an independent bug reported by Hans
Verkuil.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Reviewed-by: Josh Triplett <josh@joshtriplett.org>
Signed-off-by: Christopher Li <sparse@chrisli.org>
|
|
This stops warnings in code using socket operations with a modern glibc,
which otherwise result in warnings of the form:
warning: incorrect type in argument 2 (invalid types)
expected union __CONST_SOCKADDR_ARG [usertype] __addr
got struct sockaddr *<noident>
Since transparent unions are only applicable to function arguments, we
create a new function to check that the types are compatible
specifically in this context.
Also change the wording of the existing warning slightly since sparse
does now support them. The warning is left in case people want to avoid
using transparent unions.
Signed-off-by: John Keeping <john@keeping.me.uk>
Signed-off-by: Christopher Li <sparse@chrisli.org>
|
|
This will allow us to reuse the logic when processing a transparent
union by checking each member in turn without printing a warning unless
none of the members match.
Signed-off-by: John Keeping <john@keeping.me.uk>
Signed-off-by: Christopher Li <sparse@chrisli.org>
|
|
Allow an override to emit or not the sizeof(bool) warning.
Add a "-Wsizeof-bool" description to the manpage.
Signed-off-by: Joe Perches <joe@perches.com>
Reviewed-by: Josh Triplett <josh@joshtriplett.org>
Signed-off-by: Christopher Li <sparse@chrisli.org>
|
|
The comparison in same_cast_type only checked the bit_size of the new and the
old symbol. The bit_offset was only compared with itself and thus would always
be true. Instead Linus most likely wanted to compare the bit_offset of the new
and the old symbol. This regression was introduced in
47f53396a1d62719c44941f84370ead80181728e ("If two implied casts end up undoing
each other, just remove them.").
Reported-by: James Westby <jw+debian@jameswestby.net>
Signed-off-by: Franz Schrober <franzschrober@yahoo.de>
Signed-off-by: Christopher Li <sparse@chrisli.org>
|
|
The old code was relicensed by Novafora Corporation, successor in interest to
Transmeta Corporation, in 2009. Other authors were also asked about the change
of their contributions to the MIT license and all with copyrightable changes
agreed to it.
Signed-off-by: Franz Schrober <franzschrober@yahoo.de>
Acked-by: Adam DiCarlo <adam@bikko.org>
Acked-by: Al Viro <viro@ZenIV.linux.org.uk>
Acked-by: Alberto Bertogli <albertito@blitiri.com.ar>
Acked-by: Alecs King <alecs@perlchina.org>
Acked-by: Alexander Shishkin <alexander.shishckin@gmail.com>
Acked-by: Alexey Dobriyan <adobriyan@gmail.com>
Acked-by: Alexey Zaytsev <alexey.zaytsev@gmail.com>
Acked-by: Andries E. Brouwer <Andries.Brouwer@cwi.nl>
Acked-by: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
Acked-by: Atsushi Nemoto <anemo@mba.ocn.ne.jp>
Acked-by: Ben Pfaff <blp@nicira.com>
Acked-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Acked-by: Bernd Petrovitsch <bernd@petrovitsch.priv.at>
Acked-by: Bernhard Reutner-Fischer <rep.dot.nop@gmail.com>
Acked-by: Blue Swirl <blauwirbel@gmail.com>
Acked-by: Chris Forbes <chrisf@ijw.co.nz>
Acked-by: Chris Wedgwood <cw@f00f.org>
Acked-by: Christopher Li <sparse@chrisli.org>
Acked-by: Damien Lespiau <damien.lespiau@gmail.com>
Acked-by: Dan Carpenter <error27@gmail.com>
Acked-by: Dan McGee <dan@archlinux.org>
Acked-by: Daniel De Graaf <danieldegraaf@gmail.com>
Acked-by: Daniel Sheridan <dan.sheridan@postman.org.uk>
Acked-by: Dave Jones <davej@redhat.com>
Acked-by: David Given <dg@cowlark.com>
Acked-by: David Miller <davem@redhat.com>
Acked-by: David Mosberger-Tang <dmosberger@gmail.com>
Acked-by: David Olien <David.Olien@lsi.com>
Acked-by: Diego Elio Pettenò <flameeyes@flameeyes.eu>
Acked-by: Emil Medve <Emilian.Medve@Freescale.com>
Acked-by: Ethan Jackson <jacksone@nicira.com>
Acked-by: Florian Fainelli <f.fainelli@gmail.com>
Acked-by: Frank Zago <fzago@systemfabricworks.com>
Acked-by: Frederic Crozat <fcrozat@suse.com>
Acked-by: Geoff Johnstone <geoff.johnstone@gmail.com>
Acked-by: Hannes Eder <hannes@hanneseder.net>
Acked-by: Jan Pokorný <pokorny_jan@seznam.cz>
Acked-by: Jeff Garzik <jgarzik@redhat.com>
Acked-by: Jiri Slaby <jslaby@suse.cz>
Acked-by: Joe Perches <joe@perches.com>
Acked-by: Joel Soete <rubisher@scarlet.be>
Acked-by: Johannes Berg <johannes@sipsolutions.net>
Acked-by: Jonathan Neuschäfer <j.neuschaefer@gmx.net>
Acked-by: Josh Triplett <josh@kernel.org>
Acked-by: Kamil Dudka <kdudka@redhat.com>
Acked-by: Kim Phillips <kim.phillips@linaro.org>
Acked-by: KOSAKI Motohiro <kosaki.motohiro@gmail.com>
Acked-by: Kovarththanan Rajaratnam <kovarththanan.rajaratnam@gmail.com>
Acked-by: Linus Torvalds <torvalds@linux-foundation.org>
Acked-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
Acked-by: Martin Nagy <nagy.martin@gmail.com>
Acked-by: Masatake YAMATO <yamato@redhat.com>
Acked-by: Mauro Dreissig <mukadr@gmail.com>
Acked-by: Michael Büsch <m@bues.ch>
Acked-by: Michael Stefaniuc <mstefani@redhat.com>
Acked-by: Michael S. Tsirkin <mst@redhat.com>
Acked-by: Mika Kukkonen <mikukkon@iki.fi>
Acked-by: Mike Frysinger <vapier@gentoo.org>
Acked-by: Mitesh Shah <Mitesh.Shah@synopsys.com>
Acked-by: Morten Welinder <mortenw@gnome.org>
Acked-by: Namhyung Kim <namhyung@gmail.com>
Acked-by: Nicolas Kaiser <nikai@nikai.net>
Acked-by: Oleg Nesterov <oleg@redhat.com>
Acked-by: Pavel Roskin <proski@gnu.org>
Acked-by: Pekka Enberg <penberg@cs.helsinki.fi>
Acked-by: Peter Jones <pjones@redhat.com>
Acked-by: Peter A Jonsson <pj@sics.se>
Acked-by: Ralf Wildenhues <Ralf.Wildenhues@gmx.de>
Acked-by: Ramsay Jones <ramsay@ramsay1.demon.co.uk>
Acked-by: Randy Dunlap <rdunlap@xenotime.net>
Acked-by: Reinhard Tartler <siretart@tauware.de>
Ached-by: Richard Knutsson <richard.knutsson@gmail.com>
Acked-by: Rob Taylor <rob.taylor@codethink.co.uk>
Acked-by: Rui Saraiva <rmpsaraiva@gmail.com>
Acked-by: Ryan Anderson <ryan@michonline.com>
Acked-by: Sam Ravnborg <sam@ravnborg.org>
Acked-by: Samuel Bronson <naesten@gmail.com>
Acked-by: Santtu Hyrkkö <santtu.hyrkko@gmail.com>
Acked-by: Shakthi Kannan <shakthimaan@gmail.com>
Acked-by: Stephen Hemminger <shemminger@linux-foundation.org>
Acked-by: Thomas Schmid <Thomas.Schmid@br-automation.com>
Acked-by: Tilman Sauerbeck <tilman@code-monkey.de>
Acked-by: Vegard Nossum <vegardno@ifi.uio.no>
Acked-by: Xi Wang <xi.wang@gmail.com>
Acked-by: Yura Pakhuchiy <pakhuchiy@gmail.com>
Signed-off-by: Christopher Li <sparse@chrisli.org>
|
|
James Westby is the only person not reacting when asking him about the MIT
license change over email or social media. So he has to count as not accepting
and reverting his contributions is the only way to to avoid possible legal
problems. The contributions can be re-added later when they are rewritten from
scratch.
This reverts commit 006eff06c7adcfb0d06c6fadf6e9b64f0488b2bf.
Cc: James Westby <jw+debian@jameswestby.net>
Signed-off-by: Franz Schrober <franzschrober@yahoo.de>
Signed-off-by: Christopher Li <sparse@chrisli.org>
|
|
Run test-linearize against this program.
static int foo(float x) { return !x; }
The output is:
set.32 %r2 <- 0.000000
bad_op.32
ret.32 %r3
The expression type of zero testing should be EXPR_COMPARE, rather than
EXPR_BINOP, which causes bad_op.
Acked-by: Christopher Li <sparse@chrisli.org>
Signed-off-by: Xi Wang <xi.wang@gmail.com>
Signed-off-by: Pekka Enberg <penberg@kernel.org>
|
|
The result type of relational operators (e.g., x < y) and logical
operators (e.g., x && y) in C should be int, rather than bool.
For example, sparse incorrectly evaluates sizeof(x < y) to 1 (i.e.,
sizeof(int)), which should have been sizeof(int).
This patch fixes the result type of these operators in evaluation,
linearization, and the LLVM backend.
Acked-by: Christopher Li <sparse@chrisli.org>
Signed-off-by: Xi Wang <xi.wang@gmail.com>
Signed-off-by: Pekka Enberg <penberg@kernel.org>
|
|
It will indicate this argument will skip the type compatible check.
It allow PTR_ERR() to accept __iomem pointer without complaining.
Signed-off-by: Christopher Li <sparse@chrisli.org>
|
|
This patch adds new option -Winit-cstring to sparse.
With the option sparse can Warn about initialization of a char array
with a too long constant C string. If the size of the char array and
the length of the string is the same, there is no space for the last
nul char of the string in the array.
char s[3] = "abc";
If the array is used as just a byte array, not as C string, this
warning is just noise. However, if the array is passed to functions
dealing with C string like printf(%s) and strcmp, it may cause a
trouble.
Here is a example of such trouble:
http://www.spinics.net/lists/netdev/msg229765.html
http://www.spinics.net/lists/netdev/msg229870.html
Signed-off-by: Masatake YAMATO <yamato@redhat.com>
Signed-off-by: Christopher Li <sparse@chrisli.org>
|
|
Pull preprocessor fix from Al Viro.
1) we really, really shouldn't convert escape sequences too early;
#define A(x) #x
A('\12')
should yield "'\\12'", *not* "'\\n'".
2) literal merging handles all sequences of string/wide string
literals; result is wide if any of them is wide. string_expression() is
handling that wrong - "ab"L"c" is L"abc"
3) with support (no matter how cursory) of wide char constants
and wide string literals, we really ought to handle
#define A(x,y)
A(L,'a')
properly; it's not that tricky - combine() needs to recognize <IDENT["L"],CHAR>
and <IDENT["L"],STRING> pairs.
4) '\777' is an error, while L'\777' is valid - the value should fit
into unsigned char or unsigned counterpart of wchar_t. Note that for string
literals this happens *after* phase 6 - what matters is the type of literal
after joining the adjacent ones (see (2) above).
5) stringifying should only quote \ and " in character constants and
string literals,
#define A(x) #x
A(\n)
should produce "\n", not "\\n"
6) we are losing L when stringifying wide string literals; that's
wrong.
I've patches hopefully fixing the above. Basically, I delay interpreting
escape sequences (past the bare minimum needed to find where the token ends)
until we are handling an expression with character constant or string literal
in it.
For character constants I'm keeping the token body in token->embedded -
4-character array replacing token->character. That covers practically
all realistic instances; character constant *may* be longer than that,
but it has to be something like '\x000000000000000000000000041' - sure,
that's 100% legitimate C and it's going to be the same as '\x41' on
everything, but when was the last time you've seen something like that?
So I've split TOKEN_CHAR into 5 values - TOKEN_CHAR+1--TOKEN_CHAR+4 meaning
1--4 characters kept in ->embedded[], TOKEN_CHAR itself used for extremely
rare cases longer than that (token->string holds the body in that case).
TOKEN_WIDE_CHAR got the same treatment.
AFAICS, with those fixes we get the same behaviour as in gcc for
silently ignored by cpp if the string/char constant doesn't make it
out of preprocessor. sparse still warns about those. The situation
with this one is frustrating; on one hand C99 is saying that e.g.
'\x' is not a token. Moreover, in a footnote in 6.4.4.4 it flat-out
requires diagnostics for such. On the other hand... footnotes are
informative-only and having "other character" token match ' would
puts us in nasal daemon country, so gcc is free to do whatever it feels
like doing. I think we shouldn't play that kind of standard-lawyering
*and* sparse has always warned on that, so I've left that warning
in place.
Note that real wchar_t handling is still not there; at the very least,
we need to decide what type will be used for that sucker (for gcc it's
int on all targets we care about), fix the handling of wide string literals
in initializers and evaluate_string() and stop dropping upper bits in
get_string_constant(). That would probably mean not using struct string
for wide ones, as well... Hell knows; I don't want to touch that right
now. If anything, I'd rather wait until we get to C11 support - they've
got much saner variants of wide strings there (char16_t/char32_t with
u and U as token prefix as L is used for wchar_t; there's also u8"..." for
UTF8 strings).
|
|
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
|
|
This patch sets ->stmt of a SYM_LABEL to the corresponding label
statement. If ->stmt was already set, it is a duplicate label.
On the other hand, if ->stmt of a goto label is not set during
evaluation, the label was never declared.
Signed-off-by: Christopher Li <sparse@chrisli.org>
|
|
Skip the expression instead of adding a null one.
Signed-off-by: Christopher Li <sparse@chrisli.org>
|
|
The new gcc complain about set but not used
variable. This should make the new gcc happy.
Signed-off-by: Christopher Li <sparse@chrisli.org>
|
|
Without this commit, sizeof(_Bool) provokes an error with "cannot size
expression" because _Bool is a 1-bit type and thus not a multiple of a full
byte in size. But sizeof(_Bool) is valid C that should evaluate to 1, so
this commit fixes the problem and adds a regression test.
Signed-off-by: Ben Pfaff <blp@nicira.com>
Signed-off-by: Christopher Li <sparse@chrisli.org>
|
|
As of gcc 4.5, asm goto("jmp %l[label]" : OUT : IN : CLOB : LABELS) is
supported. Add this support to the parser so that it won't choke on
the newest Linux kernel when compiling with gcc 4.5.
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
Signed-off-by: Christopher Li <sparse@chrisli.org>
|
|
This should fix the segfault report by Randy.
It still doesn't parse the struct attribute correctly though.
Signed-off-by: Christopher <sparse@chrisli.org>
|
|
Some structure types provide a set of fields of which most users will
only initialize the subset they care about. Users of these types should
always use designated initializers, to avoid relying on the specific
structure layout. Examples of this type of structure include the many
*_operations structures in Linux, which contain a set of function
pointers; these structures occasionally gain a new field, lose an
obsolete field, or change the function signature for a field.
Add a new attribute designated_init; when used on a struct, it tells
Sparse to warn on any positional initialization of a field in that
struct.
The new flag -Wdesignated-init controls these warnings. Since these
warnings only fire for structures explicitly tagged with the attribute,
enable the warning by default.
Includes documentation and test case.
Signed-off-by: Josh Triplett <josh@joshtriplett.org>
Signed-off-by: Christopher Li <sparse@chrisli.org>
|
|
GCC provides a 128 bit type called internally as TImode (__int128_t)on 64 bit
platforms (at least x86_64 and Sparc64). These types are used by OpenBIOS.
Add support for types "long long long", __mode__(TI) and __(u)int128_t.
Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
Signed-off-by: Christopher Li <sparse@chrisli.org>
|
|
In gcc extern inline function has special meaning. The inline
function will never emit stand alone copy of the function. It also
allow multiple implementations cross different file. That effectively
makes the extern inline has file scope.
Signed-off-by: Christopher Li <sparse@chrisli.org>
|
|
Remove all previous checks for Waddress_space and add one centralized to
the address_space attribute handler. If user passes the
-Wno-address-space option, we behave as if every pointer had no address
space.
Signed-off-by: Martin Nagy <nagy.martin@gmail.com>
Signed-off-by: Christopher Li <sparse@chrisli.org>
|
|
Was:Re: Initializing float variables without type suffix)
> cast_to() seems fine.
>
> In expanding stage, cast_value() did not cast the constant
> correctly.
You're right, I also noticed this in the meantime.
The decision, whether newtype is int_type or fp_type is not made
correctly.
The following patch seems to work:
Fix implicit cast to float
Patch modified by Chris.
Signed-Off-By: Thomas Schmid <Thomas.Schmid@br-automation.com>
Signed-Off-By: Christopher Li <sparse@chrisli.org>
|
|
There are several interesting problems caused by the fact that
we create a separate symbol for each declaration of given function.
1)
static inline int f(void);
static int g(void)
{
return f();
}
static inline int f(void)
{
return 0;
}
gives an error, since the instance of f in g is not associated with anything
useful. Needless to say, this is a perfectly valid C. Moreover,
static inline int f(void)
{
return 0;
}
static inline int f(void);
static int g(void)
{
return f();
}
will step on the same thing. Currently we get the former case all over the
place in the kernel, thanks to the way DEFINE_SYSCALLx() is done.
I have a kinda-sorta fix for that (basically, add a reference to external
definition to struct symbol and update it correctly - it's not hard).
However, that doesn't cover *another* weirdness in the same area -
gccisms around extern inline. There we can have inline and external
definitions in the same translation unit (and they can be different,
to make the things even more interesting). Anyway, that's a separate
story - as it is, we don't even have a way to tell 'extern inline ...'
from 'inline ...'
2) More fun in the same area: checks for SYM_FN in external_declaration()
do not take into account the possibility of
void f(int);
typeof(f) g;
Ergo, we get linkage-less function declarations. Fun, innit? No patch.
3) Better yet, sparse does _NOT_ reject
typeof(f) g
{
...
}
which is obviously a Bloody Bad Idea(tm) (just think what that does to
argument list). Similar crap is triggerable with typedef. IMO, we really
ought to reject _that_ - not only 6.9.1(2) explicitly requires that, but
there's no even remotely sane way to deal with arguments.
4)
static void f(void);
...
void f(void);
triggers "warning: symbol 'f' was not declared. Should it be static?"
which is at least very confusing - it *is* declared and it *is* static.
IOW, we do not collect the linkage information sanely. (2) will make
fixing that one very interesting.
Anyway, proposed patch for (1) follows:
Subject: [PATCH] Handle mix of declarations and definitions
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Christopher Li <sparse@chrisli.org>
|
|
Signed-off-by: Alexey Zaytsev <alexey.zaytsev@gmail.com>
|
|
sizeof(void) still evaluate as 1 after the warning.
void_ctype.bit_size remain zero so is_byte_type()
will continue to work.
Signed-Off-By: Christopher Li <sparse@chrisli.org>
|
|
This change will fix Rusty Russel's test case:
(*(typeof(v) __attribute__((address_space(0), force)) *)(&v))
Signed-Off-By: Christopher Li <sparse@chrisli.org>
|
|
Signed-off-by: Josh Triplett <josh@freedesktop.org>
|
|
Signed-off-by: David Given <dg@cowlark.com>
[negative value division fixed by alexey.zaytsev@gmal.com]
Signed-off-by: Alexey Zaytsev <alexey.zaytsev@gmail.com>
|
|
evaluate.c forgets to evaluate iterator_syms, which
might have some expression in initializer.
Signed-Off-By: Christopher Li <sparse@chrisli.org>
|
|
If I put the following in a public header:
struct foo;
typedef struct foo *Foo;
void func (Foo f);
and the definition of struct foo in a private header:
struct foo { int bar; }
then I get a sparse warning (different base type for argument 1) when
I compile the implementation file:
#include "public.h"
#include "private.h"
void func (Foo f) { ... }
i.e. sparse doesn't realise that the incomplete structure definition
in the function prototype refers to the same type as the complete
structure definition in the function definition.
*I think* that the patch fixes this - it silences the error - but I
don't know enough about sparse to know whether it's correct (or
whether it silences other legitimate errors, for example).
Signed-off-by: Geoff Johnstone <geoff.johnstone@googlemail.com>
|
|
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
|
|
* postfix stuff had been applied in wrong order (e.g. int a[2][3] generated
int [addressable][toplevel] a[3][2])
* after fixing that, we've no need for recursion anymore, a bunch of arguments
go away and turn into local variables and we get an easy way to get rid of
bogus space in the show_typename() result.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
[Josh: fix test suite to match]
Signed-off-by: Josh Triplett <josh@kernel.org>
|
|
* don't crap the type->ident for unsigned int just because somebody did
typedef unsigned int x;
only structs, unions, enums and restricted types need it.
* generate saner warnings for restricted, include type name(s) into them.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
|
|
Signed-off-by: Josh Triplett <josh@freedesktop.org>
|
|
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
|
|
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
|
|
fix a braino - (void *)0 == 1 is not acceptable, even though one argument
is a pointer, another is an integer and there's a null pointer constant in
the mix.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
|
|
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
|
|
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
|
|
We did examine_symbol_type() too late - after checking that it looks
like a struct or union.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
|
|
starting to encapsulate types handling...
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
|
|
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
|
|
* new helper: examine_pointer_target(). Examine target, find address_space
et.al. If the target is SYM_NODE - merge it, etc.
* new helper: target_qualifiers(). Pointers to any array are considered
as pointers to unqualified type as far as implicit conversions are
concerned; handle that right.
* SYM_TYPEOF can be handled sanely now: don't copy the node, just convert
SYM_TYPEOF to SYM_NODE and examine that.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
|
|
a) qualifiers should not be ignored beyond the top layer
b) qualifiers *should* be ignored in top layer of function arguments
c) change prototype - pass ctype * instead of symbol * and pass
"what to add to modifiers in that ctype" instead of "what to ignore".
We are still not quite done (there are incomplete types, there
are array size comparisons, there is lifting of signedness logics
into compatible_assignment_types()), but it's a much better approximation.
BTW, it's already good enough for kernel ARRAY_SIZE(), which
has become a major source of noise lately...
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
[Josh: prototype fix]
Signed-off-by: Josh Triplett <josh@freedesktop.org>
|
|
We are checking the wrong thing - the arguments have already
degenerated, so we won't see SYM_FN there (or SYM_ARRAY, for
that matter). That check should be done to the target of
pointer, not to the pointer itself and it should simply check
for SYM_FN - that's what we'll get there both from decayed
functions _and_ pointers to functions.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
|
|
a) pointer to _Bool is OK
b) struct to same struct or union to same union is OK; void to void etc. are not
c) to/from void * with loss of qualifiers or with different address space
should give the right warning itself instead of "different base types"
it would get from fallback to type_difference()
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
|
|
a) examine_fn_arguments() when comparing SYM_FN nodes; then
we won't need to try implementing argument adjustment as
part of the main loop. SYM_ARRAY->SYM_PTR and SYM_FN/SYM_PTR
interactions go away (and we stop getting nonsense results
like "int * and int [1] are the same thing"). All callers
are already happy with that.
b) different structs or unions are incompatible.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
|
|
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
|
|
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
|
|
a) qualifiers are joined (const int * / volatile int * -> const volatile int *)
b) pointer to void / pointer to T => pointer to void (with all qualifiers)
testcase added
Still missing: T1 * / T2 * => pointer to composite type of T1 and T2
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
|
|
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>
|
|
conditional on -Wreturn-void
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
|
|
... until we have initializer.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
|
|
... and lose useless argument
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
|
|
It should do integer_promotion() for integer types, turn float into
double and degenerate() the functions/arrays. We do *not* want
compatible_assignment_type() in any case, though.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
|
|
index may need to be expanded
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
|
|
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
|
|
* evaluate_binop() cleaned up
* evaluate_add(), evaluate_sub(), evaluate_arith() are gone
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
|
|
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
|
|
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
|
|
ptr_type in there is dead since commit 87900e832ac31d3aae63051ee054b01c17170439
(Nov 2004).
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
|
|
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
|
|
Pure assignment and <op>= cases are different enough to make it easier handling
them in separate functions. For now just split compatible_assignment_types()
in two; the next patches will clean each up.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
|
|
At the same time we get to pass expressions by value...
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>
|
|
sparse should distinguish two cases. One is when the structure or union
is declared and the member is not found. Another is when the structure
or union is not yet declared. In the later case, the message should
indicate that the type is incomplete, rather than complain that the
particular member is not found.
Mention the incomplete type like gcc does, but provide the member name
too, it may be useful.
Signed-off-by: Pavel Roskin <proski@gnu.org>
|
|
degrade to integer type, generate a warning and move on...
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
|
|
a NULL pointer
Signed-off-by: Josh Triplett <josh@freedesktop.org>
|
|
Signed-off-by: Josh Triplett <josh@freedesktop.org>
|
|
Signed-off-by: Josh Triplett <josh@freedesktop.org>
|
|
For inline functions, Sparse inlines the function body at evaluation. It is
very hard to find out the original function call. This change preserves the
original call as an annotation.
Signed-Off-By: Christopher Li <sparse@chrisli.org>
|
|
Add a new function expression_error, which works just like
sparse_error but also installs a bad_ctype into the expression.
Signed-Off-By: Christopher Li <sparse@chrisli.org>
|
|
The following case causes a warning about different signedness of pointer.
The pointer should not have signedness at all.
struct sk_buff;
struct sock;
extern int skb_append_datato_frags(struct sock *sk, struct sk_buff *skb,
int getfrag(void *from, char *to, int offset,
int len,int odd, struct sk_buff *skb),
void *from, int length);
int skb_append_datato_frags(struct sock *sk, struct sk_buff *skb,
int (*getfrag)(void *from, char *to, int offset,
int len,int odd, struct sk_buff *skb),
void *from, int length)
{
return 0;
}
Signed-Off-By: Christopher Li <sparse@chrisli.org>
Acked-By: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Josh Triplett <josh@freedesktop.org>
|
|
Fix a mistake in same_cast_type where the second test became a no-op as it
compared a value to itself, rather than to the second operand.
Signed-off-by: James Westby <jw+debian@jameswestby.net>
|
|
The back end need to generate some storage for anonymous string.
This simplify testing of anonymous string.
Signed-off-by: Christopher Li <sparse@chrisli.org>
|
|
Signed-off-by: Pavel Roskin <proski@gnu.org>
Signed-off-by: Josh Triplett <josh@freedesktop.org>
|
|
Signed-off-by: Adam DiCarlo <adam.dicarlo@gmail.com>
|
|
This stuff comes from handling smaller-than-int bitwise types (e.g. __le16).
The problem is in handling things like
__be16 x, y;
...
if (x == (x & ~y))
The code is bitwise-clean, but current sparse can't deduce that. Operations
allowed on bitwise types have the following property: (type)(x <op> y) can
be substituted for x <op> y in any expression other than sizeof. That allows
us to ignore usual arithmetical conversions for those types and treat e.g.
| as __be16 x __be16 -> __be16, despite the promotion rules; resulting
semantics will be the same. However, ~ on smaller-than-int does not have
such property; indeed, ~y is guaranteed to _not_ fit into range of __be16
in the example above.
That causes a lot of unpleasant problems when dealing with e.g. networking
code - IP checksums are 16bit and ~ is often used in their (re)calculations.
The way to deal with that is based on the observation that even though we do
get junk in upper bits, it normally ends up being discarded and sparse can
be taught to prove that. To do that we need "fouled" conterparts for short
bitwise types. They will be assigned to (sub)expressions that might carry
junk in upper bits, but trimming those bits would result in the value we'd
get if all operations had been done within the bitwise type. E.g. in the
example above y would be __be16, ~y - fouled __be16, x & ~y - __be16 again
and x == (x & ~y) - boolean.
Basically, we delay reporting an error on ~<short bitwise> for as long as
possible in hope that taint will be cleansed later. Exact rules follow:
* ~short_bitwise => corresponding fouled
* any arithmetics that would be banned for bitwise => same warning
as if we would have bitwise
* if t1 is bitwise type and t2 - its fouled analog, then
t1 & t2 => t1, t1 | t2 => t2, t1 ^ t2 => t2.
* conversion of t2 to t1 is silent (be it passing as argument
or assignment). Other conversions are banned.
* x ? t1 : t2 => t2
* ~t2 => t2 (_not_ t1; something like ~(x ? y : ~y) is still fouled)
* x ? t2 : t2 => t2, t2 {&,|,^} t2 => t2 (yes, even ^ - same as before).
* x ? t2 : constant_valid_for_t1 => t2
* !t2 => warning, ditto for comparisons involving t2 in any way.
* wrt casts t2 acts exactly as t1 would.
* for sizeof, typeof and alignof t2 acts as promoted t1. Note that
fouled can never be an lvalue or have types derived from it - can't happen.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
|
|
|
|
All these guys are really pieces of usual arithmetic conversions;
doesn't make sense to handle them separately, especially if we
want to recover from mismatches in __bitwise__, etc. by letting
them degrade to corresponding integer types.
|
|
* new helper - restricted_binop_type(); gives resulting type of binary
operation when at least one of arguments is SYM_RESTRICT. NULL is
returned in case of error. Arguments will make sense when we get
to consolidation of compatible_binop_...() (next patch), switching
to better recovery from type errors for these guys (next after that)
and smarter handling of ~ on small restricted types.
* compatible_restricted_binop() and check_case_type() switched to
using that puppy
|
|
|
|
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
|
|
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
|
|
that bugger is weird; _no_ type modifications are
done to arguments (no promotions, no degeration,
void accepted, etc.). Implemented, testcase added.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
|
|
fixed, testcase added
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
|
|
Add the ability to turn off enum type mismatch warnings using
-Wno-enum-mismatch, helpful when attempting to track down a particular class
of warnings only without losing them amongst others. Enum type mismatch
checking defaults to on, so this does not change the default behavior of
sparse.
Signed-off-by: Josh Triplett <josh@freedesktop.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
|
|
Add the ability to turn off address-space mismatch warnings using
-Wno-address-space, helpful when attempting to track down a particular class
of warnings only without losing them amongst others. Address space checking
defaults to on, so this does not change the default behavior of sparse.
Signed-off-by: Josh Triplett <josh@freedesktop.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
|
|
Run evaluate_symbol() before check_duplicates() so that the signedness
of the token is known by the time the token is compared with other
tokens.
Signed-off-by: Pavel Roskin <proski@gnu.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
|
|
Noted by Alexey Dobriyan, who also sent in a small test-case.
When evaluating to a bad type, just use "&bad_ctype" rather than
returning NULL. That will also mean that we won't be re-evaluating that
expression over and over again - we'll just mark the expr->ctype to be
bad, once and for all.
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
|
|
This adds a warning when enums of different types are mixed. I found a
handful of problems with this in my own code -- nothing that testing
could have revealed at this point, but if someone has added an extra
flag to an enum, things would have gone "boom!"
typedef enum { A1, A2 } enumA;
typedef enum { B1 = 10, B2 } enumB;
static void Afunc (enumA a) { }
int
main (int argc, char **argv)
{
enumA a = A1;
switch (A1) {
case A1: break;
case A2: break;
case B1: break; // Warn
case B2: break; // Warn
default: break;
}
switch (1) {
case A1: break;
case A2: break;
case B1: break; // Warn
case B2: break; // Warn
default: break;
}
switch (1) {
case A1 ... B2: break; // Warn
default: break;
}
(void)(1 ? a : B1); // Warn
(void)(A1 == B1); // Warn
(void)(A1 << B1); // No warning wanted
a = B1; // Warn
Afunc (B1); // Warn
return 0;
}
Signed-off-by: Morten Welinder <terra@gnome.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
|
|
We can move the cast down only if it's casting to a smaller type,
obviously.
Problem case found by Al Viro.
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
|
|
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>
|
|
member dereferencing didn't examine the parent type, as consequence the
member offset were never calculated.
[ Note: we _used_ to do eager examination of all types whenever we saw a
pointer, but as of commit 017034ed49eb0c0fdf91a4109faedf389c81fa9b we
only do it when necessary, and this case had been missed. - Linus ]
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
|
|
... and should be in MOD_PTRINHERIT
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
|
|
Make "should it be static?" warnings conditional on a new flag (-Wdecl);
default is to be quiet.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
|
|
The "volatile" and "const"'ness of the symbol will become part of the
pointer type, but we don't want to keep around things like "pointer to
unsigned", so strip that part off.
This still keeps other attributes, like "pointer to 'static'". Useful?
Probably not. I'll have to think about it.
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
|
|
When we check the case statement type against the type of the switch
statement it is associated with, we need to make sure that the case
expression has been fully type-evaluated.
It should have happened automatically as we evaluate the switch
statement, but if that has not happened, we'd follow a NULL pointer due
to the unevaluated type.
Thanks to Adrian Bunk for reporting a segfault for reiser4
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
|
|
Mitesh Shah (and others) report that broken libc's will have their own
"error()" that the sparse naming clashes with.
So use a sed-script to rewrite all the occurrences.
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
|
|
This avoids evaluating already evaluated symbols. I think if the symbol
is already evaluated once, there is no change in the conditions so it
should not be evaluated again. This helps when we are evaluating for
multiple files.
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
|
|
No need to turn an "enum" into an "int" if it's already the right size -
the longer we can keep the full type information, the better.
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
|
|
Problem noted by Zach Brown
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
|
|
Follow offset and cast expressions down etc, instead of just looking at
the type we assigned.
|
|
It's usually a wrong pointer type, wrong address space, or similar.
If it's a _really_ wrong type that simply can't be converted to the
right one (like trying to pass a structure instead of a scalar), it
would be an error, but we don'äknow that at this point.
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
|
|
This replaceq calls to warning() with error() at places where (I think)
the gcc reports an error. Also added a global variable die_if_error
which is set if there is one or more errors. If someone wants to stop
processing further, can check for the variable.
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
|
|
* generate a warning when we cast _between_ address spaces (e.g. cast
from __user to __iomem).
* optional (on -Wcast-to-as) warning when casting _TO_ address space
(e.g. when normal pointer is cast to __iomem one - that caught a lot
of crap in drivers). casts from unsigned long are still OK, so's
cast from 0, so's __force cast, of course.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
|
|
Noted by Alexey Dobriyan <adobriyan@gmail.com>
|
|
Now that we don't always examine types all the way, we need to examine
stuff when looking at the base type..
|
|
Examining a pointer should not cause us to examine what it points to.
However, that means that we'll have to be more careful later on when we
look at the base type of a pointer.
|
|
It obviously shouldn't be static, but we could add a test for it
having one of the acceptable types if we wanted to. Right now
I don't care enough.
|
|
This patch avoid a segfault while printing a warning message about
bad asm statement like:
void foo(void)
{
asm( "" : "" : "r" (0));
}
Signed-Off-by: Luc Van Oostenryck <luc.vanostenryck@looxix.net>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
|
|
This patch add static declare to make sparse happy of checking itself.
|
|
This removes SYM_ENUM as a special case for symbol handling, and
makes it possible to follow the types much better.
|
|
|
|
It could be a sparse bug (lacking type evaluation), but the kernel
has zero-sized arrays in valid places, so..
|
|
|
|
It's usually indicative of a sparse type-sizing bug rather
than a bug in the checked source.
|
|
We weren't checking the types properly, only the sizes. That
made us incorrectly ignore implicit casts between integers
and pointers if they just had the right size and sign.
|
|
could never trigger.
Also, make sure that the node we create gets the signedness
etc specifiers from the pointer.
|
|
|
|
We do need to take the modifiers from the pointer too, but not
to the point of ignoring the modifiers of the member itself.
|
|
|
|
(As well as unsigned restricted types).
|
|
It's wrong to optimize away a cast just based on its bitsize.
For one thing, the bit _offset_ also matters. For another, we
do care about potential sign-changes of the cast too.
So call "cast_to()" more aggressively, and make that function
do the proper checks.
|
|
Needed to get all the MOD_ASSIGNED and "const" warnings right.
Another in the "Al Viro found strange things" series.
|
|
properly MOD_ADDRESSABLE.
This made some other parts of sparse think that symbols
were read-only and could be optimized away.
Al's test-cases found this.
|
|
pointer subtractions.
Not only does it generate bad code (that can often be rewritten
to not do that), it also causes gcc to go into horrible contortions,
and Al Viro reports that it can make a factor of 2.5 difference in
kernel build times to have just a few of these in common header
file inline functions.
|
|
in-place.
In case of inline functions we share the expression tree
with the original inline fn, and we mustn't change the
sub-expressions.
|
|
|
|
The asm_inputs/outputs "expression list" is not really an
expression list any more: it is a list of "triples", where
the first entry is the identifier name, the second one is
the constraint string, and the third one is the expression.
|
|
Much prettier than "input_streams[x].name", since most
users really don't want to know about the internals of
how the preprocessor lays out its stream tracking.
|
|
|
|
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.
|
|
We used to (long ago) consider a zero bit_size to be a sign
of the symbol type needing to be examined. However, when I
changed that to use an explicit "examined" flag, I didn't
realize that the function argument degeneration had depended
on that.
So make the function argument degeneration explicitly ask for
re-examination after changing it to a pointer. Otherwise it
ends up being a "zombie pointer" of size 0, which makes for
lots of confusion.
|
|
This allows us to notice when a symbol address usage is
trivially dead, and optimize such a symbol better since
we don't have to worry about the address being used to
access it.
|
|
|
|
We used to complain about binops that were not restricted,
and accept assignments that were not ok.
|
|
Not only do all users want it, the list of used symbols
is not stable until after the tree has been evaluated.
|
|
Noted by Anton Altaparmakov who is clearly better at testing
than I am. This got broken by the assignment evaluation re-org.
|
|
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 happens for implied cast simplification.
Currently only a binary not will be simplified, but it's conceptually
right for things like "char a,b,c; c = a+b;" too, where we should end
up simplifying away the thing across a binop too..). Some day..
|
|
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.
|