Age | Commit message (Collapse) | Author | Files | Lines |
|
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
With the configured theme, 'classic', the table of contents
didn't show up in the sidebar.
It seems it was because 'html_sidebars' was partially set in
conf.py, overhidding the theme defaults.
Fix this by removing 'html_sidebars' from the config.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Currently, the release notes are kept on the wiki which
contains nothing else but a small intro.
The docs are certainly as good as this wiki to keep these
release notes. So, let try this for now.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
The generated doc is hosted on readthedocs.io since a little
while but:
* it wasn't much publicised
* it's now also live on sparse.docs.kernel.org
So, add a link to this doc on the manpage.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
The documentation about the documentation is in the middle of the
documentation about sparse itself.
Move it to its own section.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Sparse's type system, or more exactly the way types are encoded
in Sparse's data structures, is not hard but is also not exactly
immediate to grok.
Here is a modest attempt to document this.
The corresponding generated documentation can be find at:
https://sparse.docs/kernel.org
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
In struct ctype, 'modifiers' & 'base_type' are, by far,
the 2 most frequently used members.
However, `base_type`, the most used, is defined as the last one.
Change this by moving `base_type` as the first one.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
* add support for arch-specific builtins
|
|
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 real goal here is in fact to move the alpha-specfic
builtins out of the main builtins table.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
The real goal here is in fact to move the bfin-specfic
builtins out of the main builtins table.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
The real goal here is, in fact, to move the nios2-specfic
builtins out of the main builtins table.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Now that a table is used for the declaration of builtin functions
it's easy to support arch-specific builtins.
The main objective is to not 'pollute' the main table with
arch-specfic entries for uncommon architectures.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Till now, 2 tables are used to initialize builtin functions:
* an older, small one, without type information, used to set
a symbol_op to evaluate and/or expand the ones that have
some associated behaviour.
* a newer and bigger one which only contains what is effectively
the prototype for these builtins in order to avoid warnings
about undeclared functions.
It's kinda annoying to have 2 tables for this, even more so
because most entries in the first table also need to be in the
second one (for arguments type and number checking).
Fix this by:
* adding a field in the second table for the symbol_op
* merging or moving the entries in the first table into
the second one.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
The curent way to declare the builtins is not by using a table
but via a (variadic) function call, one for each builtin.
A table is preferable but a complication for doing this
is that some elements are not constant. For example, 'size_t_ctype'
is dynamically set in the early steps of the type initialization.
Doing a series of function calls allowed to circumvent this.
Fix this by:
* Using a constant temporary alias for non-constant entries. It's the
value of these alias that will be used when registering the builtins.
* using a table to declare the builtin functions.
Note: the motivation for doing this is to be able to add sub-tables
for the arch-specific builtins (and use the same mechanism
as for the main table).
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
The initialization of the buitins can be done later, after
the types have been initialized.
So move the call to init_builtins() to just before declare_builtins().
This will allow some other small improvements.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
These 2 are used for the kernel and the lack of a
declaration is causing problems.
So add the declarations for these 2 builtins.
At the same time also add one for '__builtin_custom_ini()'
since this one may also be used in the kernel.
Note: a better fix should be to move this to target-nios2.c
Link: https://lore.kernel.org/lkml/20200609151329.GU23011@xsang-OptiPlex-9020/
Reported-by: kbuild test robot <lkp@intel.com>
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>
|
|
Remove this declaration which follows the definition.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
On cygwin, the <ctype.h> header is written in such a way as to cause
a gcc compiler warning if a plain 'char' is passed to the character
classification macros (in this case isdigit). The result is defined
only if the parameter is representable as an unsigned char, or if it
is EOF.
When passing a 'char' type argument to isdigit(), the compiler warns
like so:
CC pre-process.o
In file included from pre-process.c:33:
pre-process.c: In function ‘predefine’:
pre-process.c:1429:18: warning: array subscript has type ‘char’ [-Wchar-subscripts]
1429 | if (isdigit(buf[0])) {
| ~~~^~~
In order to suppress the warning, cast the argument of isdigit() to
an 'unsigned char' type.
Signed-off-by: Ramsay Jones <ramsay@ramsayjones.plus.com>
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
'{ 0 }' is the standard idiom for the universal zero initializer '{ }'.
But if the '0' is taken literally, warnings can be issued, for exemple
for 'using 0 as NULL pointer' or for 'using a positional initializer'
when the attribute 'designated_init' is used.
These warnings were not intended to be issued for this initializer
and are confusing and annoying when people have to use or want to
use standard code or ignore that '{ }' is fine to use with GCC,
clang or Sparse.
So, set sparse default to -Wno-universal-initializer, suppressing
any warnings caused by using '{ 0 }' instead of '{ }'.
Reference: https://lore.kernel.org/git/e6796c60-a870-e761-3b07-b680f934c537@ramsayjones.plus.com/
Reference: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95379
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>
|
|
Commit c100a7ab (add support for _Generic, 2020-05-28) added the
function evaluate_generic_selection() as an external symbol, without
providing an external declaration in a header file. This causes
sparse to issue a warning as part of the 'selfcheck' target.
Since this function does not (currently) need to be an external symbol,
mark it as static.
Signed-off-by: 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>
|
|
Some platforms have some of their system header files missing the
ending newline. Sparse will then warn about it, again and again,
and more important warnings can easily be lost in the noise.
So, add an option flag '-W[no-]newline-eof' to conditionalize
this warning.
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>
|
|
* improve handling of function attributes
* separate modifiers into type/declaration
* add support for attributes 'unused' & 'gnu_inline'
* simplify parsing of inline/__tls/__visible
|
|
* doc: do not use obsolete sphinx's AutodocReporter
|
|
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>
|
|
In most cases symbols are automatically marked as being used via
a successfull call to lookup_symbols(), the idea being that the
symbol will be created at its declaration and then any (successfull)
lookup will correspond to an use.
For labels, things are slightly different because labels are
created on-demand via label_symbol() and their use can precede their
'declaration'. And of, course, label_symbol() has no ways to know
if it is used for a definition or an use.
So, fix this by adding an argument to label_symbol(), explictly
telling if the call correspond to an use or not.
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>
|
|
Extract this helper from evaluate_goto_statement().
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
More exactly, what is undefined is to jump inside the statement
expression with a computed goto.
Of course, once the address of such a label is taken, it's generaly
impossible to track if it will be used or not to jump inside the
statement expression.
So, for now, handle taking the address of such a label from outside
the statement expression, exactly as if a computed goto is effectively
done from there and so issue an error message and also mark the function
as useless for linearization.
Note: this is only partially correct since:
1) the address could be taken from outside the statement
and never used for a computed goto.
2) the address could be taken from outside the statement
but the corresponding computed goto only done from
inside, which is perfectly fine.
3) the address could be taken from inside but a computed
goto done from outside.
Note: the real problem, like for the regular goto, is that the
statement expression can be eliminated before linearization,
the correspondng gotos corresponding then to branches to
unexistent BBs.
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>
|
|
One way of detecting gotos inside an statement expression
is to use a new kind of scope for the gotos & labels.
Since gotos don't need to have their label predeclared,
nothing can be checked at parsing time but later it can
be checked that a goto doesn't jump inside one of the
label scope created by statement expressions.
So, add additional scope information to gotos and labels
to allow such check to be done.
Note: the label's symbols are still created in the function
scope since they belong to a single namespace.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Add an helper to check if a scope is included into another one.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
It's invalid to jump inside a statement expression.
So, concerning labels & gotos, a statement expression is
like a kind of scope.
So, in preparation for the detection of such jumps, create
these new scopes and open/close them when entering/leaving
statement expressions.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
The functions {start,end}_symbol_scope() haven't been renamed
when separated scope have been introduced for functions & blocks.
But these functions only start & end a block scope.
So, rename them to their more direct name: {start,end}_block_scope().
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Labels declared wth __label__ are special because they must follow
the block scope normally used for variables instad of using the
scope used for labels.
So, use bind_symbol_with_scope() instead of first using bind_symbol()
and then changing the namespace.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
__func__ needs to be in the namepsace for symbols: NS_SYMBOL
but doesn't follow the usual scope rules of them: it always
needs to be declared in the function scope.
So, use bind_symbol_with_scope() instead of first using bind_symbol()
and then changing the namespace.
Also change the comment to better express that it's the scope
that is the unusual thing.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
In most cases, the scope that must be used for a symbol is
given by its namespace.
However, in some situations a different scope must be used.
This is then set, for example by doing the lookup with
the wrong namespace (but corresponding to the desired scope)
and changing it just after to its correct value.
To avoid these contortions, extract from bind_symbol() a version
where the scope can be explicitly given: bind_symbol_with_scope().
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
A compound statement starts and ends a block scope, so
it's better to start & end this scope inside the function
parsing the statement: compound_statement.
The only exception is for the body of a function where
the scope also enclose the parameter declaration but that
is fine since the function is special anyway.
Move the calls to start & close the block scope inside
compound_statement() and directly call statement_list()
for the function body.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
When starting some scopes, the newly allocated struct is
memset'ed with zero but this is unneeded since the allocator
always returns zeroed memory.
Remove the unneeded call to memset().
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>
|
|
It's not possible to produce a valid & correct IR if
the function contains a goto to an undeclared label.
So, try to catch these situations and mark the function
as such, the linearization will then simply ignore it.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
There is no need to do a lookup: checking if the label's
symbol is in the NS_LABEL namespace and is lacking an
associated statement is enough and much simpler.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
No functional changes here, only changing the code structure
to prepare more incoming changes.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
In some error cases, it's not possible to produce a valid &
correct IR for the concerned function. For exemple, if the
AST contains invalid gotos, the CFG will either be invalid
or won't correspond to the erroneous source code.
So, refuse to linearize such functions.
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>
|
|
At evaluation time and at expansion time, current_fn is set
to the function's base type (SYM_FN) but at parse time it's
set to its parent type (SYM_NODE).
Since current_fn is used to access the corresponding ident,
it should be set to the node type, not the base.
So, always set current_fn to the node type.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
In evaluate_return_expression(), it's checked if the type of
the return statement match the function return type.
But, the variable used to hold this type is named 'fntype'
which is slightly confusing.
So, rename the variable holding the return type to 'rettype'
and only use 'fntype' for the one holding the full function type.
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>
|
|
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.
So, use the the generic code for 'declaration modifiers'
to parse this attribute.
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.
So, use the the generic code for 'declaration modifiers'
to parse this attribute.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
But for the moment do nothing special with it.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
When parsing a declaration, type specifiers, qualifiers and other
modifiers are handled by declaration_specifiers(). Some of these
are part of the type being declared but some others only concern
the object in itself. For example, the storage specifiers pertains
to the objects being declared but not their type. Because of this
the storage specifiers need to be processed separately in order to
be correctly applied to the object node. This is done via the helper:
storage_modifier().
However, some attributes are exactly in the same situation (an
obvious example is something like the section attribute).
These attributes should also be moved to the declaration and it's
only because they are currently ignored/without effect that they're
not causing problem in the type.
So generalize storage_modifiers() into decl_modifiers() to extract
all modifiers not pertaining to the type of the declared object.
The modifiers currently concerned are the attributes:
- unused
- pure
- noreturn
- externally_visible
Note: currently this change shouldn't have any effects other
than not showing anymore the "[unused]" when displaying
the type differences in diagnostics.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Add support for the attribute 'unused' (and its double underscore
variant. There is no semantic attached to it but it's now at least
parsed and added to the modifiers.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
A warning is issued when a qualifier or another modifier
is present more than once in a declaration.
This is fine but in the kernel some attributes, for example
'unused' & 'gnu_inline', are sometimes present multiple times
in the same declaration (mainly they are added in the define
used for 'inline'). This then creates a lot of useless noise.
So, use a (now empty) white list to not warn when these attributes
are present multiple times in the same declaration.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
to avoid duplicated code checking for ... duplicated modifiers!
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>
|
|
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
It seems that Markdown is now parsed slightly differently and
now generate some warnings.
So tweak the .md files to shut up the warnings.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
sphinx.ext.autodoc.AutodocReporter is obsolete since Sphinx 1.7
and removed in some later versions.
So, replace it by the code suggested in the release notes when
it was obsoleted.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
In do_show_type() the first if statement allows passing null
pointers, which can cause a null pointer dereference in some
cases, which I believe is not the desired behavior.
Fix this by changing the first if statement comparison.
Signed-off-by: Davidson Francis <davidsondfgl@gmail.com>
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
The regex match used for detecting the LLVM version works for versions
with a single-digit major number. Now that LLVM v10 is out, detection
can fail, resulting in sparse-llvm not being built.
Fix detection by extracting the major version number to compare with the
minimum supported.
Signed-off-by: Quentin Monnet <quentin@isovalent.com>
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
* fix type compatibility of _Atomic types
|
|
expr->left & expr->conditional are unioned but 'left'
should only be used for binary operators.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
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>
|
|
* generate OP_UNREACH from __builtin_unreachable()
* add OP_UNREACH after calls to __noreturn functions
|
|
__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>
|
|
Sparse ignores most builtins. A few of them are directly
interpreted at parsing time (types_compatible_p, offsetof).
Some others are expanded if their argument(s) are constant
but that's all.
However, some of the builtins are significant at the IR
level and shouldn't thus be ignored.
This patch add the support needed for the linearization of
these builtins.
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>
|
|
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
To create plugin for text editor, it may be useful to be able to search
by position in a file.
$ sindex search -l include/uapi/linux/msdos_fs.h:91:8
(---) fs/fat/dir.c 759 1 fat_ioctl_filldir FAT_IOCTL_FILLDIR_FUNC(fat_ioctl_filldir, __fat_dirent)
(r--) fs/fat/dir.c 759 1 fat_ioctl_filldir FAT_IOCTL_FILLDIR_FUNC(fat_ioctl_filldir, __fat_dirent)
(m--) fs/fat/dir.c 759 1 fat_ioctl_filldir FAT_IOCTL_FILLDIR_FUNC(fat_ioctl_filldir, __fat_dirent)
(def) include/uapi/linux/msdos_fs.h 91 8 long d_ino;
$ sindex search -l -m w include/uapi/linux/msdos_fs.h:91:8
(m--) fs/fat/dir.c 759 1 fat_ioctl_filldir FAT_IOCTL_FILLDIR_FUNC(fat_ioctl_filldir, __fat_dirent)
Another use is to get the full name of symbol in case of a high level
of nesting:
$ sindex search -e fs/dcache.c:567
(--r) fs/dcache.c 567 9 __dentry_kill dentry->d_op->d_prune(dentry);
(--r) fs/dcache.c 567 15 __dentry_kill dentry->d_op->d_prune(dentry);
$ sindex search -e --format='%n' fs/dcache.c:567
dentry.d_op
dentry_operations.d_prune
$ sindex search -e --format='%n' fs/dcache.c:567:9
dentry.d_op
Signed-off-by: Alexey Gladkov <gladkov.alexey@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>
|
|
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
sindex is the simple to use cscope-like tool based on sparse/dissect.
Unlike cscope it runs after pre-processor and thus it can't index the
code filtered out by ifdef's, but otoh it understands how the symbol
is used and it can track the usage of struct members.
To create an index for your linux kernel configuration:
$ make C=2 CHECK="sindex add --"
Now, to find where a definition of the pid field from the task_struct
structure:
$ sindex search -m def task_struct.pid
(def) include/linux/sched.h 793 11 pid_t pid;
default output format:
SOURCE-FILE \t LINE-NUMBER \t COLUMN \t IN FUNCTION NAME \t CODE LINE
To find where this field changes:
$ sindex search -m w task_struct.pid
(-w-) fs/exec.c 1154 6 de_thread tsk->pid = leader->pid;
(-w-) kernel/fork.c 2155 3 copy_process p->pid = pid_nr(pid);
To get only filenames and line number you can change output format:
$ sindex search -f '%f:%l' -m w task_struct.pid
fs/exec.c:1154
kernel/fork.c:2155
Current limitations:
* inline functions are ignored;
* enums are ignored;
* unknown #include leads to a fatal error.
Suggested-by: Oleg Nesterov <oleg@redhat.com>
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Signed-off-by: Alexey Gladkov <gladkov.alexey@gmail.com>
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
A separate change for documentation purposes.
Test-case:
void func(void)
{
struct UNDEFINED x;
x.member = 0;
}
output:
1:6 def f func void ( ... )
3:26 func def . v x struct UNDEFINED
4:9 func -w- . v x struct UNDEFINED
4:10 func -w- . m UNDEFINED.member bad type
but in this case is_sym_local(UNDEFINED) = F makes more sense, most
probably this struct was defined somewhere else but __sparse() didn't
see its definition.
Change lookup_member() to set type->scope = file_scope if !symbol_list.
This is not 100% correct, but struct_union_enum_specifier() does the
same check with the following comment:
// The following test is actually wrong for empty
// structs, but (1) they are not C99, (2) gcc does
// the same thing, and (3) it's easier.
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Now that struct_union_enum_specifier() always sets sym->scope we can
simplify sym_is_local(sym) and rely on toplevel() even if sym is type.
Test-case:
// copied from linux kernel
# define __force __attribute__((force))
#define WRITE_ONCE(x, val) \
({ \
union { typeof(x) __val; char __c[1]; } __u = \
{ .__val = (__force typeof(x)) (val) }; \
__write_once_size(&(x), __u.__c, sizeof(x)); \
__u.__val; \
})
void func(int *p)
{
WRITE_ONCE(*p, 0);
}
before this patch the widely used WRITE_ONCE() generates a lot of spam which
can't be filtered out using sym_is_local(),
11:6 def f func void ( ... )
11:11 func def . v p int *
13:9 def s :__u
13:9 --- . v p int *
13:9 def m :__u.__val int
13:9 def m :__u.__c char [1]
13:9 func def . v __u union :__u
13:9 func -w- . v __u union :__u
13:9 func -w- m :__u.__val int
13:9 func --- . v p int *
13:9 func --r f __write_once_size bad type
13:9 func -r- . v p int *
13:9 func -r- . v __u union :__u
13:9 func m-- m :__u.__c char [1]
13:9 func --- . v p int *
13:9 func --- . v __u union :__u
13:9 func --- m :__u.__val int
plus it triggers warning("no context") in test-dissect.c. With this patch
the only "nonlocal" report is __write_once_size() call.
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Currently it is not possible to figure out the scope of the private
struct/union/enum type, its ->scope is NULL because bind_symbol() is
not called.
Change struct_union_enum_specifier() to set sym->scope = block_scope
in this case, this is what bind_symbol() does when type has a name.
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
It is trivial and has a single caller, lookup_member().
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
no_member() sets ->ident = built_in_ident("?") for the case when dissect()
can't figure out the name of initialized member. For example:
struct EMPTY {} var = { 10 };
the output:
1:25 var -w- m EMPTY.? bad type
This is useful, but dissect should not dictate the policy. Let r_member()
decide how this case should be reported.
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
I didn't know show_ident() uses 4 buffers for the string it returns and
thus it is safe to call it twice in a row.
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
This is more flexible. For example, we can change dissect() to inspect
file_scope->symbols too without changing its callers.
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Can be used to filter out the usage of local variables.
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
A separate change for documentation purposes.
dissect() tries to work even if the parsed code is buggy or incomplete,
thus it makes sense to change expr_symbol() to set kind = 'f' when it
likely looks like a function name.
We can safely abuse EXPR_SYMBOL->op to pass the hint to expr_symbol(),
it must be 0.
Test-case:
void call(void)
{
func();
}
before this patch
1:14 def f call void ( ... )
3:17 call --r v func bad type
after:
1:14 def f call void ( ... )
3:17 call --r f func bad type
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Change dissect to report ctags-like kind passed in sym->kind.
Currently only v,f,s and m kinds are possible.
SYM_UNION doesn't differ from SYM_STRUCT and has ->kind = 's'.
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>
|
|
Now that we have dissect_ctx do_statement(STMT_RETURN) can use
base_type(dissect_ctx->ctype.base_type) instead.
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
examine_fn_arguments() silently degenerates function arguments into
pointers but dissect doesn't do evaluate_symbol_list(), that is why
do_sym_list(type->arguments) can report the bogus definitions.
Test case:
void extf(int MUST_NOT_BE_REPORTED);
typedef void (fptr_t)(int MUST_NOT_BE_REPORTED);
void func1(fptr_t fptr) {}
void func2(typeof(extf) fptr) {}
void func3(void) { typeof(extf) fptr; };
void func4(void (fptr)(int MUST_NOT_BE_REPORTED)) {}
without this patch:
4:6 def func1 void ( ... )
4:12 func1 def fptr void ( ... )
2:23 fptr def MUST_NOT_BE_REPORTED int
5:6 def func2 void ( ... )
5:19 func2 --- extf void ( ... )
5:12 func2 def fptr void ( ... )
1:11 fptr def MUST_NOT_BE_REPORTED int
6:6 def func3 void ( ... )
6:27 func3 --- extf void ( ... )
6:33 func3 def fptr void ( ... )
1:11 fptr def MUST_NOT_BE_REPORTED int
7:6 def func4 void ( ... )
7:12 func4 def fptr void ( ... )
7:24 fptr def MUST_NOT_BE_REPORTED int
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Points to the current function or to the global variable in case of
compound initializer.
Kill the ugly test-dissect.c:storage() and change print_usage() to
report dissect_ctx->ident instead.
Signed-off-by: Oleg Nesterov <oleg@redhat.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>
|
|
To report where is the member of struct/union defined.
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
This makes dissect.c a bit more readable.
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Change deanon() to always initialize base->ident when parent != NULL
but still return false to avoid the pointless ->r_symdef().
Test-case:
struct {
union {
int x;
};
} var = {
{ .x = 0 },
};
before this patch:
1:8 s def :var
5:3 g def var struct :var
5:3 g -w- var struct :var
6:12 s -w- ?.x int
after:
1:8 s def :var
5:3 g def var struct :var
5:3 g -w- var struct :var
6:12 s -w- :var.x int
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Preparation. Change mk_name() to initialize base->ident itself, simplify it,
and rename to deanon().
Also change examine_sym_node() to accept "struct symbol *parent" rather than
"struct ident *root". Currently it is only used as ->ident holder, but this
will be changed.
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Change report_member() to not call ->r_member(mem) if !mem->ident.
This can only happen in initializer, the output gives no useful info
but looks like a bug. Test-case:
struct {
union {
int x;
};
} var = {
{}
};
before this patch:
1:8 s def :var
5:3 g def var struct :var
5:3 g -w- var struct :var
6:9 s -w- :var.? union <noident>
after:
1:8 s def :var
5:3 g def var struct :var
5:3 g -w- var struct :var
We also need to change no_member() to ensure we still report the bad
initializers, this will be cleanuped later.
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Each time domtree_build gets called, extraneous/duplicated child nodes
get left in the bb->doms ptrlist. This is because the existing children
are not cleared from bb->doms before rebuilding it.
In addition to consuming memory, the extraneous child nodes result
in a malformed dominance tree.
The following 3 line patch fixes this problem by freeing the dominator
tree before rebuilding it.
Signed-off-by: Xan Phung <xan.phung@gmail.com>
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Signed-off-by: John Levon <john.levon@joyent.com>
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
The SPARCV9 compile check needs to look for __sparcv9 on some systems,
and should also define "sparc".
Signed-off-by: Toomas Soome <tsoome@me.com>
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
GCC defines these, so should we.
Signed-off-by: John Levon <john.levon@joyent.com>
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Signed-off-by: John Levon <john.levon@joyent.com>
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
As per:
https://gcc.gnu.org/onlinedocs/gcc-4.6.3/gcc/Symbol_002dRenaming-Pragmas.html
we should set this define.
Signed-off-by: John Levon <john.levon@joyent.com>
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Only on UNIX-like OSes are __unix__ & __unix predefined, so it's needed
to easily test if the OS is UNIX-like or not.
Let's do this cheaply by moving all the define of UNIX-like OSes
after the define for 'generic UNIX': OS_UNIX.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
If nothing more specific matches but __unix__ or __unix is defined,
use OS_UNIX as the native OS.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Sparse knew about OpenBSD & NetBSD but didn't detected them.
Until now, that's it.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
The detection of the native OS was done in a strange order.
Now, do this alphabetically.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
When detecting SunOS, '&&' was used instead of '||'.
Fix that.
Fixes: 6bca188679d235ddbad2e97aa3e4186a4730686e
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
GCC adds predefines for some symbols lying in the user's namespace,
like "linux" or "sparc", but only if the selected dialect is not one
of the standard ones.
Add an helper, predefine_nostd(), for these.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
* move arch specificities in their own files
* better support of arch specificities
|
|
do_show_type() checks sym->type inside the "if (!sym || ...)" block.
While at it, remove the trailing whitespaces.
Fixes: 0fe7ebb9 ("show-parse: do not display base type's redundant specifiers")
Reported-by: Alexey Gladkov <gladkov.alexey@gmail.com>
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Fix some embarrassing typos.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
* improve diagnostic message about wrong redeclaration
|
|
* tidy-up of typeof expansion
|
|
* 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>
|
|
arch_target now points to a structure holding all the
arch-specificities. So, arch_mach is not needed anymore.
Remove arch_mach.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
The predefine for INT128 is still done with the generic
predefines but are arch-specific.
So, set a new flag for each arch supporting int128
and use this to determine if the predefine must be
issued or not.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Now that each supported arch has its own target file,
move the predefines for cmodel, which are arch-specific,
to the target files.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Now that each supported arch has its own target file,
move the arch-specific predefines to these files too.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
This is for completeness and only useful for S390 which is not
exactly the most common arch. But since it's now easy to do
this kind of thing ...
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Before initaializing the builtin types some 'finalizations' are
needed. target_ini() already does most of this.
So, move the arch-specific content of handle_arch_finalize()
into the corresponding target files and the generic part to
target_init().
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
So, the 2 tables indexed by arch are next to each other,
both in target.c, making easier to add a new arch.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
lib.c and even more so, target.c, become cluttered by the
arch specific type initialization.
It would be better to move this to arch-specific files,
move the generics target related helpers to target.c
and have sparse_initialize() to just call these helpers.
For doing this:
* introduce a struct to hold the configurations for each arch,
* move the arch-specific type initialization to separate files,
* make target.c generic.
Also change the default types to LP64.
Note: this is the first step to better handle other arch
specificities like the predefines or the handling
of some options.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
The spec names 'ppc64+{be,le}' had the '+' to force them
to be internal names but are also useful as external names
(it helps to make systematic testing of the arch-specific code).
So rename them to 'ppc64{be,le}'.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
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>
|
|
is_bitfield_type() is one of the few type-testing helper
based on get_sym_type(). But get_sym_type() test for SYM_NODE
and SYM_ENUM, which is not needed here.
So, simply test for SYM_BITFIELD.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
No functional changes here, just moving the code for the
conversion of SYM_TYPEOFs in its own function, in preparation
for some further changes.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
SYM_TYPEOFs are expanded at examination time.
However, classify_type() does its own expansion of SYM_TYPEOFs.
Worse, it does this differently (address space & noderef are
not removed)..
So, to enforce the same expansion, also use examine_symbol_type()
to do the expansion in classify_type().
Note: it's not sure that it's currently possible to have
SYM_TYPEOFs to expand in classify_type().
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>
|
|
evaluate_string() leaves the strings it creates as unexamined
& unevaluated. More exactly, they are examined and evaluated
(they have correct size & type) but not marked as such.
This doesn't seem to really matter but shows up when auditing
if classify_type() is always used on examined symbols.
So, mark the strings as examined and evaluated since their
size & type are known.
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>
|
|
This is just moving the 3 lines of code to mark a symbol
as addressable in a speparate function.
This is a preparatory step for one of the next patches.
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
|
|
* testsuite: avoid standard includes in the tests
|
|
* remove redundant to degenerate()
|
|
* add support for '-std=c17/c18'
This is mainly an excuse for cleaning the associated
code and to easily test 'strict' vs. 'gnu'.
|
|
'__CYGWIN32__' is wrongly defined on 64-bit Cygwin.
Fix this by only defining it when $m32 is set and set $m32
when i386 is selected.
Signed-off-by: Ramsay Jones <ramsay@ramsayjones.plus.com>
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
No real support is done here (or is needed) but the __STDC_VERSION__
will return the correct value.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
The definition of __STDC_NO_ATOMICS__ and friends will also
be needed for C17.
Move these definitions outside of the switch statement.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Currently, the definition of __STRICT_ANSI__ is done in the same
switch statement used for __STDC_VERSION__. However, this lead to
some repetions that can be avoided if moved outside of the switch.
Move the definition of __STRICT_ANSI__ out of the switch statement
and guard it by testing the absence of STANDARD_GNU.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Move some of the cases so that each STANDARD_GNU* is just
under the its corresponding STANDARD_C*.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
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>
|
|
While issuing a diagnostic related to a bitfield, it's useful
to display the bitfield's name. Unfortunately, this name is not
stored in the symbol and thus is only available during parsing.
Fix this by adding the ident to the symbol initialization.
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>
|
|
At parsing time, bitfields with invalid width have their size
set to -1 but at examination time this size is interpreted as
an unsigned value, causing a second warning.
Fix this by avoiding to cast the size to an unsigned variable.
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>
|
|
In compatible_assignment_types(), the source expression is
first degenerated before calling check_assignment_types().
But this is not needed since check_assignment_types() must
anyway do the call to degenerate().
So, remove the redundant call to degenerate().
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>
|
|
During a call to add_specs('linux'), cgcc adds several macro definitions
to the sparse command line. In particular, it provides the incorrect
definition: '-Dlinux=linux'.
This bug was introduced in commit 807f74466b (<no title>, 2004-08-13), while
moving some calls to add_pre_buffer() around in lib.c. This was then moved
out of sparse, into cgcc, by commit cf2bde63a6 (<no title>, 2004-10-05),
where the definition was copied verbatum.
Fix this macro definition to read '-Dlinux=1' instead.
Signed-off-by: Ramsay Jones <ramsay@ramsayjones.plus.com>
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
It may be useful to known the base standard and if we're using
the gnu extensions but as these are defined it can only be done
on a case-by-case basis.
Change these defines so that:
* the GNU extensions is the least significant bit
* the versions can be easily compared with <, >, <= and >=
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Since semantics and supported features can differ between
standard version we may need the supported version.
Allow this by moving the variable 'standard' and the corresponding
enum definition to lib.h
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
In preparation for supporting C17 flags, remove unneeded
STANDARD_... cases and remove the impossible default assert(0).
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Sparse itself already add support for it, so add
support for it in the wrapper too.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
These are only for native build and I don't know
if anyone is using sparse on openbsd, but for completeness
and ease of testing let's get them right for sparse too.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
The macros __PPC, _ARCH_PPC & _ARCH_PPC64 are predefined by
GCC for powperpc (well, it seems __PPC isn't anymore but
it was, at least on my old toolchain for ppc32).
So, do the same here too.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
These seem to be defined whenever the __x86_64 and
__x86_64__ macros are defined.
So, do the same here too.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
These options are sparse-specific and shouldn't be passed to GCC.
Reported-by: Ramsay Jones <ramsay@ramsayjones.plus.com>
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Sparse knows about __int128_t, __uint128_t & __int128.
However, internally, these types are treated as a kind of 128-bit
'long long long' type. It's mainly a question of variable naming,
but these types are also displayed by show_typename() as
'long long long' which can't be parsed back, neither by GCC,
nor even by sparse itself.
So, rename the variables to use 'int128' and let show_typename()
display these types as '[signed|unsigned] __int128'.
Reported-by: Ramsay Jones <ramsay@ramsayjones.plus.com>
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
|
|
On mips64, the 'new' ABIS have 128-bit long doubles while
the 'old' and the embedded ABIs use 64-bit.
Add a note for this, since currently the -mabi flag is not handled.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
On 32-bit sparc running SunOS or Solaris, long doubles
are 128-bit, not 64-bit.
Add a special case to handle this.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
On 32-bit sparc running SunOS or Solaris, wchar_t and wint_t
are long, not uint or int.
Add a special case to handle this.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
There are a few OS-specific settings and handling them
with #ifdef is 1) ugly, 2) can only work with when specifically
built for this OS (either a native or cross-build).
So, use a variable to hold the OS and initialize it to the one
used to compile sparse. This avoid the ugly #ifdef and allow
simpler transition if if the future sparse would take the OS
in parameter (maybe as triple).
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>
|
|
The known execptions are:
* ARM with the bare-metal eabi
* MIPS64 with the n32 ABI
But these two are not really supported yet.
So, for now, int32 & uint32 can siply be set to int & uint.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
When the predefine for char32_t was added, it was made to
correspond 'unsigned int' with the commit message saying
some archs use 'unsigned long'. In fact, it appears that
char32_t is always uint32_t (on the archs & OSes I'm using
to look at this).
So, simply predefine __CHAR32_TYPE__ like uint32_t is.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
|