| Age | Commit message (Collapse) | Author | Files | Lines |
|
The current code will simplify away some casts at evaluation time
but doesn't take in account some special cases:
* (bool)~<int> is not equivalent to ~(bool)<int> (anything not all 0 or 1)
* (float)~<int> is not equivalent to ~(float)<int> which doesn't make sense.
* (int)(float)<int> is not a no-op if the (float) overflows
This kind of simplification is better done on the IR where the different
kind of casts correspond to distinct instructions.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
and remove one that didn't made much sense.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Assignment to restricted variables are severely ... restricted.
Nevertheless, one value is always fine because it has always
the same bit representation: 0.
So, 0 is accepted unconditionally but this creates a problem
because the type of this 0 needs to be adjusted. Otherwise
0 (int) is assigned as-is even on restricted variable with a
different bit-length.
Fix this by casting the value to the target type before accepting it.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Statement expressions should be subjected to lvalue-conversion
and thus should drop qualifiers.
Fix this by calling unqualify_type() after array-to-pointer
conversion.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Comma expressions should be subjected to lvalue-conversion
and thus should drop qualifiers.
Fix this by calling unqualify_type() after array-to-pointer
conversion.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Add some testcases related to qualifier dropping / lvalue conversion.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Casts should drop qualifiers but Sparse doesn't do this yet.
The fix seems pretty simple: after having evaluated the type of
the cast, if this type is a SYM_NODE and contains qualifiers,
make a copy of the type with the qualifiers removed and use
this copy as the type.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
A cast to union type is a GCC extension similar to a compound
literal just for union, using the syntax of a cast.
However, sparse doesn't know about them and treats them like
other casts to non-scalars.
So, teach sparse about them, convert them to the corresponding
compound literal and add a warning flag to enable/disable the
associated warning: -W[no-]union-cast.
Note: a difference between union casts and compound literals
is that the union casts yield rvalues while compound
literals are lvalues but this distinction is not yet done
in this series.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Casts to union type are a GCC extension and are similar to
compound literals.
However, sparse doesn't know about them and treats them like
other casts to non-scalars.
Add some testcases for this and its upcoming warning flag.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
This is a fix for a problem reported today to the mailing list.
In check_assignment_types(), the first 'level' is checked by the
function itself but the next level is checked by the type_difference().
This later function take as arguments, beside the types to be
checked, the modifiers that can be assumed for each of the types
(this works as a kind of reverse mask).
But these modifiers are taken from target_qualifiers() which,
purposely ignore the modifiers for arrays introduced in commit
984b7b66457c ("[PATCH] deal correctly with qualifiers on arrays")
with the comment:
"Pointers to any array are considered as pointers to unqualified
type as far as implicit conversions are concerned"
But by dropping these modifiers, type_difference() reports
incorrect results for pointers to qualified arrays.
So, do not use target_qualifiers() but take the modifiers directly
from the ctypes. Admittingly, I'm far from sure that this is the
right fix but it solve several wrong cases.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
The problem is seems to be related with evaluate_dereference()
where all mods are dropped when the type is a node.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Those are cases that sparse should warn about but doesn't.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
You can assign a '<type>[]' to a 'const <type> *'. Likewise,
you can assign a '<type>[][N]' to a 'const <type> (*)[N]' but
sparse doesn't like this.
Analyzed-by: Ard Biesheuvel <ardb@kernel.org>
Reported-by: Herbert Xu <herbert@gondor.apana.org.au>
Link: https://lore.kernel.org/linux-crypto/20200709120937.GA13332@gondor.apana.org.au/
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
When inlining multiple times a function which contains an undeclared
function call, multiple error messages are issued. More annoyingly,
only the first one is meaningful, the other ones doesn't even show
the incriminated identifier:
error: undefined identifier '...'
error: not a function <noident>
Part of the problem is that the first message is displayed with
expression_error() which also sets the expression to &bad_ctype.
This change the way how the expression is handled when re-evaluated.
Fix this by avoiding the evaluation of function calls that already
evaluate to bad_ctype: it's known that an error message have already
been issued for them and that nothing good can done with them.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
* improve expansion of constant symbols
|
|
Symbols which have their address taken (with the 'addressof'
operator: &) are marked as such (with the modifier MOD_ADDRESSABLE).
But degenerated arrays and functions have their address implicitly
taken.
MOD_ADDRESSABLE is used to prevent to replace a symbol dereference
nto the value used to initialize to it. For example, in code like:
static int foo(void)
{
int x[2] = { 1, 2 };
return x[1];
}
the return expression can be replaced by 2. This is not the case
case if the array is first passed in a function call, like here:
extern void def(void *, unsigned int);
static int bar(void)
{
int x[2] = { 1, 2 };
def(x, sizeof(x));
return x[1];
}
Fix this by marking degenerated arrays (and functions) as also
being addressable.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
mark_addressable() is used to track if a symbol has its
address taken but does not take in account the fact that
a symbol can be accessed via one of its subfields.
A failure occurs in case like:
struct { int a; } s = { 3 };
...
def(&s.a);
return s.a;
where 's' is not marked as being addressable and so the
the initializer will be expanded and the return expression
will always be replaced by 3, while def() can redefine it.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Once a symbol has its address taken, a lot of simplifications
must be avoided because the symbol can now be modified via
a pointer.
This is currently done but the symbol addressability
does not take in account the fact that a symbol can be
accessed via one of its subfields.
Add a testcase to illustrate this.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
An array or a function that degenerates into a pointer
has its address implicitly taken since the result is
equivalent to '&array[0]' or '&fun'.
So, the corresponding symbol needs to be marked as
addressable, like when its address is explicitly taken.
Add a testcase to illustrate this.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
in the fixes 696b243a5ae0 ("fix: evaluate_dereference() unexamined base type"),
the pointer's examination was done prematurely, before the undereferenceable
types are filtered out. This allows to examine the base abstract types when
the expression was in fact not dereferenceable.
Fix that by moving the examination to the top of the SYM_PTR's case
since only pointers are concerned.
Fixes: 696b243a5ae0 ("fix: evaluate_dereference() unexamined base type")
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Unless an explicit call to examine_pointer_target() or
get_base_type() is made, the base type of pointers are
*not* examined via the usual recursive examine_symbol_type().
That means that it is possible to call show_typename()
on a non-fully examined type which is wrong (for example,
because SYM_TYPEOFs may not be converted).
So, call examine_pointer_target() on pointers when trying
to display them.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
The base type of pointers are not examined when the pointer is.
It needs to be done later when looked at.
This may be a problem when show_typename() is used on a pointer
which has not yet been 'deep-examined' and, for example, has a
SYM_TYPEOF as its base type.
Add a test case showing the problem.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Non-memory asm operands are very much like function's arguments.
As such, any array (or function designator) used as an asm operand
need to degenerate into the corresponding pointer.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
The operands of extended ASM need to have their type evaluated,
exactly like any other expression.
So, add the missing evaluation of ASM operands.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
ASM statements are quite complex.
Add some tests to catch some potential errors.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|