Variables declared in the if condition (or in C++17 init-statement) are
visible not only in the if body but also in the else body. But logic in
Tokenizer::setVarIdPass1() handled such variables as if they were
declared in the if body.
As the result they were removed from variablesMap by the time the else
block was parsed and their uses in the else block were either given an
incorrect varId from variables in some outer scope or not given a varId
at all.
This then resulted in false positive unreadVariable errors for variables
declared in the if condition (or init-statement) and used only in the
else block.
Simplification from "else if ..." to "else { if ... }" was moved before
setVarId() to simplify detection for ends of blocks in if-else chains.
Fix faulty removal of parenthesis when "]" is followed by parenthesis
with a number inside, for example when calling a function pointer in
an array or (perhaps more common) in c++, calling operator ( on an
element in an array.
Fixes#8875 where such wrong simplification lead to a FP with too many
bits shifted due to "<<" was interpreted like a shift operator rather
than a stream output.
* fix some hangs in daca from uninstantiated template classes derived from itself
* remove assertions
* fix another simplifyUsing hang
Co-authored-by: Robert Reif <reif@FX6840>
* clang_tidy.cmake: added clang-tidy-11 to list of executables to look for
* .clang-tidy: disabled warnings we are (currently) not interested in
* fixed clang-tidy warnings
The template simplifier works well enough now so cleanupAfterSimplify is
no longer necessary. In fact cleanupAfterSimplify was introducing a bug
which improperly simplified C++ style casts.
Bugs should be exposed and fixed properly rather than just hiding them.
Co-authored-by: Robert Reif <reif@FX6840>
* Tokenize: Set varId for variables in enum
Set varIds in enum values. It was previously disabled in 5119ae84b8
to avoid issues with enums named the same as global variables. Take care
to only set varids to variables used to set the value of an enumerator,
not the enumerator itself. This is somewhat complicated by the fact that
at the time this happens, astOperand1(), astOperand2(), astParent() etc
are not set. The current implementation is not perfect, for example in
the code below, y will not have a varid set, but x and z will. This is
deemed sufficient for now.
int x, y, z;
enum E { a = f(x, y, z); };
* Fix#9647: Value of enums with variables as init values
C++ allows enum values to be set using constexprs, which cppcheck did
not handle before. To solve this, add a new pass to valueflow to update
enum values after global consts have been processed. In order to do so,
I moved all settings of enum values to valueflow. After setting the enum
values, we need another call to valueFlowNumber() to actually set users
of the enums.
There is still room for improvements, since each pass of
valueFlowGlobalConstVar() and valueFlowEnumValue() only sets variables
that are possible to set directly, and not if setting the value of a
variable allows us to set the value of another. For example
constexpr int a = 5;
constexpr int b = a + 5;
enum E { X = a };
constexpr E e = X;
Here both b and e will not have their values set, even though cppcheck
should be possible to figure out their values. That's for another PR
though.
This was tested by running test-my-pr.py with 500 packages. The only
difference was one error message in fairy-stockfish_11.1, where cppcheck
now printed the correct size of an array instead of 2147483648 which I
assume is some kind of default value. In that package, using a constexpr
when setting enum values is common, but as mentioned, there was no
change in the number of warnings.
The template parameter is confusing simplifyUsing: it does not compute
properly the scope, and we end up replace "type" in "to_string" with
"void", then later "void" is removed and we have an internal error.
* Add rudimentary support for [[maybe_unused]]
* Add more test cases. use the symboldatabase rather than reparsing. Fix travis error.
* test review actions
* change var to usage._var
* cppcheck.cpp: Check for JSON error when parsing addon .json files
This fixes that errors in JSON files given via `--addon=*.json` are
silently ignored and maybe only a part of the JSON file is used.
Now the error message which picojson can return is checked and a
corresponding error message is returned again by getAddonInfo().
* naming.json: Fix missing comma
* CLI: Fix naming violations detected by addon naming.py via naming.json
* Addon naming: Add argument for validating names of constants
* LIB: Rename functions/variables so they are valid, loosen naming rules
* GUI: Fix naming violations
* fix syntax error for conversion operator for type with global namespace
* fix syntax error when taking address of operator function
* fix syntax error for using ::operator "" _a;
* fix syntax error for template<> void operator "" _h<'a', 'b', 'c'>() {}
* fix syntax error for operator in parentheses
There are probably a lot more valid code patterns that generates syntax
errors so I added "operator" to the error message to make it easier to
find them.
* Set correct type and size of string and char literals
Use that string and char literal tokens store the prefix. This makes
it possible to distinghuish between different type of string literals
(i.e., utf8 encoded strings, utf16, wide strings, etc) which have
different type.
When the tokens holding the string and character values have the correct
type, it is possible to improve Token::getStrSize() to give the correct
result for all string types. Previously, it would return the number of
characters in the string, i.e., it would give the wrong size unless
the type of the string was char*.
Since strings now can have different size (in number of bytes) and
length (in number of elements), add a new helper function that returns
the number of characters. Checkers have been updated to use the correct
functions.
Having the size makes it possible to find more problems with prefixed
strings, and to reduce false positives, for example in the buffer
overflow checker.
Also, improve the stringLiteralWrite error message to also print the
prefix of the string (if there is one).
* Add comment and update string length
Keeping the prefix in the token allows cppcheck to print the correct
string and char literals in debug and error messages.
To achieve this, move some of the helper functions from token.cpp to
utils.h so that checks that look at string and char literals can reuse
them. This is a large part of this commit.
Note that the only user visible change is that when string and char
literals are printed in error messages, the prefix is now included.
For example:
int f() {
return test.substr( 0 , 4 ) == U"Hello" ? 0 : 1 ;
};
now prints U"Hello" instead of "Hello" in the error message.
`__typeof__` is just an alternative keyword for `typeof`, see
https://gcc.gnu.org/onlinedocs/gcc/Typeof.html
Since `typeof` is handled in several checkers it makes sense to define
`__typeof__` as `typeof`.
Tokenizer::simplifyTypedef(): Use `typeof` instead of `__typeof__` to
be consistent with the rest of the code.
* Better handle const/noexcept methods/conversion operator
const or noexcept in a method / (conversion) operator definition were
badly parsed, ending in a bad ast.
This patch tries to make it better, at least making the ast less bad,
so as to avoid errors in later checks.
* Fix parsing of some operator
It is still very broken, but at least, it does not fail.
Here is the previous error:
```
TestSimplifyTypedef::simplifyTypedef129
terminate called after throwing an instance of 'InternalError'
Program received signal SIGABRT, Aborted.
__GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:51
51 ../sysdeps/unix/sysv/linux/raise.c: No such file or directory.
(gdb) bt
#0 __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:51
#1 0x00007ffff612a801 in __GI_abort () at abort.c:79
#2 0x00007ffff6b1d957 in ?? () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#3 0x00007ffff6b23ab6 in ?? () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#4 0x00007ffff6b23af1 in std::terminate() () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#5 0x00007ffff6b23d24 in __cxa_throw () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#6 0x0000555556366bf8 in Tokenizer::cppcheckError (this=0x7fffffffc2d0, tok=0x607000006760) at ../lib/tokenize.cpp:8721
#7 0x000055555636a4bb in Tokenizer::validate (this=0x7fffffffc2d0) at ../lib/tokenize.cpp:9154
#8 0x000055555633e3aa in Tokenizer::simplifyTokenList1 (this=0x7fffffffc2d0, FileName=0x603000002d50 "test.cpp") at ../lib/tokenize.cpp:4477
#9 0x00005555563223ca in Tokenizer::simplifyTokens1 (this=0x7fffffffc2d0, configuration="") at ../lib/tokenize.cpp:2286
#10 0x00005555563235c8 in Tokenizer::tokenize (this=0x7fffffffc2d0, code=..., FileName=0x555556fda9a0 "test.cpp", configuration="") at ../lib/tokenize.cpp:2345
#11 0x00005555569410ea in TestSimplifyTypedef::tok[abi:cxx11](char const*, bool, cppcheck::Platform::PlatformType, bool) (this=0x555557728580 <(anonymous namespace)::instance_TestSimplifyTypedef>,
code=0x7fffffffcb70 "class c {\n typedef char foo[4];\n foo _a;\n constexpr operator foo &() const noexcept { return _a; }\n};", simplify=false, type=cppcheck::Platform::Native, debugwarnings=true) at ../test/testsimplifytypedef.cpp:192
#12 0x000055555697239e in TestSimplifyTypedef::simplifyTypedef129 (this=0x555557728580 <(anonymous namespace)::instance_TestSimplifyTypedef>) at ../test/testsimplifytypedef.cpp:2599
#13 0x000055555694092c in TestSimplifyTypedef::run (this=0x555557728580 <(anonymous namespace)::instance_TestSimplifyTypedef>) at ../test/testsimplifytypedef.cpp:167
#14 0x00005555569cab84 in TestFixture::run (this=0x555557728580 <(anonymous namespace)::instance_TestSimplifyTypedef>, str="simplifyTypedef129") at ../test/testsuite.cpp:306
#15 0x00005555569cb445 in TestFixture::runTests (args=...) at ../test/testsuite.cpp:329
#16 0x000055555687bdfb in main (argc=2, argv=0x7fffffffd988) at ../test/testrunner.cpp:44
```
* Replace some ASSERT_EQUALS with TODO_ASSERT_EQUALS when the actual result is still wrong
* Remove invalid code from simplifyTypedef129
* Properly skip parentheses
Previously, cppcheck discarded the `extern "C"` specifier. This patch modifies cppcheck to parse each as a Scope in the symbol database, then uses that scope to avoid false positives when making recommendations about changing a function argument to be a reference (since variable references is a C++ feature, unavailable in C, and thus unavailable in `extern "C"`).
I fixed the AST enough to pass testrunner but I don't believe it is
correct.
This code:
void Foo4(int&&b);
has this AST:
( 'void'
|-Foo4
`-&& 'bool'
|-int
`-b 'signed int'
but I don't believe && should have `bool`.
* use range loops
* removed redundant string initializations
* use nullptr
* use proper boolean false
* removed unnecessary continue from end of loop
* removed unnecessary c_str() usage
* use emplace_back()
* removed redundant void arguments