aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/validation
AgeCommit message (Collapse)AuthorFilesLines
2020-11-01Merge branch 'typed-cmp'Luc Van Oostenryck3-0/+45
* give an explicit type to compare's operands
2020-11-01linearize __builtin_isdigit()Luc Van Oostenryck2-0/+22
As an experiment about the linearization of builtins, try this easy one (and statically expand it if the argument is constant). Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-11-01fix usage count in linearize_fma()Luc Van Oostenryck1-1/+1
When linearizing __builtin_fma(), the arguments were just assigned but the corresponding usage was not tracked. Fix this. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-11-01testsuite: add a new tag: check-output-returnsLuc Van Oostenryck2-0/+28
The current tags check-output-contains/excludes/pattern are quite powerful and the new check-output-match is easy to use but it can be even simpler. Indeed, a lot of IR simplifications/ canonicalizations can be tested by checking that the expression to be tested is equivalent to another one. This is less precise than some more specific tests but: * it's a big advantage because it's less sensitive to 'noise' like the exact number used by the pseudos or to the results of some new simplifications or canonicalizations * very often, this equivalence is what really matters and not the exact transformation. So, add a new utra-simple-to-use tag: just ask that all functions of the tests return the same specified value (usually 1): check-output-returns: <value> Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-11-01testsuite: add a new tag: check-output-matchLuc Van Oostenryck2-0/+39
The current tags check-output-contains/excludes/pattern are quite powerful, universal, but they often need 'complex' regular expressions with escaping which make them not so nice to read. For testing IR results, a very common pattern is: this instruction must have this (kind of) operand. So, make a new tag for this. It does nothing than can't be done with done with the previous ones, on the contrary, but is much simpler to use: check-output-match(instruction): operand Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-11-01eval_insn: give an explicit type to compare's operandsLuc Van Oostenryck2-2/+0
The return type of IR instructions is stored in the field ::type of struct instruction and this struct has no space to hold the type of the operand(s). This is not a problem for most instructions because there is an easy way to get the operands' type. For example, for binops both types must be the same so they are used interchangeably. However, for compare instructions both types can be different and there is no easy way to get the type of the operands. Currently, this is ignored and creates some errors. It also blocks simplifications that need this type information. But compares instructions need only 2 operands, there is thus one 'slot' left. So, use this slot for the operands' type. This solves the current errors, allows new simplifications and has very little impact on existing code. Of course, this type information needs now to be tracked and adjusted whenever the operands change or an instruction is changed into a compare. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-11-01eval_insn: add testcases for incorrect type in OP_SET_*Luc Van Oostenryck3-0/+47
Because of the lack of type information, compare instruction are not always handled correctly. So, add some testcases for this. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-10-27Merge branches 'cleanup-linearize', 'inline-use', 'inline-def', 'pure-call', ↵Luc Van Oostenryck6-5/+43
'old-style' and 'kill-dead' * cleanup linearize_cond_branch() * OP_INLINE should not use the function symbol * add testcase for missing inline definition * fix testing if a OP_CALL's function is pure * warn on all missing parameter types * kill dead instructions before any other simplifications
2020-10-24Merge branches 'optim-setuimm' and 'optim-unop' into nextLuc Van Oostenryck8-0/+85
* simplify and canonicalize unsigned compares * basic unop simplifications
2020-10-24unop: simplify ~(-x) --> x - 1Luc Van Oostenryck1-1/+0
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-10-24unop: simplify ~(x ^ C) --> x ^ ~CLuc Van Oostenryck1-1/+0
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-10-24unop: simplify ~(C - x) --> x + ~CLuc Van Oostenryck1-1/+0
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-10-24unop: simplify ~(x + C) --> ~C - xLuc Van Oostenryck1-1/+0
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-10-24unop: simplify -(~x) --> x + 1Luc Van Oostenryck1-1/+0
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-10-24unop: simplify -(x - y) --> y - xLuc Van Oostenryck1-1/+0
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-10-24unop: simplify -(x + C) --> -C - xLuc Van Oostenryck1-1/+0
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-10-23canonicalize unsigned compares against 0 or 1Luc Van Oostenryck1-1/+5
Some unsigned compares against 0 or 1 are equivalent to testing equality with 0 (x <= 0, x > 0, x < 1, x >= 1). Canonicalize them to this later, more common form. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-10-23simplify unsigned compares against 0Luc Van Oostenryck1-0/+10
Some unsigned compares against 0 are always true or always false (x < 0 or x >= 0). Simplify them. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-10-23unop: add testcases for unop simplificationsLuc Van Oostenryck7-0/+78
Add a few testcases for the simplification of unary operations. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-10-22warn on all missing parameter typesLuc Van Oostenryck5-5/+13
A warning is given for K&R parameters without type declaration and these parameters are given an implicit type of int to avoid several problems with false errors in the next stages. However, this is only done for K&R functions with the optional parameter type declarations. If the parameters has no type declaration at all, no diagnostic is given and the type is left as incomplete. In consequence, a function defined with a typo like 'int foo(oid)' instead of 'int foo(void)' is left undetected (even with -Wold-style-definition and -Wstrict-prototypes enabled). Fix this by: 1) adding the type check to declare_argument() so that all parameters have a real type. 2) downgrade the diagnostic to a warning for K&R functions. Fixes: 6f7aa5e84dacec8e27a8d70090bba26a1a1276de Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-10-22add testcase for missing inline definitionLuc Van Oostenryck1-0/+30
If the address of an inline function is taken, a definition for this function must be emitted. However, sparse only do this if this inline function is defined before it is used. So add a testcase for this. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-10-22Merge branch 'optim-base' into nextLuc Van Oostenryck15-0/+156
* essential OP_ADD & OP_SUB simplifications
2020-10-21optim: fix some testcases related to bitfield manipulationLuc Van Oostenryck2-5/+8
The patterns used here were based on looser semantic for OP_{SEXT,TRUNC}. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-10-20Merge branch 'bf-sign' into nextLuc Van Oostenryck6-20/+48
* teach sparse about -funsigned-bitfields * let plain bitfields default to signed
2020-10-20sub: simplify x + (y - x) --> yLuc Van Oostenryck1-1/+0
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-10-20sub: simplify (x - y) + y --> xLuc Van Oostenryck1-1/+0
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-10-20sub: simplify x - (y + x) --> -yLuc Van Oostenryck1-1/+0
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-10-20sub: simplify x - (x + y) --> -yLuc Van Oostenryck1-1/+0
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-10-20sub: simplify (x + y) - y --> xLuc Van Oostenryck1-1/+0
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-10-20sub: simplify (x + y) - x --> yLuc Van Oostenryck1-1/+0
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-10-20add: simplify (-x + y) --> (y - x)Luc Van Oostenryck1-1/+0
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-10-20add: simplify (x + -y) --> (x - y)Luc Van Oostenryck1-1/+0
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-10-20sub: simplify (x - -y) --> (x + y)Luc Van Oostenryck1-1/+0
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-10-20sub: simplify (C - y) + D --> eval(C+D) - yLuc Van Oostenryck1-1/+0
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-10-20sub: simplify C - (D - z) --> z + eval(C-D)Luc Van Oostenryck1-1/+0
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-10-20sub: simplify C - (y + D) --> eval(C-D) - yLuc Van Oostenryck1-1/+0
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-10-20sub: canonicalize (0 - x) into -xLuc Van Oostenryck1-1/+0
Not really a simplification in itself but it make some other simplification a little easier (already because there is one argument less to be matched). Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-10-20reassoc: simplify (x # C) # K --> x # eval(C # K)Luc Van Oostenryck1-1/+0
Do this simplification once for all associative binops. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-10-20constants must be truncated to the operation's sizeLuc Van Oostenryck1-1/+0
At expansion phase, when simplified, all constants are truncated to the size of the operations that generate them. This should be done during simplification too because: *) if some constants are sometimes truncated and sometimes sign-extended, CSE will miss some opportunities. *) it's not possible to sign-extend them because it's not always known if the constant is used in a signed context or not. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-10-20add testcases about OP_ADD & OP_SUB simplificationsLuc Van Oostenryck15-0/+171
Add some testcases about basic simplifications of additions and subtractions. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-10-19Merge branch 'builtin-atomic' into nextLuc Van Oostenryck2-0/+39
* fix and complete the evaluation of atomic builtins
2020-10-19builtin: add support for __atomic_clear()Luc Van Oostenryck1-0/+15
The first argument is supposed to be a pointer to a bool, but of course, a volatile qualified pointer should be accepted too. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-10-19builtin: evaluate __sync_*_fetch*()Luc Van Oostenryck1-0/+24
Reuse the generic method for all these builtins. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-10-19Merge branch 'warn-address-builtin' into nextLuc Van Oostenryck1-10/+15
2020-10-16fix null pointer deref on return expression with invalid typeLuc Van Oostenryck1-0/+9
If the evaluation of the return expression failed a following test can dereference the pointer holding the expression's type ... which is null. Bad. Fix this by adding the missing null pointer test. Fixes: 3bc32d46494c404df7905fceaca9156830ff97f1 Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-10-16warn when taking the address of a built-in functionLuc Van Oostenryck1-10/+15
Built-in functions are meant to be expanded by the compiler. As such, they don't have an address. So, issue an error when trying take the address of a built-in function. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-10-16testsuite: fix location of error messagesLuc Van Oostenryck1-3/+3
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-10-14flex-array: fix typo in warning messageLuc Van Oostenryck1-2/+2
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-10-09flex-array: fix location for nesting of flexible membersLuc Van Oostenryck1-2/+2
The warning about the nesting of flexible array members is given with the location of the outer struct or union but that is not very interesting. What is needed is the location of the member causing this nesting. So, fix the warning message to use the member's location. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-10-09Merge branch 'misc'Luc Van Oostenryck1-1/+1
2020-10-09Merge branch 'usual-conv'Luc Van Oostenryck2-1/+11
2020-10-09flex-array: allow arrays of unions with flexible members.Ilya Maximets3-0/+31
There is a common pattern on how to allocate memory for a flexible-size structure, e.g. union { struct flex f; /* Structure that contains a flexible array. */ char buf[MAX_SIZE]; /* Memory buffer for structure 'flex' and its flexible array. */ }; There is another example of such thing in CMSG manpage with the alignment purposes: union { /* Ancillary data buffer, wrapped in a union in order to ensure it is suitably aligned */ char buf[CMSG_SPACE(sizeof(myfds))]; struct cmsghdr align; } u; Such unions could form an array in case user wants multiple instances of them. For example, if you want receive up to 32 network packets via recvmmsg(), you will need 32 unions like 'u'. Open vSwitch does exactly that and fails the check. So, add a new option, -W[no-]flex-array-union, to enable or disable any warning concerning flexible arrays and unions. This option needs at least one of -Wflex-array-{array,nested,union} to be enabled in order to have any effect. Signed-off-by: Ilya Maximets <i.maximets@ovn.org> Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-10-08fix usual conversion of integersLuc Van Oostenryck1-0/+11
The current implementation of the usual conversion doesn't handle correctly the case of 'long' + 'unsigned int' on a 32-bit arch. The resulting type is 'unsigned int' instead of 'unsigned long'. Fix this by following closely the C99's wording. This now gives the expected result for C89 & C99 on 32 & 64-bit archs (as tested with the GCC testsuite). Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-10-08fix evaluation of pointer to bool conversionsLuc Van Oostenryck1-1/+0
The pointer to bool conversion used an indirect intermediate conversion to an int because the pointer was compared to 0 and not to a null pointer. The final result is the same but the intermediate conversion generated an unneeded OP_PTRTOU instruction which made some tests to fail. Fix this by directly comparing to a null pointer of the same type as the type to convert. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-10-06flex-array: remove unneeded testLuc Van Oostenryck1-22/+0
This test was for a failed experience. Remove it. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-10-01testsuite: fix erroneous commentLuc Van Oostenryck1-1/+1
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-10-01flex-array: warn on flexible array in nested aggregate typesLuc Van Oostenryck1-1/+0
A structure or a union containing another aggregate type containing, possibly recursively, a flexible array is quite error prone and make not much sense. So, add an option -Wflexible-array-nested to warn on such usage. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-10-01flex-array: warn an arrays containing a flexible arrayLuc Van Oostenryck1-1/+0
An array of some aggregate type containing, possibly recursively, a flexible array is pretty non-sensical. So, add an option -Wflexible-array-array to warn on such usage. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-10-01flex-array: warn when using sizeof() on a flexible arrayLuc Van Oostenryck1-1/+0
Using sizeof() on a structure containing a flexible array will ignore the 'flexible' part. This is maybe what is expected but maybe not, so add an option -Wflexible-array-sizeof to warn on such usage. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-10-01flex-array: warn if flexible array is not lastLuc Van Oostenryck1-1/+0
Flexible array members must be the last in a structure. Warn if it is not the case. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-10-01flex-array: flexible array members have zero size and alignment is OKLuc Van Oostenryck1-1/+0
When doing the layout of structures, flexible arrays used to not align the resulting structure size. However, the standard specify that while for most purposes flexible arrays can be handled as if not present, they still may add some trailing padding (cfr. C11's 6.7.2.1p18). So, there is no reason to reset the alignment. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-10-01flex-array: add testcasesLuc Van Oostenryck6-0/+133
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-09-16teach sparse about -funsigned-bitfieldsLuc Van Oostenryck6-20/+48
Currently, Sparse treats 'plain' bitfields as unsigned. However, this is this is inconsistent with how non-bitfield integers are handled and with how GCC & clang handle bitfields. So, teach sparse about '-funsigned-bitfields' and by default treat these bitfields are signed, like done by GCC & clang and like done for non-bitfield integers. Also, avoid plain bitfields in IR related testcases. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-09-07builtin: teach sparse to linearize __builtin_fma()Luc Van Oostenryck1-0/+19
The support for the linearization of builtins was already added for __builtin_unreachable() but this builtin has no arguments and no return value. So, to complete the experience of builtin linearization, add the linearization of __builtin_fma(). Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-08-18Merge branch 'union-cast' into masterLuc Van Oostenryck2-0/+47
* teach sparse about union casts
2020-08-17fix evaluate_ptr_add() when sizeof(offset) != sizeof(pointer)Luc Van Oostenryck2-0/+173
For a binary op, both sides need to be converted to the resulting type of the usual conversion. For a compound-assignment (which is equivalent to a binary op followed by an assignment), the LHS can't be so converted since its type needs to be preserved for the assignment, so only the RHS is converted at evaluation and the type of the RHS is used at linearization to convert the LHS. However, in the case of pointer arithmetics, a number of shortcuts are taken and as a result additions with mixed sizes can be produced producing invalid IR. So, fix this by converting the RHS to the same size as pointers, as done for 'normal' binops. Note: On 32-bit kernel, this patch also removes a few warnings about non size-preserving casts. It's fine as these warnings were designed for when an address would be stored in an integer, not for storing an offset like it's the case here. Reported-by: Valentin Schneider <valentin.schneider@arm.com> Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-08-17union-cast: teach sparse about union castsLuc Van Oostenryck2-2/+0
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>
2020-08-15union-cast: add some testcasesLuc Van Oostenryck2-0/+49
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>
2020-08-12Merge branch 'fix-scalar'Luc Van Oostenryck1-0/+13
* fouled types are scalars too (fix is_{scalar,integral}_type()
2020-08-11fix is_scalar_type(): fouled types are scalars tooLuc Van Oostenryck1-0/+13
is_scalar_type() accept SYM_RESTRICT but not SYM_FOULED but both are for integer types (and only for them). So, let it accept SYM_FOULED too. Same for is_integral_type(). Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-08-11bug-assign-op0.c: fix test on 32-bit buildsRamsay Jones1-5/+5
This test was failing on 32-bit because it made the assumption that 'long' is always 64-bit. Fix this by using 'long long' when 64-bit is needed. Fixes 36a75754ba161b4ce905390cf5b0ba9b83b34cd2 Signed-off-by: Ramsay Jones <ramsay@ramsayjones.plus.com> Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-08-09Merge branch 'empty-char' into nextLuc Van Oostenryck2-0/+22
* delay 'empty character constant' warning to phase 5
2020-08-08Merge branch 'wstring-init' into nextLuc Van Oostenryck2-0/+42
* teach sparse about wide string initializers
2020-08-08Merge branch 'sync-cas' into nextLuc Van Oostenryck1-0/+25
* fix evaluation of __sync_{bool,val}_compare_and_swap()
2020-08-08Merge branch 'bad-shift-equal' into nextLuc Van Oostenryck8-53/+403
* fix type evaluation of shifts-assigns * don't warn for UB shifts in dead code
2020-08-08Merge branch 'prev-stream' into nextLuc Van Oostenryck1-0/+11
* fix diagnostic source path from command line * fix diagnostic source path for invalid streams
2020-08-08wstring: extend is_string_type() to also detect wide stringsLuc Van Oostenryck1-1/+0
When evaluating initializers, it must be known if it is for a string or not. But sparse doesn't known about wide strings. Fix this by modifying is_string_type() to use is_wchar_type() in addition of is_byte_type(). Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-08-08wstring: add support for checking size in string initializerLuc Van Oostenryck2-0/+43
A warning is given for string initializers if the LHS array is not large enough to contains the string. But this check doesn't knowns about wide strings. Fix this by selecting the correct char type and use this type for the size calculations. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-08-07add builtin support for __sync_{bool,val}_compare_and_swap()Luc Van Oostenryck1-1/+0
In the kernel, the architecture s390 uses these builtins to implement __atomic_cmpxchg() and friends. These builtins are polymorphic, so they need some special evaluation. These builtins are known to sparse but with a return type of 'int' and the argument's types being ignored. A problem occurs when used on a pointer type: the expected type doesn't match 'int' and it can give warnings like: warning: non size-preserving integer to pointer cast So, improve the support for these builtins by: *) checking the number of arguments *) extract the type from the 1st argument *) set the returned type to this type if needed *) finally, do the typechecking by calling evaluate_arguments() Reported-by: kernel test robot <lkp@intel.com> Link: https://lore.kernel.org/lkml/202008072005.Myrby1lg%25lkp@intel.com/ Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-08-07add testcases for __sync_{bool,val}_compare_and_swap()Luc Van Oostenryck1-0/+26
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-08-06bad-shift: wait dead code elimination to warn about bad shiftsLuc Van Oostenryck5-50/+29
Sparse complains when a shift amount is too big for the size of its operand or if it's negative. However, it does this even for expressions that are never evaluated. It's especially annoying in the kernel for type generic macros, for example the ones in arch/*/include/asm/cmpxchg.h So, remove all warnings done at expansion time and avoid any simplifications of such expressions. Same, at linearization and optimization time but in this case mark the instructions as 'tainted' to inhibit any further simplifications. Finally, at the end of the optimization phase, warn for the tainted instructions. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-08-06shift-assign: restrict shift count to unsigned intLuc Van Oostenryck1-1/+0
After the RHS of shift-assigns had been integer-promoted, both gcc & clang seems to restrict it to an unsigned int. This only make a difference when the shift count is negative and would it make it UB. Better to have the same generated code, so make the same here. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-08-06shift-assign: fix linearization of shift-assignLuc Van Oostenryck3-10/+8
The result of a shift-assigns has the same type as the left operand but the shift itself must be done on the promoted type. The usual conversions are not done for shifts. The problem is that this promoted type is not stored explicitly in the data structure. This is specific to shift-assigns because for other operations, for example add-assign, the usual conversions must be done and the resulting type can be found on the RHS. Since at linearization, the LHS and the RHS must have the same type, the solution is to cast the RHS to LHS's promoted type during evaluation. This solve a bunch of problems with shift-assigns, like doing logical shift when an arithmetic shift was needed. Fixes: efdefb100d086aaabf20d475c3d1a65cbceeb534 Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-08-06shift-assign: add more testcases for bogus linearizationLuc Van Oostenryck2-0/+374
The usual conversions must not be applied to shifts. This causes problems for shift-assigns. So, add testcases for all combinations of size and signedness. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-07-31Merge branch 'array-decl'Luc Van Oostenryck3-0/+40
2020-07-30fix diagnostic source path from command lineLuc Van Oostenryck1-0/+11
Now, diagnostic messages are prepended with the source path. But if the problem comes from a file included directly from the command line like: sparse -include some-buggy-file.c the prepended message will be: (null): note: in included file ... because there isn't a source path yet. So, initialize the source path to "command-line". Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-07-25generic: fix missing inlining of generic expressionLuc Van Oostenryck1-0/+10
Inlining in sparse works slightly differently than what my mental model is: the body is only evaluated after the inline expansion. IOW, an inline function is not evaluated until it is effectively inlined. That's fine but it means that generic expressions also need to be handled during the inlining. However, since the body of inline functions is evaluated just after inline expansion, so (recursively) copying the expression and its type - expression map is quite useless here. So, just copy the expression itself and its control expression to 'isolate' them from evaluation, evaluate it and then just copy the selected expression. Reported-by: kernel test robot <lkp@intel.com> Reported-by: Peter Zijlstra <peterz@infradead.org> Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-07-23allow [*] in array declaratorsLuc Van Oostenryck1-1/+0
Since C99, a '*' is allowed in an abstract array declarator to specify that the array is a VLA with a yet-to-be-determined size. So, accept this construction (but still ignore it for now). Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-07-23simplify & fix parsing of array declaratorsLuc Van Oostenryck1-1/+0
Any type qualifier is valid inside an abstract-array-declarator but currently only 'restrict' is accepted. Also the parsing of this is somehow more complex than needed and done by comparing the identifiers instead of being driven by the keyword table. So, simplify & fix the parsing of these declarators by: 1) using the keyword type KW_QUALIFIER to identify all type qualifier at once. 2) add a new keyword type just for 'static' 3) folding the helper abstract_array_static_declarator() into the main function: abstract_array_declarator(). Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-07-23add testcases for C99 array declaratorsLuc Van Oostenryck2-0/+31
C99 introduced some funky new array declarators, those with 'restrict' or 'static' inside the brackets. Add some testcases for them. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-07-23do not accept comma expressions in array declaratorLuc Van Oostenryck1-1/+0
Comma expressions are not allowed for the size in an array declarator. So, change the parsing of these expressions to only accept assignment-expressions. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-07-23add testcase for comma in array declaratorLuc Van Oostenryck1-0/+12
Comma expressions are not allowed for the size in an array declarator. Add a testcase for this. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-07-22delay 'empty character constant' warning to phase 5Luc Van Oostenryck2-0/+22
A subset of C syntax regarding character constants is: char-constant: ' c-char-sequence ' c-char-sequence: char c-char-sequence char In short, when tokenized, a character constant must have at least one character between the quotes. Consequently, sparse will issue an error on empty character constants (unlike GCC). However, sparse issues the error during tokenization (phase 3), before preprocessing directives are handled (phase 4). This means that code like: #if 0 ... '' #endif will throw an error although the corresponding code is discarded. Fix this by 1) silently accept empty char constants during tokenization 2) issue the diagnostic only when escape sequences are handled. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-07-19prepend diagnostics with source's path and include chainLuc Van Oostenryck1-0/+1
When a diagnostic is issued for a problem in an included file, the message show the include's path but it's often needed to (quickly) know the chain of include files involved. So, if the path associated with the diagnostic is different than the path oft he source file and different from the path of the previous message, prepend the message with a note showing the source file's path. And, if any intermediate include file is concerned, display the include chain (possibly truncated or not displayed at all if too long). Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-07-18Merge branch 'empty-expr'Luc Van Oostenryck3-0/+23
* warn on empty assignments & initializations
2020-07-14Merge branch 'assert-opt-msg'Luc Van Oostenryck1-0/+5
2020-07-14Merge branch 'bad-shift-assign'Luc Van Oostenryck1-0/+115
2020-07-14warn on empty initializationsLuc Van Oostenryck1-1/+0
Currently sparse accepts an empty initialization like: int a = ; Make this an error. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-07-14warn on empty assignmentsLuc Van Oostenryck2-1/+1
Currently sparse accepts an empty assignment like: a = ; Make this an error. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-07-14add testcase for incorrect empty expressionsLuc Van Oostenryck2-0/+24
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-07-13fix evaluation error with assignment of qualified arraysLuc Van Oostenryck2-2/+0
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>
2020-07-10add testcase for missing warning for assignment to constLuc Van Oostenryck1-0/+29
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>
2020-07-10add another testcase with const array/pointerLuc Van Oostenryck1-0/+50
Those are cases that sparse should warn about but doesn't. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-07-09add a testcase for assignment to const <type> (*)[]Luc Van Oostenryck1-0/+7
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>
2020-07-08c2x: message in _Static_assert() is now optionalLuc Van Oostenryck1-0/+5
It seems that in the next version of the standard, the second argument of _Static_assert() will be optional. Nice. Let sparse already support this now. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-07-08Merge branches 'predef-fix', 'predef-helper' and 'simplify-add-pre-buffer'Luc Van Oostenryck1-0/+5
* predefine: fix multi-token predefine * predefine: add helper predefine_{strong,weak}() * predefine: avoid add_pre_buffer() for targets * predefine: simplify add_pre_buffer()
2020-07-06predefine: add testcase for multi-token predefinesLuc Van Oostenryck1-0/+5
The function predefine() and its variants are only valid if they define a single-token value. Add a testcase for this. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-07-06testsuite: add testcase for bogus linearization of >>= & /=Luc Van Oostenryck1-0/+115
When doing a shift operation, both arguments are subjected to integer promotion and the type of the result is simply the type of the promoted left operand. Easy. But for a shift-assignment, things are slightly more complex: -) 'a >>= n' should be equivalent to 'a = a >> n' -) but the type of the result must be the type of the left operand *before* integer promotion. Currently, the linearization code use the type of the right operand to infer of the type of the operation. But simply changing the code to use the type of the left operand will also be wrong (for example for signed/unsigned divisions). Nasty. For example, the following C code: int s = ...; s >>= 11U; is linearized as a logical shift: lsr.32 %r2 <- %arg1, $11 while, of course it's an arithmetic shift that is expected: asr.32 %r2 <- %arg1, $11 So, add a testcase for these. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-07-04testsuite: add new flag '-p' to subcommand 'format'Luc Van Oostenryck1-0/+4
This flag facilitates the creation of testcases for preprocessing. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-07-04avoid multiple warnings when inlining undeclared callsLuc Van Oostenryck1-0/+19
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>
2020-06-23testsuite: fix 'format help' / validate number of argumentsLuc Van Oostenryck1-1/+6
The subcommand 'format help' is broken because the of the way arguments are parsed without validating the number of arguments. Fix this by parsing all arguments (even if there is only one) and validate the number of arguments at the end of the loop. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-06-23teach sparse about __STDC_HOSTED__Luc Van Oostenryck2-0/+22
It seems that some system libraries expect __STDC_HOSTED__ to be always defined. So, teach sparse the options flags -f[no-]{hosted,freestanding} and define __STDC_HOSTED__ accordingly. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-06-20Merge branch 'fix-gensel'Luc Van Oostenryck2-0/+20
2020-06-20gensel: validate the type of the associationsLuc Van Oostenryck1-0/+4
The type in a generic association must correspond to a complete type and not a variably modified type. Add validation for this. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-06-20gensel: controlling expression must be pointer-convertedLuc Van Oostenryck1-1/+0
Following the resolution of DR481, the controlling expression of a generic selection must be array-to-pointer converted and function-to-pointer converted. Do this by adding a call to degenerate(). Reported-by: Marco Elver <elver@google.com> Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-06-19gensel: add testcases from DR481Luc Van Oostenryck1-0/+17
Following the resolution of DR481, the controlling expression is subject to a few different rules. Add the testcases from this defect report. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-06-18Merge branch 'genmacro'Luc Van Oostenryck1-0/+20
* support for builtin macros with arguments * support for __has_feature() & __has_extension()
2020-06-18pre-process: add support for __has_feature() & __has_extension()Luc Van Oostenryck1-1/+0
Add the trivial methods for the expansion of these macros with: c_alignas, c_alignof, c_generic_selections and c_static_assert. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-06-18pre-process: add testcases for __has_feature() & __has_extension()Luc Van Oostenryck1-0/+21
The support for these builtin macros is incoming. So, add some testcases for them. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-06-16testsuite: be less paranoid with timeoutLuc Van Oostenryck1-1/+1
For some testcases, the testsuite use the command 'timeout' to ensure that the test finish after a reasonable amount of time. This is mainly used for some testcases which, in the past, were stuck in an infinite loop. This the command 'timeout' is used with an extra option (-k 1s) to issue a second kill signal in case the first one would have been ignored. However, this extra option is not supported on all implementations (Alpine) and its use seems a bit paranoid for sparse. So, remove this extra option. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-06-12testsuite: plain chars are never compatible with [un]signed charsLuc Van Oostenryck1-0/+19
In standard C, plain chars are either signed or unsigned but are only compatible with themselves, not with signed chars nor with unsigned ones. However, Sparse has this wrong and make them compatible with the corresponding sign-qualified chars. So, add a testcase for this. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-06-09generic: fix crash when nothing matchLuc Van Oostenryck1-0/+23
The code for the generic selection doesn't take in account the fact that the default entry could be absent. Catch the case where nothing matches and issue an error. Fixes: c100a7ab2504f9e6fe6b6d3f9a010a8ea5ed30a3 Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-06-03univ-init: scalar initializer needs some additional checksLuc Van Oostenryck2-0/+35
Currently, -Wno-universal-initializer is simply implemented by simply replacing '{ 0 }' by '{ }'. However, this is a bit too simple when it concerns scalars initialized with '{ 0 }' because: * sparse & GCC issued warnings for empty scalar initializers * initializing a pointer with '{ }' is extra bad. So, restore the old behaviour for scalar initializers. This is done by leaving '{ 0 }' as-is at parse time and changing it as '{ }' only at evaluation time for compound initializers. Fixes: 537e3e2daebd37d69447e65535fc94e82b38fc18 Thanks-to: Ramsay Jones <ramsay@ramsayjones.plus.com> Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-05-28add support for _GenericLuc Van Oostenryck3-0/+240
It's slightly tested but is fine for the latest kernels like https://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git locking/kcsan Note: a known difference with GCC is that it doesn't make the distinction between 'signed char' and a plain 'char' (on platforms where plain char are signed) since it's using the usual type compatbility like used for assignements. Reference: lore.kernel.org/r/20200527235442.GC1805@zn.tnic Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-05-27testsuite: add testcase for duplicated local definitionsLuc Van Oostenryck1-0/+28
Sparse warn when a top-level object is initialized multiple times but doesn't warn when it's a local object. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-05-21Merge branch 'univ'Luc Van Oostenryck2-0/+25
* conditionally accept { 0 } without warnings
2020-05-21Merge branch 'bad-goto'Luc Van Oostenryck21-16/+463
* warn when jumping into statement expressions * warn when using undefined labels * warn on defined but unused labels It's not allowed to do a goto into an expression statement. For example, it's not well defined what should happen if such an expression is not otherwise reachable and/or can be optimized away. For such situations GCC issues an error, clang doesn't and produce a valid IR but Spare produce an invalid IR with branches to unexisting BBs. The goals of the patches in this series are: *) to detect such gotos at evaluation time; *) issue a sensible error message; *) avoid the linearization of functions with invalid gotos. The implementation principle behind these is to add a new kind of scope (label_scope), one for the usual function scope of labels one for each statement expressions. This new scope, instead of being used as a real scope for the visibility of labels, is used to mark where labels are defined and where they're used. Using this label scope as a real scope controling the visibility of labels was quite appealing and was the initial drive for this implementation but has the problem of inner scope shadowing earlier occurence of labels identically named. This is of course desired for 'normal' symbols but for labels (which are normally visible in the whole function and which may be used before being declared/defined) it has the disadvantage of: *) inhibiting the detecting of misuses once an inner scope is closed *) allowing several distinct labels with the same name in a single function (this can be regarded as a feature but __label__ at block scope should be used for this) *) create diffrences about what is permssble or not between sparse and GCC or clang.
2020-05-21univ-init: conditionally accept { 0 } without warningsLuc Van Oostenryck2-0/+25
In standard C '{ 0 }' is valid to initialize any compound object. OTOH, Sparse allows '{ }' for the same purpose but: 1) '{ }' is not standard 2) Sparse warns when using '0' to initialize pointers. Some projects (git) legitimately like to be able to use the standard '{ 0 }' without the null-pointer warnings So, add a new warning flag (-Wno-universal-initializer) to handle '{ 0 }' as '{ }', suppressing the warnings. Reference: https://lore.kernel.org/git/1df91aa4-dda5-64da-6ae3-5d65e50a55c5@ramsayjones.plus.com/ Reference: https://lore.kernel.org/git/e6796c60-a870-e761-3b07-b680f934c537@ramsayjones.plus.com/ Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-05-21bad-label: respect attribute((unused))Luc Van Oostenryck1-0/+6
Currently, attributes on labels were simply ignored. This was fine since nothing was done wth them anyway. But now that Sparse can give a warning for unused labels it would be nice to also support the attribute 'unused' not to issues the warning when not desired. So, add a small helper around handle_attributes() and use this instead of skipping the attributes. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-05-21bad-label: check for unused labelsLuc Van Oostenryck1-1/+0
Issue a warning if a label is defined but not used. Note: this should take in account the attribute 'unused'. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-05-21bad-goto: check declaration of label expressionsLuc Van Oostenryck2-2/+0
Issue an error when taking the address of an undeclared label and mark the function as improper for linearization since the resulting IR would be invalid. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-05-21bad-goto: jumping inside a statement expression is an errorLuc Van Oostenryck6-6/+0
It's invalid to jump inside a statement expression. So, detect such jumps, issue an error message and mark the function as useless for linearization since the resulting IR would be invalid. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-05-21bad-goto: catch labels with reserved namesLuc Van Oostenryck1-1/+0
If a reserved name is used as the destination of a goto, its associated label won't be valid and at linearization time no BB will can be created for it, resulting in an invalid IR. So, catch such gotos at evaluation time and mark the function to not be linearized. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-05-21bad-goto: reorganize testcases and add some moreLuc Van Oostenryck18-13/+332
Reorganize the testcases related to the 'scope' of labels and add a few new ones. Also, some related testcases have some unreported errors other than the features being tested. This is a problem since such tescases can still fail after the feature being tested is fixed or implemented. So, fix these testcases or split them so that they each test a unique feature. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-05-21bad-goto: add testcases for linearization of invalid labelsLuc Van Oostenryck1-0/+19
A goto to a reserved or a undeclared label will generate an IR with a branch to a non-existing BB. Bad. Add a testcase for these. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-05-21bad-goto: add testcase for 'jump inside discarded expression statement'Luc Van Oostenryck2-0/+57
A goto done into an piece of code discarded at expand or linearize time will produce an invalid IR. Add a testcase for it. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-05-21misc: fix testcase typeof-safeLuc Van Oostenryck1-7/+20
This testcase was marked as known-to-fail but it was simply the expected error messages that were missing. So, slightly reorganize the test a little bit, add the expected messages and remove the 'known-to-fail' tag. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-05-19testsuite: add a few testcases for nested functionsLuc Van Oostenryck1-0/+43
Sparse doesn't really support nested functions but is able to parse them correctly. Add some testcases with them so that it continue to catch possible errors concerning them. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-05-19attribute: 'externally_visible' is just another 'declaration' modifierLuc Van Oostenryck2-2/+0
Now that the distinction is made between type modifiers and 'declaration' modifiers, there is no more reasons to parse this attribute differently than other attributes/modifiers. Even more so because this special casing made this attribute to be ignored when placed after the declarator. So, use the the generic code for 'declaration modifiers' to parse this attribute. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-05-17attribute: sort the table of modifier namesLuc Van Oostenryck2-4/+4
It easier to search an item if sorted and this avoid needless conflict when new items are always added at the end of the table. So, sort the table but keep the storage modifers first so that show_typename() & friends still display types as usual. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-04-13Merge branch 'fix-atomic-type'Luc Van Oostenryck2-22/+38
* fix type compatibility of _Atomic types
2020-03-24add support for GCC's __auto_typeLuc Van Oostenryck2-0/+100
Despite the similarity with typeof, the approach taken here is relatively different. A specific symbol type (SYM_TYPEOF) is not used, instead a new flag is added to decl_state, another one in the declared symbol and a new internal type is used: 'autotype_ctype'. It's this new internal type that will be resolved to the definitive type at evalution time. It seems to be working pretty well, maybe because it hasn't been tested well enough. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-03-20teach sparse to linearize __builtin_unreachable()Luc Van Oostenryck3-3/+0
__builtin_unreachable() is one of the builtin that shouldn't be ignored at IR level since it directly impact the CFG. So, add the infrastructure put in place in the previous patch to generate the OP_UNREACH instruction instead of generating a call to a non-existing function "__builtin_unreachable()". Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-03-20add an implicit __builtin_unreachable() for __noreturnLuc Van Oostenryck1-1/+0
The semantic of a __noreturn function is that ... it doesn't return. So, insert an instruction OP_UNREACH after calls to such functions. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-03-20add testcases for OP_UNREACHLuc Van Oostenryck4-7/+74
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-03-16cpp: fix redefinition of a macro during its own expansionLuc Van Oostenryck1-0/+20
The presence of preprocessor directives within the arguments of a macro invocation is Undefined Behaviour but most of these directives, like the conditionals, are well-defined and harmless. OTOH, the redefinition of a macro during its own expansion makes much less sense. However, it can be given a reasonable meaning: * use the initial definition for the macro body * use the new defintion for its arguments, in text order. It's what gcc & clang do but Sparse can't handle this because, during the expansion, a reference to the initial macro's body is not kept. What is used instead is what is currently associated with the macro. Fix this by using the body associated with the macro at the time of its invocation. Testcase-by: Oleg Nesterov <oleg@redhat.com> Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-03-15cpp: remove extra newlines during macro expansionLuc Van Oostenryck3-9/+16
During macro expansion, Sparse doesn't strip newlines from the arguments as required by 6.10.3p10 and done by gcc & clang. So, remove these newlines. Note: the current behaviour may make the preprocessed output more readable (and so may be considered as a feature). Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-03-15cpp: silently allow conditional directives within a macroLuc Van Oostenryck2-1/+41
The presence of preprocessor directives within the arguments of a macro invocation is Undefined Behaviour [6.10.3p11]. However, conditional directives are harmless here and are useful (and commonly used in the kernel). So, relax the warning by restricting it to non-conditional directives. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-03-15make "directive in macro's argument list" a warningOleg Nesterov1-4/+4
The presence of preprocessor directives within the arguments of a macro invocation is Undefined Behaviour [6.10.3p11]. Sparse issues an error for this but most often the result is well defined and is not a problem, processing can continue (for example, when the directive is one of the conditional ones). So, downgrade this sparse_error() to warning() (especially because issuing an error message can hide those coming later). Signed-off-by: Oleg Nesterov <oleg@redhat.com> Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-02-09do the tree inlining during expansion phaseLuc Van Oostenryck1-1/+0
Currently, the tree inlining is done very early, during the evaluation phase. This means that the inlining is done even if the corresponding call belong to a sub-expression that will be discarded during the expansion phase. Usually this is not a problem but in some pathological cases it can lead to a huge waste of memory and CPU time. So, move this inline expansion to ... the expansion phase. Also, re-expand the resulting expression since constant arguments may create new opportunities for simplification. Note: the motivation for thsi is a pathological case in the kernel where a combination of max_t() + const_ilog2() + roundup_pow_of_two() + cpumask_weight() + __const_hweight*() caused Sparse to use 2.3Gb of memory. With this patch the memory consumption is down to 247Mb. Link: https://marc.info/?l=linux-sparse&m=158098958501220 Link: https://lore.kernel.org/netdev/CAHk-=whvS9x5NKtOqcUgJeTY7dfdAHc Reported-by: Randy Dunlap <rdunlap@infradead.org> Originally-by: Linus Torvalds <torvalds@linux-foundation.org> Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-02-09inline: add some testsLuc Van Oostenryck4-0/+108
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-02-06fix type compatibility of _AtomicLuc Van Oostenryck2-22/+38
When _Atomic was introduced, it was treated, for most purposes, like the other qualifiers. However, it's best to consider _Atomic as an qualifier only for syntaxic reasons. In particular, an _Atomic type may have different size and alignment that its corresponding unqualified type. Also, an _Atomic type is never compatible with its corresponding unqualified type, and thus, for type checking, this qualifier must never be ignored. Fix this by removing MOD_ATOMIC from MOD_QUALIFIER. This, essentially, has the effect to stop to ignore MOD_ATOMIC when comparing types. Fixes: ffe9f9fef003d29b65d29b8da5416aff72baff5a Repoted-by: Ramsay Jones <ramsay@ramsayjones.plus.com> Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2019-12-17Merge branch 'msg-wrong-redecl' into nextLuc Van Oostenryck4-15/+60
* improve diagnostic message about wrong redeclaration
2019-12-17Merge branch 'expand-init' (early part) into nextLuc Van Oostenryck15-7/+256
* improve expansion of constant symbols
2019-12-17Merge branch 'top-level-init' into nextLuc Van Oostenryck1-2/+8
* fix testcase with non-constant initializer
2019-12-17fix testcase with non-constant initializerLuc Van Oostenryck1-2/+8
These 2 top-level declarations had a non-constant initializer. Fix that by moving them into a function. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2019-12-15improve diagnostic message about wrong redeclarationLuc Van Oostenryck4-15/+60
The current message is very long (in most cases the position of the previous declaration is past the 80th column) and, while saying that the types differ, doesn't show these types. Change this by splitting the message in 2 parts: - first, on the current position, the main message and the type of the current declaration. - then the type of the previous declaration on its own position. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2019-12-15testcase: remove trailing ';' in commandsLuc Van Oostenryck2-2/+2
Two testcases had their command wrongly terminated by ';'. Fix this by removing this ';'. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2019-12-10fix cost of dereference of symbols with complex typeLuc Van Oostenryck1-1/+0
Currently, in expand_dereference(), the dereference of a symbol with a complex type is considered as costing as high as a non-symbol because it's not recognised it's a symbol. However, both cases should have exactly the same cost since they address calculation amounts to 'symbol + offset'. So, instead of taking in account a single level of symbol + offset let's use a loop for this in order to handle symbol [+ offset]* Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2019-12-10fix simplify_loads() when doing type punningLuc Van Oostenryck2-2/+0
When doing loads simplification for a location where floats & integers are mixed, loads are systematically replaced with the value of their dominating memop (this checks if the corresponding write or load overlaps). However, this must not be done if the involved operations are doing some form of integer/float type punning. Fix this by refusing to convert load of an integer by a previous float value or the opposite. Note: another way to describe this problem would be to say that floats need to have their own memory operations: OP_FSTORE & OP_FLOAD or that instructions need to have some form of 'machine type' in addition of the size (like clang's i32/f32, ...). Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2019-12-10fix expansion of initializer (default)Luc Van Oostenryck1-1/+0
Currently, constant_symbol_value() is doing the expansion of a constant initializer when an explicit one is found but nothing is done if the initilizer is an implicit one. Fix this by: * adding an helper to lookup the corresponding type from offset; * using this helper to get the correct kind for the value: - a 0-valued EXPR_VALUE for integers - a 0.0-valued EXPR_FVALUE for floats. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2019-12-10fix expansion of initializer (mismatching type)Luc Van Oostenryck2-2/+0
Currently, the expansion of constant initializers is done whenever the offset in the initializer match the one being expanded. However, it's not correct to do this expansion of an integer with the initializer for a float and vice-versa. Fix this by adding the corresponding tests to the other tests of the value. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2019-12-10fix expansion of initializer (mismatching size)Luc Van Oostenryck1-1/+0
Currently, the expansion of constant initializers is done whenever the offset in the initializer match the one we're expanding. However, it's not correct to do this expansion if their size doesn't match since in this case the value of one doesn't represent the value of the other. Fix this by adding a check for the size. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2019-12-10degenerated arrays & functions are addressable tooLuc Van Oostenryck2-1/+15
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>
2019-12-10fix addressability marking in evaluate_addressof()Luc Van Oostenryck1-1/+0
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>
2019-12-10add test for constant expansion of complex initializerLuc Van Oostenryck3-0/+53
Constant expansion of symbols with a complex type is not done like for simpler ones. Only the first-level EXPR_INITIALIZER is handled. Add some testcases for this. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2019-12-10add test for dereference cost of symbol with complex typeLuc Van Oostenryck1-0/+21
Currently, in expand_dereference(), the dereference of a symbol with a complex type is considered as costing as high as a non-symbol because it's not recognised it's a symbol. Add a testcase for this. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2019-12-10add test for union castLuc Van Oostenryck1-0/+27
Sparse can't do this yet. So, add a testcase for it. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2019-12-10add testcase for addressability of 'complex' symbolsLuc Van Oostenryck1-0/+24
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>
2019-12-10add testcase for addressability of degenerated symbolLuc Van Oostenryck1-0/+18
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>
2019-12-10add testcase for expansion of default initializersLuc Van Oostenryck2-0/+39
Currently, constant_symbol_value() is doing the expansion of a constant initializer when an explicit one is found but nothing is done for the default/implicit ones. Add a testcase to illustrate this. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2019-12-10split testcases for type punning & constant initializer expansionLuc Van Oostenryck5-5/+66
Several issues were covered by the same testcase. Fix this by splitting the testcases. Also, rename these testcases to a more descriptive name. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2019-12-09Merge branch 'premature-examine' into nextLuc Van Oostenryck1-0/+27
* fix premature examination of dereferenced object
2019-12-09fix premature examination of dereferenced objectLuc Van Oostenryck1-0/+27
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>
2019-12-09Merge branch 'bitfield-size'Luc Van Oostenryck1-0/+30
* improve diagnostic messages concerning bitfields
2019-11-30bitfield: display the bitfield name in error messagesLuc Van Oostenryck1-5/+5
Diagnostics related to a bitfield and issued after parsing didn't display the bitfield name because it was not available. Now that that the name is available, use it in error messages since it helps to find the origin of the problem. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2019-11-30bitfield: oversized bitfields are errorsLuc Van Oostenryck1-1/+0
Till now, a bitfield with a width bigger than its base type only caused a warning but this should be considered as an error since it's generally impossible to emit correct IR code for it. Fix this by issuing an error instead and marking the width as invalid. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2019-11-30bitfield: add testcases for invalid bitfield widthLuc Van Oostenryck1-0/+31
Add some testcases before making related changes. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2019-11-28testsuite: avoid standard includes in the testsLuc Van Oostenryck2-3/+2
These headers are often complex and full of implementation specificities. They have no place in the testsuite. So, remove these includes and replace them by the prototype of the function being used. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2019-11-28Merge branch 'arch-cleanup' into masterLuc Van Oostenryck1-0/+2
2019-11-28arch: add predefines for INT128 only on supported archsLuc Van Oostenryck1-0/+2
The predefines for INT128 were added unconditionally for all archs but only the 64-bit ones support them. Fix this by issuing the the predefines only on 64-bit archs. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2019-11-27Merge branch 'arm-hf' into masterLuc Van Oostenryck5-0/+40
2019-11-27fp-abi: teach sparse about -m{hard,soft}-floatLuc Van Oostenryck1-1/+0
Teach Sparse about these options. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2019-11-27fp-abi: teach sparse about -mfloat-abi on ARMLuc Van Oostenryck4-4/+0
Teach sparse about the -mfloat-abi option and set the related predefines for ARM accordingly. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2019-11-27fp-abi: add tests for ARM's -mfloat-abi=... & -msoft-floatLuc Van Oostenryck5-0/+45
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2019-11-26Merge branch 'arch-cygwin' into masterLuc Van Oostenryck4-1/+27
2019-11-26Merge branch 'static-forward' into masterLuc Van Oostenryck1-9/+10
2019-11-21allow 'static' forward declarationLuc Van Oostenryck1-9/+10
A function or an object can be forward-declared as 'static' and then defining with the keyword 'static' omitted. This is perfectly legal and relatively common. However, Sparse complains that the definition is not declared and asks to the dev if should not be static. This is weird because the function or object *is* declared and *is* static (or at least should be following the standard or GCC's rules). Fix this by letting a new declaration or definition 'inherit' the 'static-ness' of the previous declarations. This is a bit more complicated than simply copying MOD_STATIC and must be done when binding the new symbol because static or extern objects have different scopes. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2019-11-21let function definition inherit prototype attributesLuc Van Oostenryck2-5/+1
It's common to declare a function with the attribute 'pure' or 'noreturn' and to omit the attribute in the function definition. It makes somehow sense since the information conveyed by these attributes are destined to the function users not the function itself. So, when checking declaration/definition, let the current symbol inherit any function attributes present in previous declarations. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2019-11-20propagate function modifiers only to functionsLuc Van Oostenryck2-2/+0
Function attributes need to be parsed differently than the usual specifiers: For example, in code like: #define __noreturn __attribute__((noreturn)) __noreturn void foo(int a); the __noreturn attribute should apply to the function type while a specifier like 'const' would apply to its return type. The situation is quite similar to how storage specifiers must not be handled by alloc_indirect_symbol(). However, the solution used for storage specifiers (apply the modifier bits only after the declarator is reached: cfr.commit 233d4e17c ("function attributes apply to the function declaration")) can't be used here (because the storage modifiers can be applied to the outermost declarator and function attributes may be applied more deeply if function pointers are present). Fix this by: 1) reverting the previous storage-specifier-like solution 2) collect function specifiers MODs in a new separate field in the declaration context (f_modifiers) 3) apply these modifiers when the declarator for the function type is reached (note: it must not be applied to the SYM_FN itself since this correspond to the function's return type; it must be applied to the parent node which can be a SYM_NODE or a SYM_PTR). 4) also apply these modifiers to the declared symbol, if this symbol is a function declaration, to take into account attributes which are placed at the end of the declaration and not in front. Reported-by: Ramsay Jones <ramsay@ramsayjones.plus.com> Fixes: 233d4e17c544e1de252aed8f409630599104dbc7 Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2019-11-19add tests for function attributesLuc Van Oostenryck9-10/+134
Function attributes need to be parsed differently than the usual specifiers. For example, in code like: #define __noreturn __attribute__((noreturn)) __noreturn void foo(int a); the __noreturn attribute should apply to the function type, while a specifier like 'const' would apply to its return type. It's even more clear when function pointers are involved: __noreturn void (*fptr)(void); here too, the attribute should be applied to the function type, not the its return type, nor to the declared pointer type. Add some testcases to cover some of the situations concerning the parsing of these function pointers. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2019-11-15arch: teach sparse about -fshort-wcharLuc Van Oostenryck1-0/+6
This is useful in cgcc for supporting Cygwin which doesn't use a 32-bit type for wchar_t. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2019-11-15function attributes apply to the function declarationLuc Van Oostenryck1-0/+19
Function attributes relate to the function declaration they appear in. Sparse ignore most these attributes but a few ones have a semantic value: 'pure', 'noreturn' & 'externally_visible'. Due to how Sparse parse attributes and how these attributes are stored for functions, the attributes 'pure' & 'noreturn' are applied not to the function itself but its return type if the function returns a pointer. Fix this by extracting these attributes from the declaration context and ensure they're applied to the declarator. Reported-by: John Levon <john.levon@joyent.com> Reported-by: Alex Kogan <alex.kogan@oracle.com> Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2019-11-14arch: fix the signedness of plain charsLuc Van Oostenryck3-1/+21
Some architectures, like ARM or PPC, use 'unsigned' for plain chars while others, like the Intel's, use signed ones. Sparse understands -funsigned-char but by default uses the native signedness. Fix this by setting the proper signedness of plain chars for the archs that Sparse know about. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2019-11-10Merge branch 'eval-typeof' into nextLuc Van Oostenryck1-0/+10
* clarify lazy evaluation & conversion of SYM_TYPEOF
2019-11-10typeof: examine it at show-timeLuc Van Oostenryck1-1/+0
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>
2019-11-10typeof: add a test for unexamined typeofLuc Van Oostenryck1-0/+11
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>
2019-10-30arch: add an option to specify the desired arch: --arch=<arch>Luc Van Oostenryck4-0/+106
Sparse is universal in the sense that the same executable can be used for all architectures. For this, most arch-specific setting can be set with an option and the default values are taken from the host machine. This is working nicely for native targets. However, for cross- compilation, while seeming to work relatively well (thanks to the kernel build system using -m32/-m64 for all archs, for example) things can never work 100% correctly. For example, in the case an X86-64 host machine is used for an ARM target, the kernel build system will call sparse with -m32, Sparse will 'autodetect' the target arch as i386 (x86-64 + -m32) and will then predefine the macro __i386__. Most of the time this is not a problem (at least for the kernel) unless, of course, if the code contains something like: #ifdef __i386__ ... #elif __arm__ ... So, add an option --arch=<arch> to specify the target architecture. The native arch is still used if no such flag is given. Reported-by: Ben Dooks <ben.dooks@codethink.co.uk> Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2019-10-09"graph" segfaults on top-level asmLuc Van Oostenryck1-0/+1
The "graph" binary segfaults on this input: asm(""); with gdb saying (edited for clarity): Program received signal SIGSEGV, Segmentation fault. in graph_ep (ep=0x7ffff7f62010) at graph.c:52 (gdb) p ep->entry $1 = (struct instruction *) 0x0 Sadly, the commit that introduced this crash: 15fa4d60e ("topasm: top-level asm is special") was (part of a bigger series) meant to fix crashes because of such toplevel asm statements. Toplevel ASM statements are quite abnormal: * they are toplevel but anonymous symbols * they should be limited to basic ASM syntax but are not * they are given the type SYM_FN but are not functions * there is nothing to evaluate or expand about it. These cause quite a few problems including crashes, even before the above commit. So, before handling them more correctly and instead of adding a bunch of special cases here and there, temporarily take the more radical approach of stopping to add them to the list of toplevel symbols. Fixes: 15fa4d60ebba3025495bb34f0718764336d3dfe0 Reported-by: Vegard Nossum <vegard.nossum@gmail.com> Analyzed-by: Vegard Nossum <vegard.nossum@gmail.com> Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2019-10-01make 'directive in argument list' clearerLuc Van Oostenryck1-4/+4
The warning 'directive in argument list' is about macros' arguments, not functions' ones. Make this clearer in the warning message. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>