aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/validation
AgeCommit message (Collapse)AuthorFilesLines
2024-01-29Merge branch 'llvm-15'Luc Van Oostenryck2-13/+14
* Support LLVM-15 and later
2024-01-29llvm: fix LLVM 15 deprecation warningsLuc Van Oostenryck1-12/+4
LLVM 15 switched to opaque pointers by default and no longer supports typed pointers. Remove deprecated LLVM calls and update test. Original-patch-by: Vladimir Petko <vladimir.petko@canonical.com> Signed-off-by: Luc Van Oostenryck <lucvoo@kernel.org>
2024-01-20llvm: add a few testcases for integer/pointer conversionLuc Van Oostenryck1-1/+10
Signed-off-by: Luc Van Oostenryck <lucvoo@kernel.org>
2024-01-07testsuite: avoid "warning: stray \ before t" messageLuc Van Oostenryck1-1/+1
Grep (or maybe only some recent versions) complains when using the (wrong) '\\t' pattern. This pattern was used only once to check if the following pattern was at the beginning of an instruction. Prefer to use the more explicit '^.' pattern, already used in other tests. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2023-12-28reassoc: fix infinite loop during reassociationLuc Van Oostenryck1-0/+13
The infinite loop is triggered by some fairly simple code on Zephyr and is caused by some exchange of pseudos done without checking the canonical order. Fix this by adding the check for the canonical order. Also use can_move_to() instead of the simpler one_use() to check the dominance of the moved pseudos. Link: https://github.com/zephyrproject-rtos/zephyr/issues/63417 Link: https://lore.kernel.org/linux-sparse/AD16C022-C5F3-4DA2-A1A0-775E4C95A7A1@intel.com/ Reported-by: Marc Herbert <marc.herbert@intel.com> Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2023-12-16parse: handle __cleanup__ attributehandle-cleanup-attrDan Carpenter1-1/+0
The kernel has recently started using the __cleanup__ attribute. Save a pointer to cleanup function. Signed-off-by: Dan Carpenter <dan.carpenter@linaro.org> Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2023-12-16parse: add testcases for __cleanup__ attributeLuc Van Oostenryck1-0/+34
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2022-06-27Merge branches 'unreplaced' and 'inline'Luc Van Oostenryck1-0/+13
* fix "unreplaced" warnings caused by using typeof() on inline functions * cleanup related to inlining of variadic functions
2022-06-26inline: add testcases for inlining of variadicsLuc Van Oostenryck1-0/+13
Inlining of variadic functions needs some special cases. Add some testcases for this. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2022-06-24fix "unreplaced" warnings caused by using typeof() on inline functionsLuc Van Oostenryck2-0/+45
Currently, sparse do all its inlining at the tree level, during constant expansion. To not mix-up the evaluation of the original function body in case the address of an inline function is taken or when the function can't otherwise be inlined, the statements and symbols lists of inline functions are kept in separated fields. Then, if the original body must be evaluated it must first be 'uninlined' to have a copy in the usual fields. This make sense when dealing with the definition of the function. But, when using typeof() on functions, the resulting type doesn't refer to this definition, it's just a copy of the type and only of the type. There shouldn't be any reasons to uninline anything. However, the distinction between 'full function' and 'type only' is not made during evaluation and the uninlining attempt produce a lot of "warning: unreplaced symbol '...'" because of the lack of a corresponding definition. Fix this by not doing the uninlining if the symbol lack a definition. Note: It would maybe be more appropriate for EXPR_TYPE to use a stripped-own version of evaluate_symbol() doing only the examination of the return and argument types, bypassing the attempt to uninline the body and evaluate the initializer and the statements since there is none of those for an EXPR_TYPE. Link: https://lore.kernel.org/all/202206191726.wq70mbMK-lkp@intel.com Reported-by: kernel test robot <lkp@intel.com> Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2022-06-07fix crash when inlining casts of erroneous expressionsLuc Van Oostenryck1-0/+15
Sparse do inlining very early, during expansion, just after (type) evaluation and before IR linearization, and is done even if some errors have been found. This means that the inlining must be robust against erroneous code. However, during inlining, a cast expression is always dereferenced and a crash will occur if not valid (in which case it should be null). Fix this by checking for null cast expressions and directly returning NULL, like done for the inlining of the other invalid expressions. Link: https://lore.kernel.org/r/e42698a9-494c-619f-ac16-8ffe2c87e04e@intel.com Reported-by: kernel test robot <lkp@intel.com> Reported-by: Yafang Shao <laoar.shao@gmail.com> Reported-by: Yujie Liu <yujie.liu@intel.com> Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2022-05-31Merge branch 'fixes' into masterLuc Van Oostenryck3-0/+29
* fix zero/sign extension of integer character constants * handle clang's option "-meabi gnu" * fix infinite loop when expanding __builtin_object_size() with self-init vars
2022-05-31fix zero/sign extension of integer character constantsLuc Van Oostenryck2-0/+18
An integer character constant has type 'int' but, subtly enough, its value is the one of a 'char' converted to an 'int'. So, do this conversion. Also set the type of wide character constants from 'long' to 'wchar_t'. Link: https://lore.kernel.org/r/20210927130253.GH2083@kadam Reported-by: Dan Carpenter <dan.carpenter@oracle.com> Reported-by: Rasmus Villemoes <linux@rasmusvillemoes.dk> Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2022-05-21fix infinite loop when expanding __builtin_object_size() with self-init varsLuc Van Oostenryck1-0/+11
expand_object_size(), used to expand __builtin_object_size(), recursively try to get the parent initializer. This fails miserably by looping endlessly when the object is a self-initialized variable. For the moment, fix this in the most obvious way: stop the recursion and do not expand such variables. Note: I wouldn't be surprised if these self-initialized variables create other problems elsewhere. Maybe we should remove their initializer and somehow mark them as "do not warn about -Wuninitialized" (well, there is no such warnings *yet*). Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2022-05-20parse: warn about a 'case label' on empty statementRamsay Jones1-0/+22
Commit 0d6bb7e1 ("handle more graciously labels with no statement", 2020-10-26) allowed a label to appear just before the closing brace of a compound statement. This is not valid C (which would require at least a null statement). Similarly, a case label is also not allowed to appear just before a closing brace. So, extend the solution of commit 0d6bb7e1 to issue a warning for case labels and 'insert' a null statement. Note that the next C standard (C23 ?) will allow even more freedom in the placement of labels (see N2508 [1]) and make this placement (along with others) legal C. [1] https://www9.open-std.org/JTC1/SC22/WG14/www/docs/n2508.pdf Signed-off-by: Ramsay Jones <ramsay@ramsayjones.plus.com> Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2022-05-20sparse: fix broken 'memcpy-max-count' checkRamsay Jones1-0/+28
commit a69f8d70 ("ptrlist: use ptr_list_nth() instead of linearize_ptr_\ list()", 2021-02-14) replaced a call to a local helper with a more generic ptr_list function. The local function, argument(), was used to retrieve the 'argno' argument to a function call, counting the arguments from one. This call was replaced by the generic ptr_list_nth() function, which accessed the ptr_list counting from zero. The 'argno' passed to the call to argument() was 3 (the byte count), which when passed to ptr_list_nth() was attempting to access the 4th (non-existent) argument. (The resulting null pointer was then passed to check_byte_count() function, which had an null-pointer check and so did not dereference the null pointer). This effectively disabled the memcpy-max-count check. In order to fix the check, change the 'argno' of 3 to the 'index' of 2. Also, add a simple regression test. Signed-off-by: Ramsay Jones <ramsay@ramsayjones.plus.com> Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-04-20Merge branches misc, cmp-pow2, optim-and-cmp, cmp-and-or and optim-cast-eval ↵Luc Van Oostenryck8-24/+164
into next * no needs to use MARK_CURRENT_DELETED() for multi-jumps * canonicalize ((x & M) == M) --> ((x & M) != 0) when M is a power-of-2 * simplify AND(x >= 0, x < C) --> (unsigned)x < C * simplify TRUNC(x) {==,!=} C --> AND(x,M) {==,!=} C * remove early simplification of casts during evaluation * but this back as simplificaion of TRUNC(NOT(x)) --> NOT(TRUNC(x))
2021-04-19remove early simplification of casts during evaluationLuc Van Oostenryck2-2/+0
The current code will simplify away some casts at evaluation time but doesn't take in account some special cases: * (bool)~<int> is not equivalent to ~(bool)<int> (anything not all 0 or 1) * (float)~<int> is not equivalent to ~(float)<int> which doesn't make sense. * (int)(float)<int> is not a no-op if the (float) overflows This kind of simplification is better done on the IR where the different kind of casts correspond to distinct instructions. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-04-19simplify TRUNC(NOT(x)) --> NOT(TRUNC(x))Luc Van Oostenryck1-1/+0
The goal is double: 1) be able to do the NOT operation on the smaller type 2) more importantly, give the opportunity to the TRUNC to cancel with a previous ZEXT if there is one. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-04-18simplify AND(x >= 0, x < C) --> (unsigned)x < CLuc Van Oostenryck2-2/+0
Such compares with a signed value are relatively common and can be easily be simplified into a single unsigned compare. So, do it. Note: This simplification triggers only 27 times in a x86-64 defconfig kernel. I expected more but I suppose it's because most checks aren't done against a constant or are done with unsigned values. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-04-18add testcases for AND(x > 0, x <= C) --> x u<= CLuc Van Oostenryck2-0/+32
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-04-18canonicalize constant signed compares toward zeroLuc Van Oostenryck1-0/+74
Currently, signed compares against a constant are canonicalized toward the smallest possible constant. So, the following canonicalization are done: x < 256 --> x <= 255 x < -2047 --> x <= -2048 This has two advantages: 1) it maximalizes the number of constants possible for a given bit size. 2) it allows to remove all < and all >= But it has also a serious disadvantages: a simple comparison against zero, like: x >= 0 is canonicalized into: x > -1 Which can be more costly for some architectures if translated as such , is also less readable than the version using 0 and is also sometimes quite more complicated to match in some simplification patterns. So, canonicalize it using 'towards 0' / using the smallest constant in absolute value. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-04-18Merge branches 'fix-phisrc' and 'insert-last-insn' into memops-prepLuc Van Oostenryck6-0/+124
* fix and improve the check that protects try_to_simplify_bb() * fix remove_merging_phisrc() with duplicated CFG edges.
2021-04-18add testcases for simplification of casts.Luc Van Oostenryck4-24/+51
and remove one that didn't made much sense. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-04-17Merge branch 'deadstore'Luc Van Oostenryck3-0/+52
* memops: kill more dead stores
2021-04-17Merge branch 'schecker'Luc Van Oostenryck3-0/+38
* add a symbolic checker
2021-04-13scheck: support pre-conditions via __assume()Luc Van Oostenryck1-0/+6
A lot of simplifications are only valid when their variables satisfy to some conditions (like "is within a given range" or "is a power of two"). So, allow to add such pre-conditions via new _assume() statements. Internally, all such preconditions are ANDed together and what is checked is they imply the assertions: AND(pre-condition) implies assertion 1 ... Note: IIUC, it seems that boolector has a native mechanism for such things but I'm not sure if t can be used here. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-04-13scheck: assert_const()Luc Van Oostenryck1-0/+1
Since, the symbolic checker check expressions at the ... symbolic level, this can be used to check if two expressions are equivalent but not if this equivalence is effectively used. So, add a new assertion (this time not at the symbolic level) to check if an expression which is expected to simplify to a constant is effectively simplified to this constant. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-04-13scheck: allow multiple assertionsLuc Van Oostenryck1-4/+0
With the SMT solver used here, by default, once an expression is checked it's kinda consumed by the process and can't be reused anymore for another check. So, enable the incremental mode: it allows to call boolecter_sat() several times. Note: Another would be, of course, to just AND together all assertions and just check this but then we would lost the finer grained diagnostic in case of failure. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-04-13scheck: assert_eq()Luc Van Oostenryck1-0/+5
Testing the equivalence of two sub-expressions can be done with with a single assertion like __assert(A == B). However, in some cases, Sparse can use the equality to simplify the whole expression although it's unable to simplify one of the two sub-expressions into the other. So, add a new assertion, __assert_eq(), testing the equality of the two expressions given in argument independently of each other. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-04-13scheck: add a symbolic checkerLuc Van Oostenryck3-0/+30
Some instruction simplifications can be quite tricky and thus easy to get wrong. Often, they also are hard to test (for example, you can test it with a few input values but of course not all combinations). I'm used to validate some of these with an independent tool (Alive cfr. [1], [2]) which is quite neat but has some issues: 1) This tool doesn't work with Sparse's IR or C source but it needs to have the tests written in its own language (very close to LLVM's IR). So it can be used to test if the logic of a simplification but not if implemented correctly. 2) This tool isn't maintained anymore (has some bugs too) and it's successor (Alive2 [3]) is not quite as handy to me (I miss the pre-conditions a lot). So, this patch implement the same idea but fully integrated with Sparse. This mean that you can write a test in C, let Sparse process and simplify it and then directly validate it and not only for a few values but symbolically, for all possible values. Note: Of course, this is not totally stand-alone and depends on an external library for the solver (Boolector, see [4], [5]). Note: Currently, it's just a proof of concept and, except the included tests, it's only very slightly tested (and untested with anything more complex than a few instructions). [1] https://blog.regehr.org/archives/1170 [2] https://www.cs.utah.edu/~regehr/papers/pldi15.pdf [3] https://blog.regehr.org/archives/1722 [4] https://boolector.github.io/ [5] https://boolector.github.io/papers/BrummayerBiere-TACAS09.pdf Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-04-04fix null-pointer crash with with ident same as one of the attributesLuc Van Oostenryck1-0/+12
match_attribute() will crash when the token has the same identifier as one of the attributes but is not an attribute. In this case, the corresponding symbol_op will be null but this is not checked. This seems to happen only with old-style declarations. Fix this by adding the missing null-check. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-04-02fix remove_merging_phisrc()Luc Van Oostenryck1-1/+0
The current implementation of remove_merging_phisrc() can't work correctly when these phi-sources belong to a basic block with several children to the same target basic block (this happens commonly with OP_SWITCH). Fix this by directly scanning the source basic block for the presence of any phi-source. Once identified, the processing is kept unchanged: remove these phi-sources if a sibling phi-source will 'overwrite' them in the target block. Fixes: 2fdaca9e7175e62f08d259f5cb3ec7c9725bba68 Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-03-30Merge branch 'testsuite-extra' (early part)Luc Van Oostenryck1-0/+11
* testsuite: add option '-r' to 'test-suite format'
2021-03-28correctly count phi argumentsLuc Van Oostenryck1-0/+27
In a phi-node,pseudo_list_size() can't be used for counting its arguments because VOIDs must be ignored. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-03-26additional testcase for remove_merging_phisrc()Luc Van Oostenryck1-0/+24
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-03-25kill redundant stores (local)Luc Van Oostenryck1-1/+0
A store is called 'redundant' when the corresponding location already contains the value that will be stored. This patch removes such stores in the case where the memops which make them redundant is in the same basic block. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-03-25kill parent's dead stores tooLuc Van Oostenryck2-2/+0
kill_dominated_stores() identify and remove dead stores (stores unneeded because the same location is overwritten later by another store) only when both stores are in the same basic block. Slightly improve this by also handling the case when the dead store is in a parent BB of the "live" store. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-03-24add testcases for stores simplificationsLuc Van Oostenryck3-0/+55
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-03-21testsuite: add option '-r' to 'test-suite format'Luc Van Oostenryck1-0/+11
Because laziness is a virtue, add an option '-r' to the 'format' subcommand of the testsuite to quickly create a test template for linearized code which should just return 1. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-03-19fix phisources during SWITCH-BR conversionLuc Van Oostenryck1-1/+0
Like for CBR-BR conversion, when a target BB containing one or several phi-nodes is removed from an OP_SWITCH, the corresponding phi-source must be removed from the phi-node. However this is not done yet. Changing this by adding some code to convert_to_jump() to remove all phi-sources from the discarded targets if the converted instruction is an OP_SWITCH. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-03-19use convert_to_jump() when converting a CBR with same targetsLuc Van Oostenryck1-1/+0
If a conditional branch has identical targets, it should be converted to a simple jump. This is done but using its own code. Change this by using the existing convert_to_jump() instead. This also allows any redundant phi-sources to be removed. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-03-19fix phisources during CBR-BR conversionLuc Van Oostenryck2-2/+0
When a parent is removed from a BB containing one or several phi-nodes, the corresponding phi-sources must be removed from the phi-node. However this is not done and consequentially: * it becomes impossibly to correctly reason about the flow of values through these phi-nodes. * simplifications are missed (e.g. if-conversion). Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-03-19add testcases to check if phi-sources from removed targets are removed tooLuc Van Oostenryck4-0/+78
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-03-13canonicalize ((x & M) == M) --> ((x & M) != 0) when M is a power-of-2Luc Van Oostenryck1-0/+12
and same for its dual: ((x & M) != M) --> ((x & M) == 0) Beside the canonicalization itself, these simplifications are useful because the compare against 0 can often be further simplified (for example when it is used by OP_CBR or OP_SELECT). Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-03-12Merge branches 'fix-ssa' and 'cmp-and-or' into nextLuc Van Oostenryck8-4/+113
* fix SSA conversion of mismatched memops * simplify CMP(AND(x,M), C) and CMP(OR(x,M), C)
2021-03-10no needs to use MARK_CURRENT_DELETED() for multi-jumpsLuc Van Oostenryck0-0/+0
MARK_CURRENT_DELETED() was added for the case(s) where an element must be removed from the list but the address of the other elements must not be changed. In this case of effectively removing the element from it list, the element is 'marked' as deleted in the list and the list walking macros will later take this in account. However, this is never needed for multi-jumps. So, use the usual DELETE_CURRENT_PTR() for them. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-03-10simplify (x | M) cmpu CLuc Van Oostenryck1-1/+0
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-03-10simplify (x | M) cmps CLuc Van Oostenryck1-1/+0
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-03-10simplify (x | M) {==,!=} CLuc Van Oostenryck1-1/+0
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-03-10simplify (x & M) {==,!=} CLuc Van Oostenryck1-1/+0
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-03-10simplify (x & M) cmps 0Luc Van Oostenryck1-1/+0
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-03-10simplify (x & M) cmpu CLuc Van Oostenryck1-1/+0
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-03-10simplify (x & M) cmps CLuc Van Oostenryck1-1/+0
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-03-10add testcases for constant compares against AND/ORLuc Van Oostenryck7-0/+116
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-03-10change testing of signed compares against SMIN or SMAXLuc Van Oostenryck1-4/+4
These tests are written by testing if the comparisons are equal to their expected value: 0 or 1. So, a compare of a compare but such compares of compare have their own simplification which defeats what's tested here. So, rewrite the test to avoid such compares of compare. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-03-09ssa: fix conversion with mismatched size or offsetLuc Van Oostenryck1-1/+0
The SSA conversion works under the assumption that all the memory operations on a given symbol always refer to the same object. So, exclude the conversion of variables where: * memory operations do not always match in size or offset * there is an implicit integer/float conversion. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-03-09ssa: avoid SSA conversion of packed bitfieldsLuc Van Oostenryck1-1/+0
Packed bitfields are incompatible with the SSA conversion which works on the assumption that memory operations are done on the whole symbol. So, directly exclude packed bitfields from the SSA conversion. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-03-09ssa: add some testcases for mismatched memopsLuc Van Oostenryck2-0/+85
The SSA conversion is incorrect when the size or offset of the memory operations doesn't match. It shouldn't be done at all. So, add a few testcases for this. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-03-01Merge branch 'fix-restrict' into nextLuc Van Oostenryck1-0/+22
* fix the type in the assignment of 0 to a restricted variable
2021-02-28asm-out0: fix a test failure on 32-bit systemsRamsay Jones1-1/+1
Signed-off-by: Ramsay Jones <ramsay@ramsayjones.plus.com> Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-02-25Merge branch 'objsize'Luc Van Oostenryck3-0/+68
* expand __builtin_object_size()
2021-02-25expand __builtin_object_size()Luc Van Oostenryck3-0/+68
__builtin_object_size() is one of these builtins that must be somehow expanded because it can't possibly be implemented at runtime. It's used by the kernel's copy_{to,from}_user() and the 'fortified' string functions, as well as by userspace's 'checked string/memory functions' like __builtin___memcpy_chk(). So, use the normal builtin expansion interface for this one too. This gets rid of 2/3 of them when used on the kernel and shaves ~0.5% of the total IR code (with x86's defconfig). Notes: 1) What is covered is an object symbol, with an optional designator of arbitrary complexity, ignoring casts and accessed via an optional chain of simple dereferences. Maybe some access path need to be added. 2) Anything with dynamic value is currently considered either as unknown (VLAs, variables or parameters) or left for a later stage (any function calls, including functions known to allocate memory given that attribute alloc_size() is not yet supported). 3) It's not totally clear to me when to give up (and thus return 'size unknown') and when things can or must be left to the simplification phase. This matters because __builtin_object_size() is relatively often used with __builtin_constant_p(). 4) Currently, only type 0 is really supported. Given the way designators are evaluated and expanded (information is lost because the expressions are overwritten), to support the other types, the expansion of __builtin_object_size() should be done during evaluation itself, much like it's done for sizeof() and offsetof(). Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-02-24fix eval of the assignment of a non-restricted value to a restricted variableLuc Van Oostenryck1-0/+22
Assignment to restricted variables are severely ... restricted. Nevertheless, one value is always fine because it has always the same bit representation: 0. So, 0 is accepted unconditionally but this creates a problem because the type of this 0 needs to be adjusted. Otherwise 0 (int) is assigned as-is even on restricted variable with a different bit-length. Fix this by casting the value to the target type before accepting it. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-02-21asm-mem: teach dominates() about OP_ASMLuc Van Oostenryck1-1/+0
The function dominates() needs to know if an OP_ASM instruction may modify. Use the information now available in the instruction to return the answer. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-02-21asm-mem: add testcase for missing reload after asm memopsLuc Van Oostenryck1-0/+15
Memory simplification is done with the help of the function dominates() which determine when memory instructions interfere. This function handles OP_CALLs, OP_LOADs and OP_STOREs but memory can also be changed via OP_ASMs. Add a testcase showing this. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-02-21asm: output *memory* operands need their address as *input*Luc Van Oostenryck1-1/+0
The addresses needed by memory output operands are linearized (and placed) after the ASM instruction needing them. So, split add_asm_output() in 2 parts: one generating only the addresses for memory operands and called before issuing the body, and another one doing the usual copy of (non-memory) output operands back into their corresponding variables. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-02-21asm: add testcase for problem with output addressesLuc Van Oostenryck1-0/+26
The addresses needed by memory output operands are linearized (and placed) after the ASM instruction needing them. So, add a test case for this. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-01-31Merge branch 'fix-join-cond'Luc Van Oostenryck1-0/+19
* fix add_join_conditional() when one of the alternative is VOID
2021-01-31fix add_join_conditional() when one of the alternative is VOIDLuc Van Oostenryck1-0/+19
add_join_conditional()'s job is to take the 2 alternatives of the conditional, make a phi-node from them and return the corresponding pseudo but if one of the alternatives is not available it's useless to create a phi-node and the other alternative can then directly be returned. The problem is that in this later case, the pseudo directly returned is the PSEUDO_PHI of the corresponding phi-source. This gives erroneous code like, for example: phisrc.32 %phi1 <- $0 ret.32 %phi1 instead of: ret.32 $0 since the %ph1 should only be used by a phi-node instruction. Fix this by returning phi-source's operand instead. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-01-26cmps: canonicalize SEL(x > 0, a, -a) --> SEL(x >= 0, a, -a)Luc Van Oostenryck1-1/+0
When computing the absolute value using an expression like: (a > 0) ? a : -a it's irrelevant to use '>' or '>=', both will give the same result since 0 is its own negation. Canonicalize these equivalent expressions, such that OP_GE is always used. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-01-26cmps: canonicalize SEL(x {<,<=} y, a, b) --> SEL(x {>=,>} y, b, a)Luc Van Oostenryck1-1/+0
Both compares and OP_SELECT are anti-symmetrical: swapping the arguments is equivalent to inversing the condition. As consequence, when combined, they're symmetrical: swapping the arguments of the compare (or equivalently reversing the direction of the compare) and swapping the operand of the OP_SELECT is a no-op, both forms are equivalent. So, canonicalize these to always use OP_GT or OP_GE. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-01-26cmps: canonicalize signed compares with constantLuc Van Oostenryck1-1/+0
Modify the constants to canonicalize (x < C) to (x <= (C-1)) and (x <= C) to (x > (C-1)). This choice is partially arbitrary but 1) it's the one with the smallest positive constants, 2) it eliminates all OP_SET_LT & OP_SET_GE with a constant. A disadvantage of this choice is that we lost some compares with 0: (x < 0) is now canonicalized into (x <= -1). Note: Another good choice would be to canonicalize using the smallest absolute constants. This would keep compares with 0 but would also keep the 4 kinds of comparison. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-01-26cmps: canonicalize SMIN/SMAX +- 1 --> EQ/NELuc Van Oostenryck1-1/+0
Compares with SMIN + 1 or SMAX - 1 are equivalent to an equality testing. For example, (x < SMIN + 1) is the same as (x == SMIN). Canonicalize these to the equality testing since these are usually simpler to handle. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-01-26cmps: canonicalize signed compares with SMIN/SMAXLuc Van Oostenryck1-1/+0
The remaining compares with SMIN or SMAX are equivalent to an equality testing. For example, (x < SMAX) is the same as (x != SMAX). Canonicalize these to the equality testing since these are usually simpler to handle. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-01-26cmps: simplify signed compares with SMIN or SMAXLuc Van Oostenryck1-1/+0
Simplify away signed compares with SMIN or SMAX which can be statically be determined to be always true or always false. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-01-26cmps: add testcases for simplification of signed comparesLuc Van Oostenryck6-0/+106
Signed compares miss some simplifications/canonicalizations. Add some testcases for them. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-01-26cmps: fix simplification of sext(x) + signed compare of {SMAX,SMIN}Luc Van Oostenryck1-11/+35
Commit a1c1b9236d5d ("cmp: simplify sext(x) cmps {SMAX,SMIN}") had a double error (wrong size and wrong compare direction) which was hidden because of too narrow testcases. So, fix the simplification and extend the testcases. Fixes: a1c1b9236d5d4af1681a45ced26f8350bd7721c2 Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-01-24simplify LSR + SEXT into ASRLuc Van Oostenryck1-0/+27
A logical shift right followed by a sign extension is equivalent to an arithmetic shift. Teach this to sparse. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-12-29packed: add support for __packed structLuc Van Oostenryck6-6/+0
Now that the 'packed' attribute is parsed and propagated into the type system, adapt the layout of structures. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-12-29struct-attr: fix: do not ignore struct/union/enum type attributesLuc Van Oostenryck5-5/+0
GCC's syntax for type attributes is specified as: An attribute specifier list may appear as part of a struct, union or enum specifier. It may go either immediately after the struct, union or enum keyword, or after the closing brace. The former syntax is preferred. Where attribute specifiers follow the closing brace, they are considered to relate to the structure, union or enumerated type defined, not to any enclosing declaration the type specifier appears in, and the type defined is not complete until after the attribute specifiers. In the section about type attributes, it's also said: You may specify type attributes in an enum, struct or union type declaration or definition by placing them immediately after the struct, union or enum keyword. A less preferred syntax is to place them just past the closing curly brace of the definition. So, while placing the attribute after the closing curly is not preferred, it is cleary legal (and it seems to be much more popular than placing them just after the struct, union or enum keyword). However, currently sparse doesn't handle this correctly: - these attributes are parsed in declaration_specifiers() and added to the current decl_state - when the ';' ending the type declaration is reached, the plain struct/union/enum is used and the content of the decl_state is simply ignored. - if the declaration is for a variable, then those attributes are assigned to the variable (but not to the type). Fix this by calling handle_attribute() once we have reached the closing '}' of a struct/union/enum definition and applying these attributes, if any, directly to the current base type. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-12-29struct-attr: prepare to handle attributes at the end of struct definitions (1)Luc Van Oostenryck1-2/+2
Type attributes for struct can be placed either just after the keyword 'struct' or after the '}' ending its definition but this later case is currently ignored. Prepare the handling of this by factoring the code common to both cases in a single place. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-12-29add testcases for packed bitfieldsLuc Van Oostenryck6-0/+172
Currently, packed bitfields are not handled correctly. Add some testcases for them. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-12-29add testcases for packed structuresLuc Van Oostenryck2-0/+57
Currently, packed structs are not handled correctly. Add some testcases for them. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-12-29add testcases for type attributesLuc Van Oostenryck4-0/+91
Currently, type attributes are not handled correctly. Add some testcases for them. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-12-29add testcases for enum attributesLuc Van Oostenryck1-0/+29
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-12-29add testcases for exotic enum valuesLuc Van Oostenryck1-0/+28
There is more than one complexity in the evaluation of enums. Add a test for enums with 'exotic' values not covered in other tests. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-12-29add testcases for dubious enum valuesLuc Van Oostenryck1-0/+18
sparse accept any type of integral value for enumerators but address constants are also accepted, which is 'strange'. Add a testcase for such 'enums'. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-12-11testsuite: fix parsing of tags used in the testcasesLuc Van Oostenryck3-4/+5
In testcases' tags, if a value contains 'check-' then this value will be used as the tagname instead of the value. Fix this by adding a bit more context in the regexp used for parsing these. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-12-10move check_access() to late_warnings()Luc Van Oostenryck1-0/+31
check_access() is called at each run of simplify_loads(). However, a bad access can belong to a dead branch and thus a bad access warning can be issued for code that is not executed, maybe specifically excluded. So, move check_access() to late_warnings(), where all optimizations have been done. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-12-02Merge branches 'fix-kill_dominated_stores' and 'kill-dead-loads' into nextLuc Van Oostenryck1-0/+22
* memops: fix wrong killing of stores partially dominated by a load * memops: kill dead loads before phi-node conversion
2020-11-29memops: kill dead loads before phi-node conversionLuc Van Oostenryck1-0/+22
During load simplification it may happen that a load is unused but if this fact is ignored and the usual conversion to a phi-node is made, then this value may seem to be needed and can't anymore be simplified away. Fix this by removing dead loads during load simplification. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-11-28fix wrong killing of stores partially dominated by a loadLuc Van Oostenryck1-0/+29
When a partial but overlapping load is followed by a store, this load is not considered as dominating the store. This is a problem for kill_dominated_stores() because the load will be simply ignored. For example, in code like: union { u64 l; int i; } u; int i; u.l = x; i = u.i; u.l = y; The load will be ignored, then the first store can be ignored too and the value of 'i' will be undefined (but actually set to 0). The root of the problem seems to be situated in dominates() where a load is considered as dominating another memop only if both correspond to the same 'access' (address and size). This is probably fine when the other memop is itself a load (because the value of the first load can't be reused for the second one) but it's not when the other memop if a store. So, to be safe, consider different-but-overlapping memops as neither dominated or non-dominated but as "don't know". Note: as explained here above, this can *probably* be relaxed when both memops are loads but it's not 100% clear to me yet and I found no examples where it actually make a difference. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-11-28Merge branch 'bit-trans' into nextLuc Van Oostenryck9-0/+228
* factorize (x OP1 z) OP2 (y OP1 z) into (x OP2 y) OP1 z * factorize SHIFT(x, s) OP SHIFT(y, s) into SHIFT((x OP y), s) * factorize SEL(x, OP(y,z), y) into OP(SEL(x, z, 0), y) * convert SEL(x & BIT1, BIT2, 0) into SHIFT(x & BIT1, S)
2020-11-27convert SEL(x & BIT1, BIT2, 0) into SHIFT(x & BIT1, S)Luc Van Oostenryck1-1/+0
Convert an expression like: (x & (1 << A)) ? (1 << B) : 0 into: (x & (1 << A)) << (B - A) or: (x & (1 << A)) >> (A - B) Suggested-by: Linus Torvalds <torvalds@linux-foundation.org> Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-11-27factorize SEL(x, OP(y,z), y) into OP(SEL(x, z, 0), y)Luc Van Oostenryck1-1/+0
'Factorize' and expression like: x ? (y | z) : y; into (x ? z : 0) | y; and some positional variants as well as replacing '|' by '+' or '^'. Note: it's not very clear if this is really an improvement but it allows some very nice simplification of 'bits translations'. Note: the same can be done for others operations, for example it can be done for '&' if '0' (the neuter value for '|', '+' and '^') by '~0' (same with '*' and '1'). Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-11-27add testscases for 'bits translation' optimizationLuc Van Oostenryck2-0/+44
Add some testcase related to the simplification of expressions like: if (val1 & BIT1) val2 |= BIT2; into val2 |= (val1 & BIT1) {SHL/LSR} |BIT2-BIT1|; Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-11-27factorize SHIFT(x, s) OP SHIFT(y, s) into SHIFT((x OP y), s)Luc Van Oostenryck3-3/+0
Factorize bitwise OPs of shifts with identical counts. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-11-27factorize (x OP1 z) OP2 (y OP1 z) into (x OP2 y) OP1 zLuc Van Oostenryck4-4/+0
Factorize common distributive operations: (x * z) + (y * z) --> (x + y) * z (x | z) & (y | z) --> (x & y) | z (x & z) | (y & z) --> (x | y) & z (x & z) ^ (y & z) --> (x ^ y) & z Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-11-27add testscases for some factorization of distributive operationsLuc Van Oostenryck7-0/+193
Add some testcases for factorizations of: (x * z) + (y * z) --> (x + y) * z (x | z) & (y | z) --> (x & y) | z (x & z) | (y & z) --> (x | y) & z (x & z) ^ (y & z) --> (x ^ y) & z and (x << s) | (y << s) --> ((x | y) << s) and same for &, ^, LSR and ASR. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-11-26fix trivial_phi() when the target is before the single valueLuc Van Oostenryck1-0/+20
A phi-node is called 'trivial' if it only reference itself and a single other value. In this case the only possible value for the phi-node is this single other value which can thus replace the phi-node. However, the current code get this slightly wrong when the first referenced value is itself and not the other value. Fix this by moving up the test checking if it references itself. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-11-24Merge branch 'optim-not' into nextLuc Van Oostenryck8-11/+80
* put PSEUDO_ARGS and PSEUDO_REGs in canonical order too * simplify (~x {&,|,^} x) --> {0,~0,~0} * simplify ((x cmp y) {&,|,^} (x !cmp y)) --> {0,1,1}
2020-11-22Merge branch 'optim-cgoto' into nextLuc Van Oostenryck3-0/+54
* simplification of computed gotos with 1 or 2 targets
2020-11-22not: simplify ((x cmp y) {&,|,^} (x !cmp y)) --> {0,1,1}Luc Van Oostenryck1-1/+0
Simplify bitwise operations on a compare and its complement into 0 (for &) or 1 for (| and ^). Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-11-22not: simplify (~x {&,|,^} x) --> {0,~0,~0}Luc Van Oostenryck1-1/+0
Simplify bitwise operations on a pseudo and its complement into 0 (for &) or ~0 for (| and ^). Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-11-22canon: put PSEUDO_REGs in canonical order tooLuc Van Oostenryck1-1/+0
Currently, only binops containing PSEUDO_VAL, SYM or ARG were put in canonical order. This means that binops containing only PSEUDO_REGs are not ordered. This is not directly a problem for CSE because commutativity is taken in account but: * more combination need to be checked during simplification * 'anti-commutative' operations like (a > b) & (b < a) are not recognized as such. So, take PSEUDO_REGs in account when checking if operands are in canonical order. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-11-22canon: put PSEUDO_ARGs in canonical order tooLuc Van Oostenryck3-12/+11
Currently, only binops containing PSEUDO_VAL or PSEUDO_SYM were put in canonical order. This means that binops containing only PSEUDO_ARGs or PSEUDO_REGs are not ordered. This is not directly a problem for CSE because commutativity is taken in account but: * more combination need to be checked during simplification * 'anti-commutative' operations like (a > b) & (b < a) are not recognized as such. So, as a first step, also take PSEUDO_ARGs in account when checking if operands are in canonical order. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-11-22not: add testcases for canonicalization & simplification of negationsLuc Van Oostenryck6-0/+73
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-11-21add a new instruction for label-as-valueLuc Van Oostenryck1-1/+0
Convert OP_SETVAL of a label into a new instruction: OP_LABEL. There is 2 reasons to do this: *) there is slightly less checking to be done in later phases (since OP_SETVAL can be for labels but also strings) *) OP_SETVAL is CSEd but this is largely useless because this instruction is hashed on the expression's address and these are (most) often not shared. With a separate instruction for label expressions, their CSE is now OK because the hashing is done on the BB. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-11-21simplify CGOTO(SEL(x, L1, L2)) into CBR x, L1, L2Luc Van Oostenryck1-1/+0
A computed goto having as operand a select of 2 statically known addresses (OP_SETVAL/EXPR_LABEL) is equivalent to a simple conditional branch. Simplify such computed goto into the corresponding OP_CBR Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-11-21simplify OP_COMPUTEDGOTO with unique and known targetLuc Van Oostenryck1-1/+0
If the OP_COMPUTEDGOTO's source pseudo is defined by a single OP_SETVAL/EXPR_LABEL, then the corresponding basic block is the only possible destination and the computed goto can then be simplified into a simple branch. So, convert such computed goto into a simple OP_BR which may then participate in other flow simplifications. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-11-21add testcases for COMPUTEDGOTO simplificationLuc Van Oostenryck3-0/+57
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-11-18unqual: statement expressions should drop qualifiersLuc Van Oostenryck1-1/+0
Statement expressions should be subjected to lvalue-conversion and thus should drop qualifiers. Fix this by calling unqualify_type() after array-to-pointer conversion. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-11-18unqual: comma expressions should drop qualifiersLuc Van Oostenryck1-1/+0
Comma expressions should be subjected to lvalue-conversion and thus should drop qualifiers. Fix this by calling unqualify_type() after array-to-pointer conversion. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-11-18unqual: add testcasesLuc Van Oostenryck4-0/+75
Add some testcases related to qualifier dropping / lvalue conversion. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-11-18casts should drop qualifiersLuc Van Oostenryck1-0/+14
Casts should drop qualifiers but Sparse doesn't do this yet. The fix seems pretty simple: after having evaluated the type of the cast, if this type is a SYM_NODE and contains qualifiers, make a copy of the type with the qualifiers removed and use this copy as the type. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-11-17cfg: early CFG simplificationLuc Van Oostenryck9-11/+18
The linearization step sometimes creates a lot of intermediate basic blocks, often containing just a branch. Their presence often make things more complicated than needed (more work to do in later phases, visual clutter when inspection the IR 'by hand') and they can sometimes, indirectly hinder some optimizations. Happily, most of them can trivially be optimized away. So, add a CFG simplification phase running very early and doing: *) jump threading (eliminate jump to jump) *) merge single-child/sinle-parents basic blocks. These changes slightly decrease the number of 'context imbalance' warnings (32 less on a total of 995 warnings) and the size of the generated IR (only ~0.4% but this is very significant relatively to most other simplifications). They also seem to improve the kernel tests' running time: before after real 4m19.261s real 4m17.548s user 72m03.634s user 71m34.642s sys 29m05.573s sys 29m01.856s but it's probably just noise. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-11-17cfg: call simplify_memops() unconditionally.Luc Van Oostenryck2-0/+37
Currently, in the main optimization loop, simplify_memops() is only called if REPEAT_SYMBOL_CLEANUP have been set. This has (at least) two problems: 1) simplify_memops() may itself create other 'symbol cleanup' opportunities. That's fine and when it happens REPEAT_SYMBOL_CLEANUP is correctly set but this is directly lost because repeat_phase is cleared just after. So, loads and stores are not always optimized away as they should. 2) Loads & stores are not always done directly on symbols, in fact, it often happens that they are done on some PSEUDO_REG. Here too, loads and stores are not always optimized away as they should. So, call simplify_memops() unconditionally. Note: this have only very small effects on the tests' running time: before after after too real 4m18.001s real 4m18.655s real 4m19.4 user 71m32.911s user 72m02.701s user 72m06.6 sys 29m06.523s sys 29m01.721s sys 29m06.8 which is under the noise I usually have. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-11-17cfg: remove phi-sources when merging BBsLuc Van Oostenryck1-1/+0
When merging two basic blocks, it may happen that both of theses blocks contain a phi-source for the same phi-node. In this case, only the phi-source from the bottom BB must be taken in account, it kinda overwrites the value from the top BB and the phi-source from the top BB must be ignored, in fact it must be removed. However, it is not the case and this extra phi-source creates different kinds of problems. Among other things, it hinders further simplifications. For example, the following code: extern int array[2]; static inline int stupid_select(int idx) { if (idx) idx = 0; return array[idx]; } int select(void) { int d = stupid_select(-1); return d; } should boil down to a simple dereference of the array with an index of zero, like: select: load.32 %r8 <- 0[array] ret.32 %r8 but currently gives: select: phisrc.32 %phi3(idx) <- $0xffffffff phisrc.32 %phi4(idx) <- $0 phi.32 %r12(idx) <- %phi3(idx), %phi4(idx) sext.64 %r5 <- (32) %r12(idx) mul.64 %r6 <- %r5, $4 add.64 %r7 <- %r6, array load.32 %r8 <- 0[%r7] ret.32 %r8 This patch takes care of the problem by: * when merging 2 BBs, check when reaching a phi-source in the bottom BB * if one is found, look after sibling phi-sources * remove such sibling if belonging to the top BB. With this change, the code above gives: select: phisrc.32 %phi4(idx) <- $0 phi.32 %r12(idx) <- %phi4(idx) sext.64 %r5 <- (32) %r12(idx) mul.64 %r6 <- %r5, $4 add.64 %r7 <- %r6, array load.32 %r8 <- 0[%r7] ret.32 %r8 which can the be simplified into the expected result. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-11-15cfg: add testcase for phi-adjusting during BB mergeLuc Van Oostenryck1-0/+24
When merging BBs, phi-sources from the bottom BB should 'overwrite' the ones from the top BB which should be ignored. Add a testcase from the incoming fix. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-11-15testcase: avoid UNDEFLuc Van Oostenryck1-2/+3
Reduced testcases (with creduce, of course) often needlessly have undefined variables. Since these are untouched by the simplification code and should not be present in source code, they should be avoided in optimization testcases. So, defines 'x' to some value other than 0. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-11-09Merge branch 'optim-cmp' into nextLuc Van Oostenryck16-111/+293
* simplify & canonicalize compares
2020-11-08select: simplify select(x, x, 0) --> xLuc Van Oostenryck2-9/+3
The dual simplification select(x, 0, x) --> 0 was already done but this one was forgotten, so add it now. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-11-08select: simplify handling of select(x, 0, x) --> 0Luc Van Oostenryck1-0/+9
This simplification is already handled but explicitly kills it's 2 operands while this is done automatically when killing the instruction. Also, it uses replace_with_value(0) which needs to recreate the pseudo for 0 while it's already available via its operands. So, changes to use replace_with_pseudo() and without the unneeded kills. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-11-08cmp: simplify compares and sign/zero extendLuc Van Oostenryck2-2/+0
Compare instructions with both operands sign or zero-extended from the same original size are equivalent to a compare of the original values. If the values were zero-extended, a signed compare becomes an unsigned one. Simplify away the sign/zero-extensions. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-11-08cmp: simplify zext(x) cmpu CLuc Van Oostenryck1-1/+0
An unsigned compare of a zero-extended value against a constant outside of the original range is statically known. Simplify to the corresponding 0/1. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-11-08cmp: simplify zext(x) cmps CLuc Van Oostenryck1-1/+0
A signed compare of a zero-extended value against a constant outside of the original range is statically known. Simplify to the corresponding 0/1. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-11-08cmp: canonicalize sext(x) cmpu C (with C >= SMAX)Luc Van Oostenryck1-1/+0
A unsigned compare of a sign-extended value against a value bigger than the original SMAX is equivalent to a signed compare against 0. Canonicalize to the signed compare against 0. Note: ultimately both forms are just a test of the sign bit. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-11-08cmp: simplify sext(x) cmps {SMAX,SMIN}Luc Van Oostenryck1-1/+0
A signed compare of a sign-extended value against a constant outside of the original range is statically known. Simplify to the corresponding 0/1. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-11-08cmp: simplify zext(x) cmp C --> x cmp CLuc Van Oostenryck3-3/+0
When doing a compare of a zero-extended value against a constant, this extension can be dropped and the comparison done on the original type if the constant is within the original range and signed compares become the corresponding unsigned one. Simplify away these sign-extensions. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-11-08cmp: simplify sext(x) cmp C --> x cmp CLuc Van Oostenryck1-1/+0
When doing a compare of a sign-extended value against a constant the, sign-extension can be dropped and the comparison done on the original type if the constant is within the original range. Simplify away these sign-extensions. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-11-08cmp: canonicalize unsigned (x {<=,>} SMAX)Luc Van Oostenryck1-1/+0
Unsigned <= or > against SMAX are equivalent to testing if the value is positive or not (when interpreted as a signed number). Canonicalize to this positive/negative test since it only needs the constant 0 which make it easier to handle at later steps. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-11-08cmp: canonicalize unsigned compare with UMAX or UMAX-1Luc Van Oostenryck1-1/+0
Unsigned compares with UMAX (or UMAX-1) are equivalent to equality tests. These are preferable since it's easier to reason about them in other simplifications. So canonicalize these compares to equality tests. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-11-08cmp: simplify unsigned (x {<=,>} UMAX) into {1,0}Luc Van Oostenryck1-1/+0
These compares are always true or false, so simplify them. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-11-08cmp: canonicalize unsigned (x {<,>=} C) --> (x {<=,>} C-1)Luc Van Oostenryck1-1/+0
An unsigned comparison like (x < 3) is equivalent to (x <= 2). Canonicalize '<' & '>=' to '<=' & '>', such that the smallest constant is used. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-11-07simplify SEL(x == y, x, y) and friendsLuc Van Oostenryck1-0/+12
If the condition of a select instruction is a equality test of the select's operands, then the result of the select is always the same as its second operand. Same for the first operand with an inequality test. Simplify away these selects. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-11-07select: simplify SEL(SEL(x, C1, C2), y, z) --> y (with C1, C2 != 0)Luc Van Oostenryck1-1/+0
If the condition of a select is also a select, with constant but non-zero operands, then the result of this inner select is always true and the outer select can be replaced by its second operand. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-11-07select: simplify SEL(SEL(x, C, 0), y, z) --> SEL(x, y, z) and its dualLuc Van Oostenryck2-2/+0
If the condition of a select is also a select but with constant operands, some simplification can be done: * if the second operand is 0, the original condition can be used, * idem if the first operand is 0s but the operand must be swapped. Originally-by: Linus Torvalds <torvalds@linux-foundation.org> Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-11-07select: add some testcases for select simplificationLuc Van Oostenryck5-0/+54
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-11-05cmp: add testcases for the simplification of comparesLuc Van Oostenryck15-0/+293
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-11-02cmp: adapt testcase for compares' canonicalizationLuc Van Oostenryck1-111/+14
The current testcase, because it's just checking test-linearize's output as-is, is very sensitive to small simplification changes. Fix this by changing the tests into equivalent tests and then just checking that these tests return '1'. This allows to test only what really matters for canonicalization and make these tests very robust. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
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>