| Age | Commit message (Collapse) | Author | Files | Lines |
|
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>
|
|
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>
|
|
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>
|
|
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
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>
|
|
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>
|
|
* teach sparse about union casts
|
|
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>
|
|
A cast to union type is a GCC extension similar to a compound
literal just for union, using the syntax of a cast.
However, sparse doesn't know about them and treats them like
other casts to non-scalars.
So, teach sparse about them, convert them to the corresponding
compound literal and add a warning flag to enable/disable the
associated warning: -W[no-]union-cast.
Note: a difference between union casts and compound literals
is that the union casts yield rvalues while compound
literals are lvalues but this distinction is not yet done
in this series.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Casts to union type are a GCC extension and are similar to
compound literals.
However, sparse doesn't know about them and treats them like
other casts to non-scalars.
Add some testcases for this and its upcoming warning flag.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
* fouled types are scalars too (fix is_{scalar,integral}_type()
|
|
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>
|
|
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>
|
|
* delay 'empty character constant' warning to phase 5
|
|
* teach sparse about wide string initializers
|
|
* fix evaluation of __sync_{bool,val}_compare_and_swap()
|
|
* fix type evaluation of shifts-assigns
* don't warn for UB shifts in dead code
|
|
* fix diagnostic source path from command line
* fix diagnostic source path for invalid streams
|
|
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>
|
|
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>
|
|
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>
|
|
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
* warn on empty assignments & initializations
|
|
|
|
|
|
Currently sparse accepts an empty initialization like:
int a = ;
Make this an error.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Currently sparse accepts an empty assignment like:
a = ;
Make this an error.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
This is a fix for a problem reported today to the mailing list.
In check_assignment_types(), the first 'level' is checked by the
function itself but the next level is checked by the type_difference().
This later function take as arguments, beside the types to be
checked, the modifiers that can be assumed for each of the types
(this works as a kind of reverse mask).
But these modifiers are taken from target_qualifiers() which,
purposely ignore the modifiers for arrays introduced in commit
984b7b66457c ("[PATCH] deal correctly with qualifiers on arrays")
with the comment:
"Pointers to any array are considered as pointers to unqualified
type as far as implicit conversions are concerned"
But by dropping these modifiers, type_difference() reports
incorrect results for pointers to qualified arrays.
So, do not use target_qualifiers() but take the modifiers directly
from the ctypes. Admittingly, I'm far from sure that this is the
right fix but it solve several wrong cases.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
The problem is seems to be related with evaluate_dereference()
where all mods are dropped when the type is a node.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Those are cases that sparse should warn about but doesn't.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
You can assign a '<type>[]' to a 'const <type> *'. Likewise,
you can assign a '<type>[][N]' to a 'const <type> (*)[N]' but
sparse doesn't like this.
Analyzed-by: Ard Biesheuvel <ardb@kernel.org>
Reported-by: Herbert Xu <herbert@gondor.apana.org.au>
Link: https://lore.kernel.org/linux-crypto/20200709120937.GA13332@gondor.apana.org.au/
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
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>
|
|
* predefine: fix multi-token predefine
* predefine: add helper predefine_{strong,weak}()
* predefine: avoid add_pre_buffer() for targets
* predefine: simplify add_pre_buffer()
|
|
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>
|
|
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>
|
|
This flag facilitates the creation of testcases for preprocessing.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
When inlining multiple times a function which contains an undeclared
function call, multiple error messages are issued. More annoyingly,
only the first one is meaningful, the other ones doesn't even show
the incriminated identifier:
error: undefined identifier '...'
error: not a function <noident>
Part of the problem is that the first message is displayed with
expression_error() which also sets the expression to &bad_ctype.
This change the way how the expression is handled when re-evaluated.
Fix this by avoiding the evaluation of function calls that already
evaluate to bad_ctype: it's known that an error message have already
been issued for them and that nothing good can done with them.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
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>
|
|
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>
|
|
|
|
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>
|
|
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>
|
|
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>
|
|
* support for builtin macros with arguments
* support for __has_feature() & __has_extension()
|
|
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>
|
|
The support for these builtin macros is incoming.
So, add some testcases for them.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
* conditionally accept { 0 } without warnings
|
|
* 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.
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
* fix type compatibility of _Atomic types
|
|
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>
|
|
__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>
|
|
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>
|
|
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
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>
|
|
* improve diagnostic message about wrong redeclaration
|
|
* improve expansion of constant symbols
|
|
* fix testcase with non-constant initializer
|
|
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>
|
|
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>
|
|
Two testcases had their command wrongly terminated by ';'.
Fix this by removing this ';'.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
Symbols which have their address taken (with the 'addressof'
operator: &) are marked as such (with the modifier MOD_ADDRESSABLE).
But degenerated arrays and functions have their address implicitly
taken.
MOD_ADDRESSABLE is used to prevent to replace a symbol dereference
nto the value used to initialize to it. For example, in code like:
static int foo(void)
{
int x[2] = { 1, 2 };
return x[1];
}
the return expression can be replaced by 2. This is not the case
case if the array is first passed in a function call, like here:
extern void def(void *, unsigned int);
static int bar(void)
{
int x[2] = { 1, 2 };
def(x, sizeof(x));
return x[1];
}
Fix this by marking degenerated arrays (and functions) as also
being addressable.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
mark_addressable() is used to track if a symbol has its
address taken but does not take in account the fact that
a symbol can be accessed via one of its subfields.
A failure occurs in case like:
struct { int a; } s = { 3 };
...
def(&s.a);
return s.a;
where 's' is not marked as being addressable and so the
the initializer will be expanded and the return expression
will always be replaced by 3, while def() can redefine it.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
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>
|
|
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>
|
|
Sparse can't do this yet.
So, add a testcase for it.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Once a symbol has its address taken, a lot of simplifications
must be avoided because the symbol can now be modified via
a pointer.
This is currently done but the symbol addressability
does not take in account the fact that a symbol can be
accessed via one of its subfields.
Add a testcase to illustrate this.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
An array or a function that degenerates into a pointer
has its address implicitly taken since the result is
equivalent to '&array[0]' or '&fun'.
So, the corresponding symbol needs to be marked as
addressable, like when its address is explicitly taken.
Add a testcase to illustrate this.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
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>
|
|
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>
|
|
* fix premature examination of dereferenced object
|
|
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>
|
|
* improve diagnostic messages concerning bitfields
|
|
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>
|
|
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>
|
|
Add some testcases before making related changes.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
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>
|
|
|
|
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>
|
|
|
|
Teach Sparse about these options.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
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>
|
|
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
|
|
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
* clarify lazy evaluation & conversion of SYM_TYPEOF
|
|
Unless an explicit call to examine_pointer_target() or
get_base_type() is made, the base type of pointers are
*not* examined via the usual recursive examine_symbol_type().
That means that it is possible to call show_typename()
on a non-fully examined type which is wrong (for example,
because SYM_TYPEOFs may not be converted).
So, call examine_pointer_target() on pointers when trying
to display them.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
The base type of pointers are not examined when the pointer is.
It needs to be done later when looked at.
This may be a problem when show_typename() is used on a pointer
which has not yet been 'deep-examined' and, for example, has a
SYM_TYPEOF as its base type.
Add a test case showing the problem.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
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>
|
|
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>
|
|
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>
|
|
Currently, ASM operands aren't expanded or even evaluated.
This causes Sparse to emit warnings about 'unknown expression'
during the linearization of these operands if they contains,
for example, calls to __builtin_compatible_types_p().
Note: the correct handling of ASM operands needs to make
the distinction between 'memory' operands and 'normal'
operands. For this, it is needed to look at the constraints
and these are architecture specific. The patches in this
series only consider the constraints m, v, o & Q as
being for memory operands and, happily, these seems
to cover most usage for the most common architectures.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
|
|
Expressions without a valid type should never be linearized
since they have no (valid) type and haven't been expanded.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
The function cast_value() needs the exact type of the old expression
but when called via cast_enum_list() this type is incorrect because:
- the same struct is used for the new and the old expression
- the type of the new expression is adjusted before cast_value()
is called.
Fix this by adjusting the type of the new expression only after
cast_value() has been called.
Fixes: 604a148a73af ("enum: fix cast_enum_list()")
Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
In a declaration like:
enum {
a = 0x80000000,
b = -1,
}
the underlying type should be long and b's value should be
0xffffffffffffffff (on a 64-bit machine) but is 0xffffffff.
Reported-by: Dan Carpenter <dan.carpenter@oracle.com>
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Code like:
int *r;
r = ({ __builtin_types_compatible_p(long, long); });
triggers the following diagnostics:
warning: incorrect type in assignment (different base types)
expected int *r
got long
warning: unknown expression (4 0)
warning: unknown expression (4 0)
The first warning is expected but the other two are bogus.
The origin of the problem could be considered as being how
type incompabilities are handled in assignment:
If an incompatibility is found by compatible_assignment_types()
- a warning is issued (not an error),
- the source expression is casted to the destination type,
- the returned value indicates a problem was detected.
In the other uses of this function the returned value is simply
ignored and normal processing continue. This seems logical since
only a warning is issued and so (thanks to the cast) the
resulting expression is at least type-coherent.
However, in evaluate_assignment() the returned value is not
ignored and the calling function directly returns. This leaves
the resulting expression without a valid type, as if an error
occured, unable to be correctly processed further.
However, the real problem is that an expression without a valid
type should never be linearized.
So, in linearize_expression(), refuse to linearize an expression
without a valid type.
Note: if one is interested in doing a maximum of processing,
including expansion and linearization, check_assignment_types()
should be modified to distinguish between recoverable and
non-recoverable type error (those for which the forced
cast make sense and those for which it doesn't) and
compatible_assignment_types() modified accordingly (maybe
issuing a warning in the first case and an error otherwise).
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Non-memory asm operands are very much like function's arguments.
As such, any array (or function designator) used as an asm operand
need to degenerate into the corresponding pointer.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
The operands of extended ASM need to be expanded, exactly
like any other expression. For example, without this expansion
expressions with __builtin_compatible_types_p() can't be
linearized and will issue a 'warning unknown expression".
So, add the missing expansion of ASM operands.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
ASM memory operands are considered by GCC as some kind of implicit
reference. Their linearization should thus not create any storage
statement: the storage is done by the ASM code itself.
Adjust the linearization of such operands accordingly.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
The operands of extended ASM need to have their type evaluated,
exactly like any other expression.
So, add the missing evaluation of ASM operands.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
The syntax of extended ASM statements requires that the
bodies & constraints are given via a literal string.
However, at parsing time more general expressions are accepted
and it's checked only at evaluation time if these are effectively
string literals. This has at least two drawbacks:
*) evaluate_asm_statement() is slightly more complicated than
needed, mixing these checks with the real evaluation code
*) in case of error, the diagnostic is issued later than
other syntaxic warnings.
Fix this by checking at parse-time that ASM bodies & constraints
are string literals and not some arbitrary expressions.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
ASM statements are quite complex.
Add some tests to catch some potential errors.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
The error handling during the parsing of _Static_assert()'s
message string is relatively complex.
Simplify this by using the new helper string_expression().
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Compound literals, like all other expressions, need to be be
expanded before linearization, but this is currently not done.
As consequence, some builtins are unexpectedly still present,
same for EXPR_TYPEs, ... with error messages like:
warning: unknown expression
at linearization.
Fix this by adding the missing expansion of compound literals.
Note: as explained in the code itself, it's not totally clear
how compound literals can be identified after evaluation.
The code here consider all anonymous symbols with an
initializer as being a compound literal.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Compound literals are currently not expanded.
Add a test for this.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
The diagnostic message is a bit long with the non-really-informative
part 'incorrect type' first and the explanation later in parentheses.
Change this by using a shorter message "non-scalar type in ...".
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Some error messages are displayed with auxillary information
about the concerned type(s).
However, this type information is displayed in various way:
just the type, "[left/right] side has type ...", "got ...", ...
Make these more consistent and simpler by just displaying
types when the error message is unambigous about the fact
that the problem is a type problem (and/or make the message
unambiguous when possible).
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Currently, sparse emits a warning when a conditional expression with a
constant condition is used where an "Integer Constant Expression" is
expected and only the false-side operand (which is not evaluated) is
not constant. The standard are especially unclear about this situation.
However, GCC silently accept those as ICEs when they evaluate to a compile-time
known value (in other words, when the conditional and the corresponding
true/false sub-expression are themselves constant). The standard are
especially unclear about the situation when the unevaluated side is non-constant.
So, relax sparse to match GCC's behaviour.
Reported-by: Oliver Hartkopp <socketcan@hartkopp.net>
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
The patch b3daa62b5 ("also accept casts of AS pointers to uintptr_t")
is bogus and allows uintptr_t as the *source type* instead of the
*target type*. This was helped by a previous bug, in patch
d96da358c ("stricter warning for explicit cast to ulong"), where
a test for Wcast_from_as was wrongly added for the source type.
Fix this by:
* adding the test for uintptr_t to the target type;
* removing the test for Wcast_from_as from the source type,
replacing it by a test of Wcast_to_as;
* clarify and extend the tge testcases.
So, now, casts from uintptr_t to AS pointers are also allowed.
Fixes: b3daa62b53109dba78c7937b3a6a0cd7d67865d5
Fixes: d96da358cfa0432f067a4e66940765883b80ee62
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Sparse will warn on casts removing the address space of a pointer
if the destination type is not unsigned long. But the type
'uintptr_t' should be more suited for this.
So, also accept casts of address-space qualified pointers to uintptr_t.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Due to the way compatible_assignment_types()'s handle type
incompatibilities and how expression with an invalid type
are nevertheless processed by linearize_expression(), some
invalid assignments retunr unwanted error messages (and
working around them can create some others).
Here are 2 relatively simple tests triggering the situation.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
During the expansion of shifts, the variable 'conservative' is used
to inhibit any possible diagnostics (for example, because the needed
information is if the expression is a constant or not).
However, this must not inhibit the simplification of valid shift
expressions. Unfortunately, by moving the validation inside
check_shift_count(), this what was done by commit
0b73dee01 ("big-shift: move the check into check_shift_count()").
Found through a false positive VLA detected in the Linux kernel.
The array size was computed through min() on a shifted constant value
and sparse complained about it.
Fix this by changing the logic of check_shift_count():
1) moving the test of 'conservative' inside check_shift_count()
and only issuing warnings if set.
2) moving the warning part in a separate function: warn_shift_count()
3) let check_shift_count() return if the shift count is valid
so that the simplication can be eluded if not.
Fixes: 0b73dee0171a15800d0a4ae6225b602bf8961599
Signed-off-by: Thomas Weißschuh <thomas@t-8ch.de>
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
For "incompatible types in comparison expression" errors, only the
kind of type difference is displayed. Displaying the types would
make easier to find the cause of the problem. The same is true
for ternary conditionals.
So, also display the left & right types.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Fix escaping of square brackets in some test patterns.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
* explain cause of 'incorrect type in conditional'
* manpage: fix doc of '-Wcast-from-as'
|
|
Add a new test file which demonstrates some problems which can be
seen on the git codebase. gcc does not complain about this file:
$ gcc -Wall -c validation/function-redecl2.c
$
... but sparse does:
$ sparse validation/function-redecl2.c
validation/function-redecl2.c:6:5: error: symbol 'func0' redeclared with different type (originally declared at validation/function-redecl2.c:3) - different modifiers
validation/function-redecl2.c:13:6: error: symbol 'func1' redeclared with different type (originally declared at validation/function-redecl2.c:11) - different modifiers
validation/function-redecl2.c:21:6: error: symbol 'func2' redeclared with different type (originally declared at validation/function-redecl2.c:18) - different modifiers
$
Note that func0 and func2 are essentially the same example, apart from
the attribute used, to demonstrate that the issue isn't caused by the
'pure' attribute. Also, examples like func1 have occurred several times
in git and, although they can be worked around (eg. See [1]), it would
be preferable if this were not necessary.
[1] (git) commit 3d7dd2d3b6 ("usage: add NORETURN to BUG() function
definitions", 2017-05-21).
Signed-off-by: Ramsay Jones <ramsay@ramsayjones.plus.com>
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
This simplifies finding the offending test when the build ended with
KO: out of 584 tests, 527 passed, 57 failed
56 of them are known to fail
Signed-off-by: Uwe Kleine-König <uwe@kleine-koenig.org>
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
If the flag '-m64' is used on a 32-bit architecture/machine having
int32_t set to 'long', then these int32_t are forced to 64-bit ...
So, ignore the effect of -m64 on these archs and ignore
'64-bit only' tests on them.
Reported-by: Uwe Kleine-König <uwe@kleine-koenig.org>
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
Tested-by: Uwe Kleine-König <uwe@kleine-koenig.org>
|
|
The test was called with the flag '-m64' but doesn't need it.
So, remove it.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
Tested-by: Uwe Kleine-König <uwe@kleine-koenig.org>
|
|
A conditional only make sense on a scalar type. If not, an
error is issued but the message doesn't explain the cause.
Fix this by adding the cause to the error message.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
* small improvemnets to show_typename()'s outout:
* strip trailing space
* don't display '<noident>'
* do not display base type's redundant specifiers
* do not let display string_ctype lika a base type 'string'
|
|
* warn on casts to/from bitwise pointers
|
|
In do_show_type(), builtin_typename() is used to display builtin
(base) types and modifier_string() is used to display modifiers.
However, most base types contains some intrinsic modifiers, the
type specifiers. So, a type like 'unsigned long' is displayed as
'unsigned long [unsigned] [long]'.
Fix this redundancy by not displaying the specifiers when displaying
a base_type (or an enum).
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Often show_typename() is used to display a type and the associated
identifier is irrelevant but is displayed nevertheless.
However, when the identifier is itself not present, it is still
displayed as '<noident>', which is just noise and can be confusing.
Fix this by displaying nothing for null identifiers in show_typename().
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Support for 'bitwise' integers is one of the main sparse's extension.
However, casts to or from pointers to bitwise types can be done
without incurring any sort of warnings although such casts can
be as wrong as direct casts to or from bitwise integers themselves.
Add the corresponding warnings and control them by a new flag
-Wbitwise-pointer (defaulting to off as it creates tens of
thousands warnings in the kernel).
CC: Thiebaud Weksteen <tweek@google.com>
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
since it seems that the strict type checking is not done
on pointers to restricted types.
Signed-off-by: Thiebaud Weksteen <tweek@google.com>
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
* add predefined macros for __INTMAX_TYPE__, __INT_MAX__, ...
|
|
These are a pain. All LP64 archs use [u]int. Good.
But some LP32 archs use [u]int and some others use [u]long.
Some even use [u]int for some ABI and [u]long for some others
(bare metal).
This really need to be target-specific to be correct.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
All LP32 archs use [u]llong and all LP64 use [u]long for these
but Darwin which seems to always use [u]llong.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
All LP64 & LP32 use [u]char and [u]short for these ones.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Seems to use [u]long for all LP64 archs and [u]llong
and all LP32 ones (but OpenBSD but it seems to not defines
the corresponding macros).
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Luckily, it seems all archs use for them the same types as
size_t & ssize_t.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
This allows to have a single function to output the
size, the type, the maximal value, ...
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
It's possible that the result of do_show_type() ends with a space.
Strip this unneeded space.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
GCC's trunk now allows to specifiy 'inline' with asm statements.
This feature has been asked by kernel devs and will most probably
by used for the kernel.
So, teach sparse about this syntax too.
Note: for sparse, there is no semantic associated to this inline
because sparse doesn't make any size-based inlining decisions.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
size_t_ctype is set to uint, ulong or ullong, depending on
the architecture (ullong is only used for LLP64).
However, when emitting '__SIZE_TYPE__', it's only compared to ulong
or uint.
Fix this by using an small helper directly using the right
struct symbol * and using builtin_typename() to output the
right type. This way we're guaranteed that '__SIZE_TYPE__'
is kept coherent with the internal type: size_t_ctype.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Now these tests should succeed and be meaningful on
all archs.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
* prepare to identify & display the address spaces by name
|
|
Currently, address space 1 is displayed as '<asn:1>' and so on.
Now that address spaces can be displayed by name, the address space
number should just be an implementation detail and it would make
more sense the be able to 'declare' these address space directly
by name, like:
#define __user attribute((noderef, address_space(__user)))
Since directly using the name instead of an number creates some
problems internally, allow this syntax but for the moment keep
the address space number and use a table to lookup the number
from the name.
References: https://marc.info/?l=linux-sparse&m=153627490128505
Idea-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
* fix linearization of non-constant switch-cases
|
|
Use a function to display the address spaces.
This will allow to display a real name instead of '<asn:1>'.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
* fixes for -dD
* add support for -dM
Luc Van Oostenryck (2):
dump-macro: break the loop at TOKEN_UNTAINT
dump-macro: simplify processing of whitespace
Ramsay Jones (5):
pre-process: suppress trailing space when dumping macros
pre-process: print macros containing # and ## correctly
pre-process: don't put spaces in macro parameter list
pre-process: print variable argument macros correctly
pre-process: add the -dM option to dump macro definitions
|
|
Sparse allows (but warns about) a bare newline (not preceded by
a backslash) inside a string. Since this is invalid C, it's
probable that a terminating '"' is missing just before the newline.
In this case, allowing the newline implies accepting the following
characters until the next '"' is found, which is most case creates
a lot of irrelevant warnings.
Change this by disallowing newlines inside strings, exactly like
already done for character constants.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Add a testcase for "Newline in string or character constant" vs.
"missing delimitator" upcoming change.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Sparse unconditionally issues warnings about non-ANSI function
declarations & definitions.
However, some environments have large amounts of legacy headers
that are pre-ANSI, and can't easily be changed. These generate
a lot of useless warnings.
Fix this by using the options flags -Wstrict-prototypes &
-Wold-style-definition to conditionalize these warnings.
Signed-off-by: John Levon <levon@movementarian.org>
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
In legacy environment, a lot of warnings can be issued about
arguments without an explicit type.
Fix this by contitionalizing such warnings with the flag
-Wimplicit-int, reducing the level of noise in such environment.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
In an old-style function definition, if not explicitly specified,
the type of an argument defaults to 'int'.
Sparse issues an error for such arguments and leaves the type
as 'incomplete'. This can then create a cascade of other warnings.
Fix this by effectively giving the type 'int' to such arguments.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Legacy code can be littered with the non-standard "#ident" directive;
ignore it.
Signed-off-by: John Levon <levon@movementarian.org>
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|