Running a project through Clang's scan-build produces countless
warnings like
build/test/mocks/mock_handleTroubleEvents.c:321:5: warning: Value stored to 'call_instance' is never read
call_instance = CMOCK_GUTS_NONE;
^ ~~~~~~~~~~~~~~~
scan-build correctly determines that in the following snippet
UNITY_CLR_DETAILS();
if (Mock.checkForActiveTroubleAfterDebounce_CallbackFunctionPointer != NULL)
call_instance = CMOCK_GUTS_NONE;
call_instance = Mock.startStopTimer_CallInstance;
as generated by Ceedling / CMock, the first assignment to
call_instance is completely unused.
The sheer amount of warnings makes it very hard to impossible to
spot real problems in one's code, and creates huge code analysis
reports that just distract from actual problems in one's code.
Without being too invasive, we can instruct scan-build to ignore
this dead store using
https://clang-analyzer.llvm.org/faq.html#dead_store
Signed-off-by: André Draszik <git@andred.net>
callback has a later priority than expect, so setting call_instance
to CMOCK_GUTS_NONE at this point has no effect. This mock_verify()
has probably been obsolete for a long time.
If we have a 'empty' macro, f.e.:
\#if <something>
\#define MY_LIBRARY_INLINE
\#endif
and using the user pattern 'MY_LIBRARY_INLINE', we would get the
following effect:
match = 'MY_LIBRARY_INLINE\n' <--- NOTE THAT THE NEWLINE IS PART OF THE MATCH
post-match = '#endif\n' <--- NO BEGINNING NEWLINE SINCE IT IS PART OF
THE MATCH ABOVE
And lead to the new header:
\#if <something>
Which gives a compilation error since the preprocessor-if is not
terminated properly.
The root cause is that we add a any-whitespace-character regex to the
user regex.
This any-whitespace-character regex was added only to cleanup the
whitespaces after a user regex.
So the next line will be deleted if we check for any whitespace
character (THIS INCLUDES A NEWLINE!) after the user regex.
But this had the side effect that when matching a user regex, the newline was
also seen as part of the match. Which in the case of an empty macro
would mean that in the cleanup of the post-match, we would delete the
line immediately after the empty macro (\#endif in the example above).
So instead of matching with every whitespace character (which includes
newlines!), we explicitly only check for whitespaces.
Taking the example above, this has the desired effect:
match = 'MY_LIBRARY_INLINE' <--- NOTE THAT THE NEWLINE IS NO LONGER PART OF THE MATCH
post-match = '\n#endif\n' <--- BEGINNING NEWLINE NOW
Now the cleanup after a define will see the beginning newline in the
post-match and only remove that newline and now the preprocessor-if is
terminated properly
First squash all multiline macro's, it makes parsing easier. Otherwise
the regex to remove the macro would become more comples if we have to
deal with newlines etc.
When we have a match, we check if the last line in the pre_match is
the beginning of a macro declaration.
If it is, we remove the beginning of this macro
declaration (#define<space>) and remove the body of the macro from the
post_match, which is basically everything until the next newline.
There is a possible edge case (pretty unlikely but still):
if there is no newline in the post_match, meaning it is a macro at the
end of the line, we should delete it as well, hence the '[\n]?' in the
post match regex.
When a inline function was declared in a file, we would find the
declaration and remove the function body. However, since it is a
declaration, there is NO function body, so we were deleting a random
piece of code that was between square brackets in the file.
To properly handle this, we have to detect if we are dealing with a
function declaration or a function definition.
If we are dealing with a function declaration, a semicolon
will come BEFORE the first square bracket.
If we are dealing with a function definition, a square bracket will
come BEFORE the first semicolon (the first semicolon will be in the
inline function body, so between the square brackets).
So we determine the location of the first semicolon and the first
square bracket after the function name and apply the logic described
above to handle function declarations.
If we are dealing with a function declaration, we don't do anything,
we just move to the next match.
This will result in redeclarations of the inline function, but this is
allowed in C and I'd rather not touch the file anymore than necessary.
It didn't add direct comparisons only for pointer arguments, but
also other types of arguments like structs, which can't be compared
with '==' and cause a compiler error instead.
To reproduce, just enable the :array plugin in
system/test_interactions/expect_and_return_custom_types.yml:
In function ‘foo’:
error: invalid operands to binary != (have ‘EXAMPLE_STRUCT_T’ {aka
‘struct _EXAMPLE_STRUCT_T’} and ‘EXAMPLE_STRUCT_T’ {aka ‘struct
_EXAMPLE_STRUCT_T’})
59 | if (cmock_call_instance->Expected_a != a) {
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ^~
This reverts commit 4df532afcc.
- If inlines are included, we don't do anything since they are
disguised already as normal functions
- If inlines are NOT included, we remove anything that has inline in
it
- We set the defaults but the user is free to add his own.
This will overwrite our defaults but they will be added to the
documentation as reference for the user