Hi @nlohmann and other mainteners,
First of all, I must say that I love your work on this librairy.
It feels really easy to use, and to read code using this library ! 鉂わ笍
I have created this issue to talk about the warnings that cppcheck found on this project.
I'm currently experimenting with both this library and cppcheck on some little side projects. And doing so, I've ended up with cppcheck warnings me about some elements inside the json library.
So the purpose of this issue is to talk about the warnings from cppcheck, to address them when they are relevant, so that other people which are going to have both this library and cppcheck] in their project, as little as warnings as possible.
Here is the list of the warnings I've got for now:
(1)[include\nlohmann\json.hpp:5076]: (style) Variable 'm_value.object->emplace' is reassigned a value before the old one has been used.
(2)[include\nlohmann\detail\conversions\to_chars.hpp:585]: (style) The expression 'kAlpha >= -60' is always true.
(3)[include\nlohmann\detail\conversions\to_chars.hpp:586]: (style) The expression 'kGamma <= -32' is always true.
(4)[include\nlohmann\detail\output\serializer.hpp:726]: (style) The expression 'thousands_sep != '\0'' is always false because 'thousands_sep' and ''\0'' represent the same value.
(5)[include\nlohmann\detail\output\serializer.hpp:736]: (style) The expression 'decimal_point != '\0'' is always false because 'decimal_point' and ''\0'' represent the same value.
(6)[include\nlohmann\detail\input\binary_reader.hpp:650]: (style) Unsigned expression 'mant' can't be negative so it is unnecessary to test it.
(7)[include\nlohmann\json.hpp:837]: (style) Local variable object shadows outer function
(8)[include\nlohmann\detail\input\input_adapters.hpp:339]: (style) Class 'input_adapter' has a constructor with 1 argument that is not explicit.
(9)[include\nlohmann\detail\input\input_adapters.hpp:342]: (style) Class 'input_adapter' has a constructor with 1 argument that is not explicit.
(10)[include\nlohmann\detail\input\input_adapters.hpp:346]: (style) Class 'input_adapter' has a constructor with 1 argument that is not explicit.
(11)[include\nlohmann\detail\input\input_adapters.hpp:349]: (style) Class 'input_adapter' has a constructor with 1 argument that is not explicit.
(12)[include\nlohmann\detail\input\input_adapters.hpp:352]: (style) Class 'input_adapter' has a constructor with 1 argument that is not explicit.
(13)[include\nlohmann\detail\input\input_adapters.hpp:355]: (style) Class 'input_adapter' has a constructor with 1 argument that is not explicit.
(14)[include\nlohmann\detail\input\input_adapters.hpp:377]: (style) Class 'input_adapter' has a constructor with 1 argument that is not explicit.
(15)[include\nlohmann\detail\input\input_adapters.hpp:421]: (style) Class 'input_adapter' has a constructor with 1 argument that is not explicit.
(16)[include\nlohmann\detail\input\input_adapters.hpp:429]: (style) Class 'input_adapter' has a constructor with 1 argument that is not explicit.
(17)[include\nlohmann\detail\json_ref.hpp:18]: (style) Class 'json_ref' has a constructor with 1 argument that is not explicit.
(18)[include\nlohmann\detail\json_ref.hpp:22]: (style) Class 'json_ref' has a constructor with 1 argument that is not explicit.
(19)[include\nlohmann\detail\json_ref.hpp:26]: (style) Class 'json_ref' has a constructor with 1 argument that is not explicit.
(20)[include\nlohmann\detail\json_ref.hpp:33]: (style) Class 'json_ref' has a constructor with 1 argument that is not explicit.
(21)[include\nlohmann\detail\output\output_adapters.hpp:105]: (style) Class 'output_adapter' has a constructor with 1 argument that is not explicit.
(22)[include\nlohmann\detail\output\output_adapters.hpp:108]: (style) Class 'output_adapter' has a constructor with 1 argument that is not explicit.
(23)[include\nlohmann\detail\output\output_adapters.hpp:111]: (style) Class 'output_adapter' has a constructor with 1 argument that is not explicit.
(24)[include\nlohmann\json.hpp:1162]: (style) Class 'basic_json' has a constructor with 1 argument that is not explicit.
(25)[include\nlohmann\json.hpp:1186]: (style) Class 'basic_json' has a constructor with 1 argument that is not explicit.
(26)[include\nlohmann\json.hpp:1253]: (style) Class 'basic_json' has a constructor with 1 argument that is not explicit.
(27)[include\nlohmann\json.hpp:1290]: (style) Class 'basic_json' has a constructor with 1 argument that is not explicit.
(28)[include\nlohmann\json.hpp:1730]: (style) Class 'basic_json' has a constructor with 1 argument that is not explicit.
(29)[include\nlohmann\detail\output\binary_writer.hpp:869]: (style) Consider using std::accumulate algorithm instead of a raw loop.
Some of them may be false positive, but others can be relevant, so this is why I've made this issue. The good news, is that all the warnings I have got are flagged as "style", not as error or warning, so their are less likely to bother most of people using cppcheck. 馃槃
If we successly correct all the warnings (and silence the false positive), we may even imagine adding cppcheck to the CI of the library. 馃
Let me know what you think about this idea. If you agree with the purpose of this issue, I'll gladly help to reach it.
For technical information, I've used the version 1.87 of cppcheck on the version 3.7.0 of the json library, on Windows, with Visual Studio 2017. You can find the repository on which I'm currently running this here
In a few minutes, I will also add a Pull Request which handles the warnings 6 and 29. 馃敎
PS: I don't know is this issue should be flagged as a feature request or as anything else, so I made it a regular issue.
@Xav83 Closed by #1760?
@t-b I don't think this issue should be closed, for now.
The Pull Request #1760 only fixed the warning 6 and 29.
The others remains unfixed yet
If I remove the warnings on non-explicit constructors (which are not a bug, but a feature for this library), we are left with the following issues:
(1)[include\nlohmann\json.hpp:5076]: (style) Variable 'm_value.object->emplace' is reassigned a value before the old one has been used.
(2)[include\nlohmann\detail\conversions\to_chars.hpp:585]: (style) The expression 'kAlpha >= -60' is always true.
(3)[include\nlohmann\detail\conversions\to_chars.hpp:586]: (style) The expression 'kGamma <= -32' is always true.
(4)[include\nlohmann\detail\output\serializer.hpp:726]: (style) The expression 'thousands_sep != '\0'' is always false because 'thousands_sep' and ''\0'' represent the same value.
(5)[include\nlohmann\detail\output\serializer.hpp:736]: (style) The expression 'decimal_point != '\0'' is always false because 'decimal_point' and ''\0'' represent the same value.
(7)[include\nlohmann\json.hpp:837]: (style) Local variable object shadows outer function
PRs welcome!
And even nicer than a PR fixes these issues would be adding the cppcheck to CI so that the codebase stays clean as well.
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
Those 2 warnings:
(4)[include\nlohmann\detail\output\serializer.hpp:726]: (style) The expression 'thousands_sep != '\0'' is always false because 'thousands_sep' and ''\0'' represent the same value.
(5)[include\nlohmann\detail\output\serializer.hpp:736]: (style) The expression 'decimal_point != '\0'' is always false because 'decimal_point' and ''\0'' represent the same value.
seems to be false positive, since the expression can be true since their are initialize as such:
, loc(std::localeconv())
, thousands_sep(loc->thousands_sep == nullptr ? '\0' : * (loc->thousands_sep))
, decimal_point(loc->decimal_point == nullptr ? '\0' : * (loc->decimal_point))
but cppcheck must deduce the warnings because of the default which is const too:
/// the locale's thousand separator character
const char thousands_sep = '\0';
/// the locale's decimal point character
const char decimal_point = '\0';
I have runned cppcheck on the version 3.7.3, the currently last release, and here are the warning that I have on a dummy project including the library through conan:
## To Check (Warnings to fix, or false positive, we don't know yet)
[C:\Users\Xaxavinou\.conan\data\jsonformoderncpp\3.7.3\vthiery\stable\package\5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9\include\nlohmann\json.hpp:5123] -> [C:\U
sers\Xaxavinou\.conan\data\jsonformoderncpp\3.7.3\vthiery\stable\package\5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9\include\nlohmann\json.hpp:5123]: (style) Vari
able 'm_value.object->emplace' is reassigned a value before the old one has been used.
[C:\Users\Xaxavinou\.conan\data\jsonformoderncpp\3.7.3\vthiery\stable\package\5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9\include\nlohmann\json.hpp:1590] -> [C:\U
sers\Xaxavinou\.conan\data\jsonformoderncpp\3.7.3\vthiery\stable\package\5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9\include\nlohmann\json.hpp:837]: (style) Local
variable object shadows outer function
[C:\Users\Xaxavinou\.conan\data\jsonformoderncpp\3.7.3\vthiery\stable\package\5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9\include\nlohmann\json.hpp:1019] -> [C:\U
sers\Xaxavinou\.conan\data\jsonformoderncpp\3.7.3\vthiery\stable\package\5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9\include\nlohmann\json.hpp:1022]: (warning) Ei
ther the condition 'stack.empty()' is redundant or stack is accessed out of bounds when stack is empty.
[C:\Users\Xaxavinou\.conan\data\jsonformoderncpp\3.7.3\vthiery\stable\package\5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9\include\nlohmann\json.hpp:1015]: (style)
Consider using std::transform algorithm instead of a raw loop.
[C:\Users\Xaxavinou\.conan\data\jsonformoderncpp\3.7.3\vthiery\stable\package\5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9\include\nlohmann\json.hpp:1038]: (style)
Consider using std::transform algorithm instead of a raw loop.
## False positive
[C:\Users\Xaxavinou\.conan\data\jsonformoderncpp\3.7.3\vthiery\stable\package\5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9\include\nlohmann\detail\conversions\to_c
hars.hpp:304] -> [C:\Users\Xaxavinou\.conan\data\jsonformoderncpp\3.7.3\vthiery\stable\package\5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9\include\nlohmann\detail
\conversions\to_chars.hpp:585]: (style) The expression 'kAlpha >= -60' is always true.
[C:\Users\Xaxavinou\.conan\data\jsonformoderncpp\3.7.3\vthiery\stable\package\5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9\include\nlohmann\detail\conversions\to_c
hars.hpp:305] -> [C:\Users\Xaxavinou\.conan\data\jsonformoderncpp\3.7.3\vthiery\stable\package\5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9\include\nlohmann\detail
\conversions\to_chars.hpp:586]: (style) The expression 'kGamma <= -32' is always true.
[C:\Users\Xaxavinou\.conan\data\jsonformoderncpp\3.7.3\vthiery\stable\package\5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9\include\nlohmann\detail\output\serialize
r.hpp:850] -> [C:\Users\Xaxavinou\.conan\data\jsonformoderncpp\3.7.3\vthiery\stable\package\5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9\include\nlohmann\detail\ou
tput\serializer.hpp:726]: (style) The expression 'thousands_sep != '\0'' is always false because 'thousands_sep' and ''\0'' represent the same value.
[C:\Users\Xaxavinou\.conan\data\jsonformoderncpp\3.7.3\vthiery\stable\package\5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9\include\nlohmann\detail\output\serialize
r.hpp:852] -> [C:\Users\Xaxavinou\.conan\data\jsonformoderncpp\3.7.3\vthiery\stable\package\5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9\include\nlohmann\detail\ou
tput\serializer.hpp:736]: (style) The expression 'decimal_point != '\0'' is always false because 'decimal_point' and ''\0'' represent the same value.
## Feature ofd the library
[C:\Users\Xaxavinou\.conan\data\jsonformoderncpp\3.7.3\vthiery\stable\package\5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9\include\nlohmann\detail\input\input_adap
ters.hpp:339]: (style) Class 'input_adapter' has a constructor with 1 argument that is not explicit.
[C:\Users\Xaxavinou\.conan\data\jsonformoderncpp\3.7.3\vthiery\stable\package\5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9\include\nlohmann\detail\input\input_adap
ters.hpp:342]: (style) Class 'input_adapter' has a constructor with 1 argument that is not explicit.
[C:\Users\Xaxavinou\.conan\data\jsonformoderncpp\3.7.3\vthiery\stable\package\5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9\include\nlohmann\detail\input\input_adap
ters.hpp:346]: (style) Class 'input_adapter' has a constructor with 1 argument that is not explicit.
[C:\Users\Xaxavinou\.conan\data\jsonformoderncpp\3.7.3\vthiery\stable\package\5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9\include\nlohmann\detail\input\input_adap
ters.hpp:349]: (style) Class 'input_adapter' has a constructor with 1 argument that is not explicit.
[C:\Users\Xaxavinou\.conan\data\jsonformoderncpp\3.7.3\vthiery\stable\package\5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9\include\nlohmann\detail\input\input_adap
ters.hpp:352]: (style) Class 'input_adapter' has a constructor with 1 argument that is not explicit.
[C:\Users\Xaxavinou\.conan\data\jsonformoderncpp\3.7.3\vthiery\stable\package\5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9\include\nlohmann\detail\input\input_adap
ters.hpp:355]: (style) Class 'input_adapter' has a constructor with 1 argument that is not explicit.
[C:\Users\Xaxavinou\.conan\data\jsonformoderncpp\3.7.3\vthiery\stable\package\5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9\include\nlohmann\detail\input\input_adap
ters.hpp:377]: (style) Class 'input_adapter' has a constructor with 1 argument that is not explicit.
[C:\Users\Xaxavinou\.conan\data\jsonformoderncpp\3.7.3\vthiery\stable\package\5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9\include\nlohmann\detail\input\input_adap
ters.hpp:421]: (style) Class 'input_adapter' has a constructor with 1 argument that is not explicit.
[C:\Users\Xaxavinou\.conan\data\jsonformoderncpp\3.7.3\vthiery\stable\package\5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9\include\nlohmann\detail\input\input_adap
ters.hpp:429]: (style) Class 'input_adapter' has a constructor with 1 argument that is not explicit.
[C:\Users\Xaxavinou\.conan\data\jsonformoderncpp\3.7.3\vthiery\stable\package\5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9\include\nlohmann\detail\json_ref.hpp:18]
: (style) Class 'json_ref' has a constructor with 1 argument that is not explicit.
[C:\Users\Xaxavinou\.conan\data\jsonformoderncpp\3.7.3\vthiery\stable\package\5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9\include\nlohmann\detail\json_ref.hpp:22]
: (style) Class 'json_ref' has a constructor with 1 argument that is not explicit.
[C:\Users\Xaxavinou\.conan\data\jsonformoderncpp\3.7.3\vthiery\stable\package\5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9\include\nlohmann\detail\json_ref.hpp:26]
: (style) Class 'json_ref' has a constructor with 1 argument that is not explicit.
[C:\Users\Xaxavinou\.conan\data\jsonformoderncpp\3.7.3\vthiery\stable\package\5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9\include\nlohmann\detail\json_ref.hpp:33]
: (style) Class 'json_ref' has a constructor with 1 argument that is not explicit.
[C:\Users\Xaxavinou\.conan\data\jsonformoderncpp\3.7.3\vthiery\stable\package\5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9\include\nlohmann\detail\output\output_ad
apters.hpp:105]: (style) Class 'output_adapter' has a constructor with 1 argument that is not explicit.
[C:\Users\Xaxavinou\.conan\data\jsonformoderncpp\3.7.3\vthiery\stable\package\5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9\include\nlohmann\detail\output\output_ad
apters.hpp:108]: (style) Class 'output_adapter' has a constructor with 1 argument that is not explicit.
[C:\Users\Xaxavinou\.conan\data\jsonformoderncpp\3.7.3\vthiery\stable\package\5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9\include\nlohmann\detail\output\output_ad
apters.hpp:111]: (style) Class 'output_adapter' has a constructor with 1 argument that is not explicit.
[C:\Users\Xaxavinou\.conan\data\jsonformoderncpp\3.7.3\vthiery\stable\package\5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9\include\nlohmann\json.hpp:1209]: (style)
Class 'basic_json' has a constructor with 1 argument that is not explicit.
[C:\Users\Xaxavinou\.conan\data\jsonformoderncpp\3.7.3\vthiery\stable\package\5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9\include\nlohmann\json.hpp:1233]: (style)
Class 'basic_json' has a constructor with 1 argument that is not explicit.
[C:\Users\Xaxavinou\.conan\data\jsonformoderncpp\3.7.3\vthiery\stable\package\5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9\include\nlohmann\json.hpp:1300]: (style)
Class 'basic_json' has a constructor with 1 argument that is not explicit.
[C:\Users\Xaxavinou\.conan\data\jsonformoderncpp\3.7.3\vthiery\stable\package\5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9\include\nlohmann\json.hpp:1337]: (style)
Class 'basic_json' has a constructor with 1 argument that is not explicit.
[C:\Users\Xaxavinou\.conan\data\jsonformoderncpp\3.7.3\vthiery\stable\package\5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9\include\nlohmann\json.hpp:1777]: (style)
Class 'basic_json' has a constructor with 1 argument that is not explicit.
I'm currently creating a repository with a project able to run cppcheck on any version of jsonformoderncpp. Once it will be done, I will be able to correct more easily the warnings, and this work might be adapted as a CI check to make sure that no other cppcheck warning are triggered in future development of jsonformoderncpp library, or with future cppcheck releases.
I will update you when this repository will be ready to use 馃檪
Here is a little update on where I am on the correction of the cppcheck fixes
I've finalize to repository on which I can run easily cppcheck with a simple program on jsonformoderncpp library, like any user of the library will do, and check if any warning is generated. You can find this repository here. 馃檪 馃憤
Once the cppcheck warnings fixed, this repository could be an inspiration to have automatic testing with cppcheck inside nlohmann/json repository. 馃槂
With that tool now available, I've stated correcting one warning on a Fork : (7)[include\nlohmann\json.hpp:837]: (style) Local variable object shadows outer function.
And I will continue in the next days to correct the other warnings and try to make cppcheck ignore the false positive.
I will update you when I will have other news to give you about this 馃槈
Until then, I wish you all a splendid day (or night 馃槃) !
Hi everyone ! 馃槂
Here is another update.
I've used to repository to facilitate the checking of the library with cppcheck to correct some more warnings, and find a way to ignore the warnings that should be ignore, like false positive and feature (such as constructor with one argument not explicit)
To ignore those, cppcheck manual indicates that we can add comments in the code to do so, and when running cppcheck, we only have to add the option --inline-suppr to have them out of the output. 馃檪
So I am going to make a Pull Request which will ignore all the warnings that must be ignored, to be able to focus on the last warning that need some code modifications.
I will make a list of the warnings that are left once the Pull Request will have been created and merge 馃槈
@Xav83 Thanks for the update. Just to make sure: are you aware of the Makefile target cppcheck (https://github.com/nlohmann/json/blob/develop/Makefile#L437)?
@nlohmann Actually, I wasn't aware of it ! This is great, it will simplify a lot the process I used to fix the warnings 馃槃 Thank you for this information !
@Xav83 Any news on this or can we close this?
Hi @nlohmann !
The latest news was the Pull Request #1876 in which I detailed how what are the solutions that I know of, to suppress some warnings which are one false positive from cppcheck.
I needed someone to validate which solution to integrate, or if another one is available, to finish having the library clear from cppcheck warnings
@Xav83 I think a pull request should do the trick for now
I today had another look at the warnings running Cppcheck 2.3 with
cppcheck --enable=all --inconclusive --force --std=c++11 single_include/nlohmann/json.hpp --error-exitcode=1
out of the long output, I think only the following reports are worth looking into:
single_include/nlohmann/json.hpp:17502:47: style: Local variable 'object' shadows outer function [shadowFunction]
std::unique_ptr<T, decltype(deleter)> object(AllocatorTraits::allocate(alloc, 1), deleter);
^
single_include/nlohmann/json.hpp:18403:23: note: Shadowed declaration
static basic_json object(initializer_list_t init = {})
^
single_include/nlohmann/json.hpp:17502:47: note: Shadow variable
std::unique_ptr<T, decltype(deleter)> object(AllocatorTraits::allocate(alloc, 1), deleter);
^
PR: #2536
single_include/nlohmann/json.hpp:5582:58: performance:inconclusive: Function parameter 'cb' should be passed by const reference. [passedByValue]
const parser_callback_t cb,
^
single_include/nlohmann/json.hpp:23226:53: performance:inconclusive: Function parameter 'cb' should be passed by const reference. [passedByValue]
const parser_callback_t cb = nullptr,
^
single_include/nlohmann/json.hpp:23265:53: performance:inconclusive: Function parameter 'cb' should be passed by const reference. [passedByValue]
const parser_callback_t cb = nullptr,
^
single_include/nlohmann/json.hpp:23277:53: performance:inconclusive: Function parameter 'cb' should be passed by const reference. [passedByValue]
const parser_callback_t cb = nullptr,
^
Will not be fixed; changing the signature to a const reference could break existing code. The copy is not too bad though, because the value is then stored inside the parser class.
single_include/nlohmann/json.hpp:4713:22: style: Consider using std::accumulate algorithm instead of a raw loop. [useStlAlgorithm]
seed = combine(seed, hash(element));
^
single_include/nlohmann/json.hpp:17714:27: style: Consider using std::transform algorithm instead of a raw loop. [useStlAlgorithm]
stack.push_back(std::move(it.second));
^
single_include/nlohmann/json.hpp:17737:31: style: Consider using std::transform algorithm instead of a raw loop. [useStlAlgorithm]
stack.push_back(std::move(it.second));
^
std::accumulate, but a raw loop would be more symmetric to the value_t::object case.The other messages are not really helpful, and, as I stated in #1876, I do not think it is a good idea to add dozens of cppcheck exclusion comments to the code.
cppcheck had a lot of update since I last runned it on the project 馃槃
@nlohmann To avoid having inline cppcheck exclusion comments, you can pass a file to cppcheck specifying the warnings to ignore: --suppressions-list=suppressions.txt.
Inline comments would ease a lot the integration of cppcheck in projects using the json library, or the integration of the json library in projects using cppcheck 馃槃
But with a "suppression" file, it will probably help the users too.
Whatever the solution used, it will also allow to have your CI enforcing cppcheck validation on the library code 馃槈
With merging https://github.com/nlohmann/json/pull/2536 I fixed the issues that I found relevant to fix. I do not think that adding a suppression list to the project and cppcheck to the CI makes sense at this point.
(We do use Cppcheck heavily at work, but I found it less useful in this project.)