Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

2nd round of cppcheck warning fixes #5125

Merged

Conversation

seanm
Copy link
Contributor

@seanm seanm commented Jan 7, 2025

No description provided.

@github-actions github-actions bot added area:Examples Demonstration of the use of classes type:Testing Ensure that the purpose of a class is met/the results on a wide set of test cases are correct area:Core Issues affecting the Core module area:Filtering Issues affecting the Filtering module area:IO Issues affecting the IO module area:Segmentation Issues affecting the Segmentation module area:Numerics Issues affecting the Numerics module labels Jan 7, 2025
@seanm
Copy link
Contributor Author

seanm commented Jan 7, 2025

@N-Dekker may interest you...

There are lots more of the 'use const references' warnings, but in public API, not sure if that's small enough a change to just do? It won't affect existing callers after all...

@@ -569,7 +569,7 @@ DOMNode::Find(const std::string & path)
if (pos != std::string::npos)
{
const std::string s2 = s.substr(pos + 1);
s = s.substr(0, pos);
s.resize(pos);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool refactoring!

@seanm seanm force-pushed the cppcheck2.16.0-part2 branch from 132040d to 49a2284 Compare January 7, 2025 19:51
Copy link
Member

@dzenanz dzenanz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Print_Array(itk::FixedArray<int, 3> x, std::ostream & os)
Print_Array(const itk::FixedArray<int, 3> & x, std::ostream & os)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this particular case, either way is fine by me. itk::FixedArray<int, 3> can be copied very quickly, as it is trivially copy-able. So the original pass-by-value does not involve dynamic memory allocation or the execution of a hand-written copy-constructor.

In general, pass-by-value (rather than pass-by-const-reference) has the advantage that it is more thread-safe. With pass-by-const-reference, the caller is responsible for keeping the object alive and unmodified, while the function is running. So pass-by-value is often simpler.

However, when copying is more expensive (as with an arbitrary std::vector), it's often beneficial to go for pass-by-const-reference. Then again, sometimes move-semantics is even better...

So as always, each approach has its pro's and con's 🤔

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Once we would have cppcheck on the CI, would it still be possible to allow pass-by-value (rather than pass-by-const-reference) in specific cases? For object types that can be copied very quickly. Or for specific functions?

Because as I wrote before, there are cases where pass-by-value is preferable.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think it warns about every single pass-by-value under the sun, only for some classes where it usually makes sense, like std::string.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed I see now that cppcheck does not warn for every pass-by-value (under the 🌞). Looks like it does not warn when you pass an empty struct by value. However, it does warn for itk::FixedArray. Looks like it even warns for very small ones, for example itk::FixedArray<int, 1> and itk::FixedArray<char, 1>. While passing those two by-value is probably faster than passing them by reference!

I'm not opposed to this specific code change, it's just a test anyway. But I just doubt if we should always enforce pass-by-const-reference whenever cppcheck tells us to do so.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI, I just posted at https://sourceforge.net/p/cppcheck/discussion/general/thread/cce6de4bfd/ "How to deal with passByValue (CWE: 398) warnings?"

math_test_helper(std::string str, bool test)
math_test_helper(const std::string & str, bool test)
Copy link
Contributor

@N-Dekker N-Dekker Jan 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this particular case, I would not expect any performance gain from using const std::string &, because math_test_helper is only called with a "literal" as argument. So if it's just about performance, I would use either const char * or (preferably) std::string_view as parameter type.

I'm interested to know if cppcheck allows passing std::string_view by value, because it's generally suggested to pass std::string_view by value.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cppcheck categorizes this under "performance", but this is just test code, so performance isn't an issue anyway.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, so this proposed change is only meant to make cppcheck happy, right?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So yes, cppcheck allows passing std::string_view by value 😃

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, so this proposed change is only meant to make cppcheck happy, right?

Yes. :)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just checked: replacing std::string with std::string_view does indeed make cppcheck happy, in this case :)

By the way, I just ran the Cppcheck 2.16.0 GUI application on Windows, analyzing source directory "ITK\Modules\Core\Common". I wasn't able to enable ITK_CPPCHECK_TEST in CMake. During CMake configuration, it says:

CMake Error at CMake/CppcheckTargets.cmake:131 (add_custom_command):
  TARGET 'all_cppcheck' was not created in this directory.
Call Stack (most recent call first):
  CMake/ITKModuleCPPCheckTest.cmake:12 (add_cppcheck_dir)
  CMake/ITKModuleMacros.cmake:201 (itk_module_cppcheck_test)
  Modules/Core/Common/CMakeLists.txt:141 (itk_module_impl)

Does the CMake option ITK_CPPCHECK_TEST work for you?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't use ITK_CPPCHECK_TEST. I used CMAKE_EXPORT_COMPILE_COMMANDS=ON then invoked with:

cppcheck --project=compile_commands.json --platform=unspecified --enable=style -q --library=qt --library=posix --library=gnu --library=bsd --library=windows --check-level=exhaustive --suppressions-list=../ITK/ITKcppcheckSuppressions.txt --template='{id},{file}:{line},{severity},{message}' -j22

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just checked: replacing std::string with std::string_view does indeed make cppcheck happy, in this case :)

OK, changed.

@seanm seanm force-pushed the cppcheck2.16.0-part2 branch from 49a2284 to f95ea0c Compare January 8, 2025 17:25
Copy link
Contributor

@N-Dekker N-Dekker left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved! The pass-by-const-references introduced with this PR are OK to me, it's just that I feel that cppcheck is too "pushy" with these passByValue warnings.

I would have preferred a few more string_view, rather than const std::string &, but I leave it up to you.

👍

TestCellInterface(std::string name, TCell * aCell)
TestCellInterface(const std::string & name, TCell * aCell)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Of course, the name parameter type of this TestCellInterface could also be string_view.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

TestCellInterface(std::string name, TCell * aCell)
TestCellInterface(const std::string & name, TCell * aCell)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

...and the name parameter of this TestCellInterface may also be string_view. (I guess it should also be placed in a different namespace, to avoid name conflicts with the other TestCellInterface function template, but apparently it "just" worked. That's probably beyond the scope of this PR anyway.)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

TestQECellInterface(std::string name, TCell * aCell)
TestQECellInterface(const std::string & name, TCell * aCell)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

string_view

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

seanm added 3 commits January 8, 2025 17:30
cppcheck identified this pattern, and suggested a fast alternative. Mutate the string instead of creating a copy.
cppcheck suggested all these. Happily does not affect callers of such functions.

In some cases used std::string_view instead.

I only changed non-public API here, for compatibility reasons.

The warning is of the form:

passedByValue,ITK/Modules/IO/PhilipsREC/src/itkPhilipsRECImageIO.cxx:211,performance,Function parameter 'imageTypesScanSequenceIndex' should be passed by const reference.
@seanm seanm force-pushed the cppcheck2.16.0-part2 branch from f95ea0c to 1ef2d1c Compare January 8, 2025 22:32
@dzenanz
Copy link
Member

dzenanz commented Jan 9, 2025

/azp run ITK.macOS

@dzenanz dzenanz merged commit 9ba9e28 into InsightSoftwareConsortium:master Jan 9, 2025
15 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area:Core Issues affecting the Core module area:Examples Demonstration of the use of classes area:Filtering Issues affecting the Filtering module area:IO Issues affecting the IO module area:Numerics Issues affecting the Numerics module area:Segmentation Issues affecting the Segmentation module type:Testing Ensure that the purpose of a class is met/the results on a wide set of test cases are correct
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants