aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/evaluate.c
AgeCommit message (Collapse)AuthorFilesLines
2017-12-21fix: evaluate_dereference() unexamined base typeLuc Van Oostenryck1-0/+1
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>
2017-12-08fix: add missing degenerate() for logical notLuc Van Oostenryck1-0/+1
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>
2017-11-11Merge branches 'volatile-loads-are-side-effects', ↵Luc Van Oostenryck1-49/+35
'fix-volatile-simplification', 'struct-asm-ops', 'restricted-pointers', 'fix-f2i-casts', 'symaddr-description', 'flush-stdout' and 'diet-simple' into tip
2017-11-08define MOD_QUALIFIER for (MOD_CONST | MOD_VOLATILE)Luc Van Oostenryck1-1/+1
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>
2017-09-17use a specific struct for asm operandsLuc Van Oostenryck1-48/+34
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>
2017-08-28Merge remote-tracking branch 'luc/constexpr-v4' into masterChristopher Li1-54/+152
2017-08-04fix: give a type to bad cond expr with known conditionLuc Van Oostenryck1-0/+12
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>
2017-06-15fix: add missing examine in evaluate_dereference()Luc Van Oostenryck1-0/+2
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>
2017-06-14Merge branches 'quiets-bool-cast-restricted-v3', 'error-vs-warnings-v2', ↵Luc Van Oostenryck1-1/+2
'implicit-int', 'cgcc-darwin' and 'more-builtin-decls' into rc2
2017-06-10finer control over error vs. warningsLuc Van Oostenryck1-0/+1
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>
2017-05-19Merge branches 'dump-macros-v2', 'fix-predefined-size', 'fix-bool-context', ↵v0.5.1-rc1Luc Van Oostenryck1-1/+1
'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>
2017-05-19avoid warning on explicit 'bool <- restricted' castsLuc Van Oostenryck1-3/+10
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>
2017-05-19returns the correct type when evaluating NULLLuc Van Oostenryck1-1/+1
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>
2017-05-11avoid useless warning for 'bool <- restricted type' conversionLuc Van Oostenryck1-0/+6
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>
2017-03-31give default return type in evaluate_call()Luc Van Oostenryck1-1/+1
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>
2017-03-31return an error if too few argsLuc Van Oostenryck1-1/+3
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>
2017-03-31constexpr: treat comparisons between types as integer constexprNicolai Stange1-4/+9
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>
2017-03-31constexpr: support compound literals as address constantsNicolai Stange1-0/+2
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>
2017-03-31constexpr: relax some constant expression rules for pointer expressionsNicolai Stange1-2/+27
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>
2017-03-31constexpr: examine constness of __builtin_offsetof at evaluation onlyNicolai Stange1-2/+6
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>
2017-03-31constexpr: recognize string literals as address constantsNicolai Stange1-0/+1
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>
2017-03-31constexpr: recognize members of static compound objects as address constantsNicolai Stange1-0/+6
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>
2017-03-31constexpr: recognize address constants created through pointer arithmeticNicolai Stange1-0/+7
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>
2017-03-31constexpr: recognize address constants created through castsNicolai Stange1-0/+7
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>
2017-03-31constexpr: recognize static objects as address constantsNicolai Stange1-1/+2
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>
2017-03-31constexpr: check static storage duration objects' intializers' constnessNicolai Stange1-0/+10
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>
2017-03-31constexpr: collect storage modifiers of initializersLuc Van Oostenryck1-6/+7
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>
2017-03-31constexpr: rename handle_simple_initializer() to handle_initializer()Luc Van Oostenryck1-4/+4
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>
2017-03-31constexpr: add support for tagging address constantsNicolai Stange1-1/+18
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>
2017-03-31constexpr: examine constness of conditionals at evaluation onlyNicolai Stange1-6/+2
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>
2017-03-31constexpr: examine constness of preops at evaluation onlyNicolai Stange1-4/+4
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>
2017-03-31constexpr: examine constness of binops and alike at evaluation onlyNicolai Stange1-13/+6
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>
2017-03-31constexpr: examine constness of casts at evaluation onlyNicolai Stange1-8/+29
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>
2017-03-31constexpr: introduce additional expression constness tracking flagsNicolai Stange1-26/+26
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>
2017-03-22fix evaluation of a function or array symbol in conditionalsLuc Van Oostenryck1-0/+1
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>
2017-03-22warn if testing the address of an arrayLuc Van Oostenryck1-0/+3
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).
2017-03-22warn if testing the address of a functionLuc Van Oostenryck1-1/+4
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>
2017-03-04Allow casting to a restricted type if !restricted_valueEdward Cree1-1/+1
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>
2017-02-13validate expression's type in conditionalsLuc Van Oostenryck1-0/+5
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>
2017-02-13fix cast to boolLuc Van Oostenryck1-0/+32
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>
2017-02-13fix typing error in compound assignmentLuc Van Oostenryck1-1/+4
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>
2017-02-13Remove unneeded variable in integer_promotion()Luc Van Oostenryck1-3/+1
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>
2017-02-13cleanup: remove evaluate_arguments()'s unused argumentLuc Van Oostenryck1-2/+2
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>
2017-01-27Fix type checking of variadic functionsLuc Van Oostenryck1-1/+1
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>
2015-03-13Ignore pure attribute in assignementArd Biesheuvel1-1/+1
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>
2014-10-25teach next_designators() use array_element_offset()Christopher Li1-1/+1
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>
2014-10-10sparse: treat function pointers as pointers to const dataArd Biesheuvel1-0/+9
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>
2014-09-18Fix initializers in anonymous structs and unionsLinus Torvalds1-2/+18
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>
2014-07-17round up the array element size to byte alignChristopher Li1-1/+1
When layout the array element, the element size should round up to byte align. Signed-off-by: Christopher Li <sparse@chrisli.org>
2014-04-03Fix error at anoymous unionsLinus Torvalds1-12/+2
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>
2014-04-01Add warning about duplicate initializersLinus Torvalds1-0/+8
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>
2014-04-01Support GCC's transparent unionsJohn Keeping1-1/+27
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>
2014-04-01evaluate: split out implementation of compatible_assignment_typesJohn Keeping1-23/+34
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>
2014-02-27sparse: Allow override of sizeof(bool) warningJoe Perches1-1/+2
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>
2013-11-29sparse: Also check bit_offset when checking implicit castsFranz Schrober1-1/+2
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>
2013-11-29sparse: Relicense under the MIT licenseFranz Schrober1-1/+17
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>
2013-11-29Revert "Fix mistaken comparison that becomes a no-op."Franz Schrober1-1/+1
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>
2013-05-27Fix expression type for floating point negation ('!')Xi Wang1-1/+1
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>
2013-05-27Fix result type of relational and logical operatorsXi Wang1-6/+9
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>
2013-04-26Allow forced attribute in function argumentv0.4.5-rc1Christopher Li1-1/+1
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>
2013-04-19Warn about initialization of a char array with a too long constant C string.Masatake YAMATO1-4/+8
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>
2013-02-13Merge git://git.kernel.org/pub/scm/linux/kernel/git/viro/sparse into margeChristopher Li1-9/+17
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).
2013-02-12Gentler handling of bitwise warnings in unary operationsAl Viro1-9/+17
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2012-06-04check missing or duplicate goto labelsXi Wang1-1/+11
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>
2011-08-23Fix parsing empty asm clobberChristopher Li1-1/+1
Skip the expression instead of adding a null one. Signed-off-by: Christopher Li <sparse@chrisli.org>
2011-05-31Remove set but not used variableChristopher Li1-8/+2
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>
2011-05-07evaluate: Allow sizeof(_Bool) to succeed.Ben Pfaff1-0/+5
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>
2010-06-17parser: add support for asm gotoJiri Slaby1-0/+8
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>
2010-03-29evaluate: check for NULL type inside typeofChristopher1-1/+3
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>
2010-03-28New attribute designated_init: mark a struct as requiring designated initJosh Triplett1-0/+10
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>
2009-08-01Add support for TImode type (__int128_t)Blue Swirl1-3/+3
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>
2009-07-19move extern inline function to file scopeChristopher Li1-5/+0
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>
2009-07-18Add missing checks for Waddress-spaceMartin Nagy1-4/+4
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>
2009-07-17Fix implicit cast to floatThomas Schmid1-31/+0
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>
2009-07-17fun with declarations and definitionsAl Viro1-0/+7
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>
2008-12-28Also warn about sizeof(function)Alexey Zaytsev1-0/+6
Signed-off-by: Alexey Zaytsev <alexey.zaytsev@gmail.com>
2008-12-28Warn about explicit usage of sizeof(void)Christopher Li1-1/+14
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>
2008-12-25Teach classify_type to handle typeofChristopher Li1-0/+5
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>
2008-12-18Expand "dubious !x & y" handling to other combinations of !, &, and |.Josh Triplett1-3/+10
Signed-off-by: Josh Triplett <josh@freedesktop.org>
2008-12-17Unhardcode byte size being 8 bits.David Given1-13/+13
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>
2008-12-15Evaluate iterator symbolsChristopher Li1-0/+1
evaluate.c forgets to evaluate iterator_syms, which might have some expression in initializer. Signed-Off-By: Christopher Li <sparse@chrisli.org>
2008-04-05Fix type mismatches with incomplete typesGeoff Johnstone1-0/+4
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>
2008-04-03catch !x & y brainosAl Viro1-0/+3
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2008-04-03fix show_typename()Al Viro1-2/+2
* 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>
2008-04-03saner warnings for restricted typesAl Viro1-13/+20
* 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>
2007-08-31Rename Wcast_to_address_space to Wcast_to_as to match the command-line argumentJosh Triplett1-1/+1
Signed-off-by: Josh Triplett <josh@freedesktop.org>
2007-07-29[PATCH] saner -WtypesignAl Viro1-22/+25
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2007-07-29[PATCH] sanitize evaluate_postop()Al Viro1-19/+19
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2007-07-29[PATCH] fix evaluate_compare()Al Viro1-2/+2
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>
2007-07-29[PATCH] sanitize evaluate_ptr_add(), start checking for pointers to functionsAl Viro1-16/+25
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2007-07-29[PATCH] ...,array should degenerateAl Viro1-1/+3
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2007-07-28[PATCH] handling of typeof in evaluate_member_dereference()Al Viro1-1/+1
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>
2007-07-28[PATCH] new helper: unfoul()Al Viro1-8/+14
starting to encapsulate types handling... Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2007-07-28[PATCH] no such thing as array of functionsAl Viro1-6/+12
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2007-07-14[PATCH] deal correctly with qualifiers on arraysAl Viro1-34/+37
* 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>
2007-07-14[PATCH] rewrite type_difference()Al Viro1-120/+152
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>
2007-07-14[PATCH] fix the sanity check in evaluate_ptr_sub()Al Viro1-6/+7
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>
2007-07-14[PATCH] get compatible_assignment_types() deal with all casesAl Viro1-14/+43
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>
2007-07-14[PATCH] start cleaning type_difference()Al Viro1-25/+9
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>
2007-07-14[PATCH] integer_promotions() can't get SYM_NODE or SYM_ENUMAl Viro1-7/+2
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2007-07-14[PATCH] clean up evaluate_sign()Al Viro1-6/+8
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2007-07-10fix handling of pointers in ?:Al Viro1-33/+49
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>
2007-07-10fix handling of address_space in casts and assignmentsAl Viro1-54/+37
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>
2007-07-08first pass at null pointer constantsAl Viro1-71/+145
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>
2007-07-08fix the comma handling in integer constant expressionsAl Viro1-0/+6
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>
2007-06-26[PATCH] fix handling of integer constant expressionsAl Viro1-0/+43
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>
2007-06-26[PATCH] implement __builtin_offsetof()Al Viro1-0/+84
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2007-06-25[PATCH] warn on return <void expression>;Al Viro1-0/+2
conditional on -Wreturn-void Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2007-06-25[PATCH] in case of compound literal we want to delay examining typeAl Viro1-5/+6
... until we have initializer. Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2007-06-25[PATCH] move degenerate() down into compatible_assignment_types()Al Viro1-17/+13
... and lose useless argument Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2007-06-25[PATCH] fix default argument promotionAl Viro1-5/+14
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>
2007-06-25[PATCH] fix index conversions in evaluate_ptr_add()Al Viro1-42/+50
index may need to be expanded Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2007-06-25[PATCH] clean up usual_conversions(), kill evaluate_shift()Al Viro1-44/+34
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2007-06-25[PATCH] clean up the typechecking in arithmeticsAl Viro1-98/+73
* evaluate_binop() cleaned up * evaluate_add(), evaluate_sub(), evaluate_arith() are gone Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2007-06-25[PATCH] cleanup of evaluate_assign_op()Al Viro1-14/+16
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2007-06-25[PATCH] remove useless argument in evaluate_ptr_sub()Al Viro1-4/+4
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2007-06-25[PATCH] remove long-dead variable in evaluate_ptr_add()Al Viro1-4/+1
ptr_type in there is dead since commit 87900e832ac31d3aae63051ee054b01c17170439 (Nov 2004). Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2007-06-25[PATCH] null pointer constants have no special meaning for pointer subtractionAl Viro1-17/+2
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2007-06-25[PATCH] mechanically split compatible_assignment_types()Al Viro1-16/+47
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>
2007-06-25[PATCH] take cast_to() out of usual_conversions(), do it in callersAl Viro1-14/+16
At the same time we get to pass expressions by value... Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2007-06-25[PATCH] missing NULL checks in initializer handlingAl Viro1-2/+13
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2007-06-18[PATCH] rewrite of initializer handlingAl Viro1-175/+394
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>
2007-06-09Improve error message if using a member of an incomplete struct or unionPavel Roskin1-2/+7
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>
2007-05-26better recovery from bad operations on bitwiseAl Viro1-9/+20
degrade to integer type, generate a warning and move on... Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2007-05-22Add -Wno-non-pointer-null to turn off warning about using a plain integer as ↵Josh Triplett1-1/+1
a NULL pointer Signed-off-by: Josh Triplett <josh@freedesktop.org>
2007-05-01Fix most -Wshadow warnings in Sparse.0.3Josh Triplett1-4/+4
Signed-off-by: Josh Triplett <josh@freedesktop.org>
2007-03-09Fix typos in commentsJosh Triplett1-6/+6
Signed-off-by: Josh Triplett <josh@freedesktop.org>
2007-03-02Add annotation for inline function call.Christopher Li1-1/+1
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>
2007-02-27Introduce expression_errorChristopher Li1-41/+41
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>
2007-02-13Bug fix in pointer modifier inheritance at function degeneration.Christopher Li1-5/+3
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>
2007-01-27Fix mistaken comparison that becomes a no-op.James Westby1-1/+1
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>
2007-01-27Marking anonymous string.Christopher Li1-0/+1
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>
2006-11-06Typo fixesPavel Roskin1-1/+1
Signed-off-by: Pavel Roskin <proski@gnu.org> Signed-off-by: Josh Triplett <josh@freedesktop.org>
2006-10-17Add type information to enum mismatch warningAdam DiCarlo1-1/+4
Signed-off-by: Adam DiCarlo <adam.dicarlo@gmail.com>
2006-10-01[PATCH] handle fouled-bitwiseAl Viro1-15/+62
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>
2006-10-01[PATCH] saner recovery from endianness errors, part 1.Al Viro1-9/+17
2006-10-01[PATCH] merged compatible_..._binop() into single functionAl Viro1-79/+61
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.
2006-10-01[PATCH] beginning of SYM_RESTRICT rewrite: restricted_binop_type()Al Viro1-42/+62
* 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
2006-10-01[PATCH] evaluate_compare() can just use evaluate_arith() for non-pointer casesAl Viro1-16/+1
2006-10-01[PATCH] introduce classify_type(), use it in obvious placesAl Viro1-49/+58
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2006-10-01[PATCH] casting null pointer constant to non-zero address space is always OKAl Viro1-1/+12
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2006-09-30[PATCH] add support for __builtin_choose_expr()Al Viro1-11/+23
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>
2006-09-30[PATCH] fix for switch(bad_type) {...} segfaultAl Viro1-8/+8
fixed, testcase added Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2006-08-29[PATCH] Add -Wno-enum-mismatchJosh Triplett1-0/+2
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>
2006-08-29[PATCH] Add -Wno-address-spaceJosh Triplett1-1/+1
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>
2006-07-13[PATCH] Fix -WtypesignPavel Roskin1-1/+1
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>
2006-06-10Fix NULL ptr dereference with bad typeLinus Torvalds1-1/+1
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>
2006-03-28[PATCH] Warning for mixing enums of different typesMorten Welinder1-7/+47
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>
2006-01-08Fix incorrect cast simplification around '~' operationLinus Torvalds1-0/+2
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>
2005-12-31Make local declarations be statements of their ownLinus Torvalds1-5/+9
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>
2005-11-27[PATCH] Fix member offset calculationLuc Van Oostenryck1-0/+1
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>
2005-11-22[PATCH] noderef is a qualifierAl Viro1-1/+1
... and should be in MOD_PTRINHERIT Signed-off-by: Al Viro <viro@zeniv.linux.org.uk> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2005-11-22[PATCH] new flag - -WdeclAl Viro1-0/+2
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>
2005-11-22When taking the address of a symbol, fix up the pointer typeLinus Torvalds1-2/+4
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>
2005-11-19Evaluate expressions fully when doing type comparisons on case statementsLinus Torvalds1-6/+8
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>
2005-11-16Re-name "error()" function to "sparse_error()"Linus Torvalds1-47/+47
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>
2005-11-16[PATCH] skip already evaluated symbolsMitesh Shah1-0/+3
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>
2005-11-16Integer promotion: leave sufficiently large integer types as themselvesLinus Torvalds1-4/+13
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>
2005-11-03Make switch/case statements check type compatibilityLinus Torvalds1-5/+41
Problem noted by Zach Brown Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2005-09-30Make sure to be more careful about marking symbols assignedLinus Torvalds1-2/+35
Follow offset and cast expressions down etc, instead of just looking at the type we assigned.
2005-09-22Turn the "incorrect type" error back into a warningLinus Torvalds1-1/+1
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>
2005-09-22[PATCH] replaced warnings with errors.Mitesh Shah1-44/+44
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>
2005-09-09[PATCH] More address space checkingviro@ZenIV.linux.org.uk1-29/+48
* 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>
2005-07-11Don't warn about "nocast" warnings that only change "const"ness.Linus Torvalds1-4/+20
Noted by Alexey Dobriyan <adobriyan@gmail.com>
2005-06-16Fix up a few missing base type evaluationsLinus Torvalds1-3/+3
Now that we don't always examine types all the way, we need to examine stuff when looking at the base type..
2005-06-16Fix up type examination.Linus Torvalds1-9/+11
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.
2005-05-19Don't warn about undeclared "main()" function.Linus Torvalds1-0/+2
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.
2005-05-17[PATCH] avoid a crash on bad asm statementLuc Van Oostenryck1-2/+2
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>
2005-04-07[PATCH] static declearChristopher Li1-1/+1
This patch add static declare to make sparse happy of checking itself.
2005-04-07Make enum symbols be regular symbols with constant initializers.Linus Torvalds1-30/+11
This removes SYM_ENUM as a special case for symbol handling, and makes it possible to follow the types much better.
2005-04-07Warn about implicit casts to/from "nocast" typesLinus Torvalds1-6/+18
2005-04-07Don't warn about zero-sized "sizeof"Linus Torvalds1-1/+1
It could be a sparse bug (lacking type evaluation), but the kernel has zero-sized arrays in valid places, so..
2005-04-07Warn about undeclared identifiers.Linus Torvalds1-0/+10
2005-04-07Warn about sizeof of zero size.Linus Torvalds1-1/+1
It's usually indicative of a sparse type-sizing bug rather than a bug in the checked source.
2005-04-07Be more careful about removing implicit casts.Linus Torvalds1-16/+32
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.
2005-04-07Remove old stale pointer dereference type mess, thatLinus Torvalds1-14/+1
could never trigger. Also, make sure that the node we create gets the signedness etc specifiers from the pointer.
2005-04-07Export "is_ptr_type()" helper function to others.Linus Torvalds1-1/+1
2005-04-07Don't drop modifier bits from a member dereference.Linus Torvalds1-0/+2
We do need to take the modifiers from the pointer too, but not to the point of ignoring the modifiers of the member itself.
2005-04-07Add compile-time "range-check" infrastructure to sparseLinus Torvalds1-1/+6
2005-04-07Make sure we evaluate pointer comparisons as unsigned.Linus Torvalds1-1/+5
(As well as unsigned restricted types).
2005-04-07Don't optimize away casts too early.Linus Torvalds1-23/+24
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.
2005-04-07Evaluate asm outputs as assignments.Linus Torvalds1-0/+1
Needed to get all the MOD_ASSIGNED and "const" warnings right. Another in the "Al Viro found strange things" series.
2005-04-07We didn't mark symbols with their address taken as beingLinus Torvalds1-0/+5
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.
2005-04-07Add option "-Wptr-subtraction-blows" to warn about expensiveLinus Torvalds1-1/+7
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.
2005-04-07Don't do the pointer offset update for a pointer additionLinus Torvalds1-11/+17
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.
2005-04-07Verify that output/input asm constraints really look like outputs/inputs.Linus Torvalds1-0/+12
2005-04-07Save off the asm parameter name too.Linus Torvalds1-25/+55
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.
2005-04-07Add "stream_name()" helper function, and use it.Linus Torvalds1-1/+1
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.
2005-04-07Evaluate asm statement inputs/outputs and verify them.Linus Torvalds1-2/+60
2005-04-07Split out the blob allocator from lib.c into allocate.c.Linus Torvalds1-0/+1
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
2005-04-07Make expression tree have an "op value" for the inc/dec operations.Linus Torvalds1-6/+14
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.
2005-04-07Fix subtle problem with fn array argumentsLinus Torvalds1-0/+1
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.
2005-04-07Do early CSE before even doing the symbol simplification.Linus Torvalds1-1/+0
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.
2005-04-07Update copyright notices a bit.Linus Torvalds1-1/+1
2005-04-07Duh. Fix sense of restricted assignment check.Linus Torvalds1-1/+1
We used to complain about binops that were not restricted, and accept assignments that were not ok.
2005-04-07Make "translation_unit()" do symbol evaluation too.Linus Torvalds1-3/+14
Not only do all users want it, the list of used symbols is not stable until after the tree has been evaluated.
2005-04-07Fix up restricted type assignment checking.Linus Torvalds1-6/+16
Noted by Anton Altaparmakov who is clearly better at testing than I am. This got broken by the assignment evaluation re-org.
2005-04-07Remove EXPR_BITFIELD entirely.Linus Torvalds1-14/+4
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.
2005-04-07If two implied casts end up undoing each other, just remove them.Linus Torvalds1-0/+8
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..
2005-04-07Separate explicit and implied casts.Linus Torvalds1-2/+3
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.