Skip to content

Conversation

@pjungkamp
Copy link
Contributor

@pjungkamp pjungkamp commented Jun 4, 2025

What is clang-tidy

clang-tidy is a linter developed as part of the clang-tools. This linter makes use of the clang C/C++ compiler front end to analyze and lint based on the actual C/C++ AST instead of the typical regex-based lints used by e.g. cppcheck.

This allows clang-tidy to automatically fix some of the errors it detects automatically. It is also nicely integrated with other clang tooling like the clangd language server.

Progress

  • Compile villas-node using clang and fix compiler warnings/errors
  • Run clang-tidy with a subset of checks enabled as a baseline check
    • modernize-use-override: Enfore CppCoreGuideline C.128. Refactor and cleanups #907 (comment)
    • misc-const-correctness: Add const to all variables that can be.
    • clang-analyzer-*: Use clang static analyzer to find memory leaks, null dereferences, use-after-free and other bugs hidden in control flow or non-exception-safe code.
  • Detect and run clang-tidy automatically through cmake's CMAKE_CXX_CLANG_TIDY integration.
  • Enforce a subset of warnings as errors in pre-commit (and therefore the CI)

@pjungkamp pjungkamp force-pushed the clang-tidy branch 4 times, most recently from 1003d2a to 3f9dfc6 Compare June 4, 2025 22:34
@pjungkamp
Copy link
Contributor Author

pjungkamp commented Jun 4, 2025

I'd like to also enable readability-isolate-declaration. This is more of a style choice, less about correctness.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The LinearAllocator triggered the clang-analyzer "dead-write" warning. I think this is definitely broken!

Copy link
Contributor

Choose a reason for hiding this comment

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

Okay, im fine with leaving it as is for now.. I am not aware of anybody using this code.

Maybe @n-eiling

Copy link
Member

Choose a reason for hiding this comment

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

I think the FPGA code is only using the HostRamAllocator. What is a dead-write warning?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

A dead write is a write to non-volatile memory that is never read for the remainder of that memory's lifetime. This constructor modifies the function parameters after the member variables have been assigned by the member-initialization-list. This means that these modifications will just be discarded at the end of a function.

@pjungkamp
Copy link
Contributor Author

@stv0g I added the NIX_LD and NIX_LD_LIBRARY_PATH environment variables to the devShells to allow the prebuilt pre-commit binaries to run on NixOS, which is missing a system-wide dynamic linker.

See https://github.com/nix-community/nix-ld?tab=readme-ov-file#usage

@stv0g
Copy link
Contributor

stv0g commented Jun 5, 2025

Great work :-)

This PR is getting a bit too large for confidently merging and reviewing it.

Especially the clang-tidy commit (cab6e02) is quite big..

I would favour to merge this as is now, or splitting up the PR into smaller ones which can be merged immediatly.

Copy link
Member

@n-eiling n-eiling left a comment

Choose a reason for hiding this comment

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

In general this looks like it improves code quality quite a bit, espc. regarding override/virtual. However, I'm not convinced of adding const everywhere. Surely the compiler will do this optimization automatically. I doubt it adds much value during programming. I get the value for function parameters, especially if part of an interface, but for local variables I don't see the point.
I want us to focus on making contributions to VILLAS easier, and forcing people to use const everywhere may not be a move in this direction, or what do you think?

Also again: Please do not do style and logic changes in one PR, especially a PR of this size.


// libpci handle of the device
const kernel::devices::PciDevice *pci_device;
[[maybe_unused]] const kernel::devices::PciDevice *pci_device;
Copy link
Member

Choose a reason for hiding this comment

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

Is this really something we want to introduce? It adds clutter to the code. In this instance, we should check whether we actually need this (now or in the future) and rather remove it.
Anything touching the FPGA code should be tested by someone with access to the FPGA before we should approve changes.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This private member variable was set in the constructor, yet never read or used anywhere. I didn't know whether this was some kind of guard variable keeping a PCI connection alive or something like that.

Copy link
Member

Choose a reason for hiding this comment

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

I suspect it's a leftover from when vfio devices were always PCI devices. If it's really unused now, we can remove it.

auto line = std::unique_ptr<char, decltype(line_destructor)>{
line_ptr, line_destructor};
if (ret == -1)
break;
Copy link
Member

Choose a reason for hiding this comment

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

I don't see the point of this. It's way less readable than the C code. If you absolutely must use C++, then why not use proper C++ file I/O? Also any change here needs to be tested by someone with access to an FPGA.

FILE *f = fopen(PROCFS_PATH "/cmdline", "r");
auto file_destructor = [](FILE *file) { fclose(file); };
auto f = std::unique_ptr<FILE, decltype(file_destructor)>{
fopen(PROCFS_PATH "/cmdline", "r"), file_destructor};
Copy link
Member

Choose a reason for hiding this comment

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

Same here. I don't see the point of this change. Also needs FPGA testing.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

clang-analyzer found a control flow path that lead to fclose not being called here. More specifically, it's missing an fclose before the return 0; // FOUND line. It also guards against leaks if an exception is thrown (I don't currently see any exception throwing code here, but I'd argue that using smart pointers for resource owning pointers is a better and less error-prone programming style.

Copy link
Member

Choose a reason for hiding this comment

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

Ok makes sense. Still you are mixing C and C++ code here, which I think is a bit ugly. Also the syntax is quite a bit more complex. I'm fine with your change, but I would prefer switching to a C++ API, or fixing the existing code.

f = fopen(fn, "w+");
auto file_destructor = [](FILE *file) { fclose(file); };
auto f = std::unique_ptr<FILE, decltype(file_destructor)>{fopen(fn, "w+"),
file_destructor};
Copy link
Member

Choose a reason for hiding this comment

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

Same.

FILE *f = fopen(argv[1], "r");
auto file_destructor = [](FILE *file) { fclose(file); };
auto f = std::unique_ptr<FILE, decltype(file_destructor)>{
fopen(argv[1], "r"), file_destructor};
Copy link
Member

Choose a reason for hiding this comment

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

I think this is less readable than the C code, and the better way would be to use C++ file I/O

#endif

rewind(stream);
(void)errno; // TODO: should we handle rewind errors?
Copy link
Member

Choose a reason for hiding this comment

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

Maybe make an issue

p->many ? producer_consumer_many : producer_consumer, p);

sleep(0.2);
// sleep(0.2); TODO: Is this supposed to to something? Yield?
Copy link
Member

Choose a reason for hiding this comment

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

Dead code. Can we understand why this was here before just removing it?

-not \( -path "${TOP_DIR}/fpga/thirdparty/*" -o -path "${TOP_DIR}/build*/*" \) | \
xargs clang-format --verbose -i
git ls-files -c -z -- "*.c" ".h" "*.hpp" "*.cpp" ":!:fpga/thirdparty" |\
xargs -0 clang-format --verbose -i
Copy link
Member

Choose a reason for hiding this comment

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

what are the implications of this change?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It does everything as before, except it only formats files known to git and works with paths that contain spaces and even newlines.

@n-eiling
Copy link
Member

n-eiling commented Jun 5, 2025

And any changes on what we expect from contributions should also be added here: https://villas.fein-aachen.org/docs/node/development/contributing Let's not let this get out of date again.

@pjungkamp
Copy link
Contributor Author

I want to emphasize that this PR is not yet ready. I just wanted to track the progress through the GitHub PR checklist and discuss what lints to enable initially.

I want to split the large enable clang tidy commit by the lint that it fixed. I can also split out a base commit that just fixes the clang build.

I'll also add a related PR to the style guide documentation before this is ready to review.

@stv0g
Copy link
Contributor

stv0g commented Jun 12, 2025

I want to emphasize that this PR is not yet ready.

Could we split out-some commits into small PRs please? There are multiple commits which deserve their own PR and we can review and merge those quicker.

Thanks :)

@stv0g stv0g mentioned this pull request Oct 30, 2025
@stv0g
Copy link
Contributor

stv0g commented Oct 30, 2025

I started to merge some unreleated changes of this PR via

@pjungkamp pjungkamp force-pushed the clang-tidy branch 2 times, most recently from d4ddbe6 to 3ff5b12 Compare January 25, 2026 00:38
@pjungkamp
Copy link
Contributor Author

I've redone the whole clang-tidy cleanup from scratch and thus removed some of the fixes I had applied before. Especially the fixes for static analyzer findings were still up for discussion.

This PR will "only" fix the Clang build, add a clang-tidy file with the modernize-use-override lint as the baseline.

Other lints and the CI integration should be added in separate MRs.

@pjungkamp pjungkamp marked this pull request as ready for review January 25, 2026 00:38
@pjungkamp pjungkamp requested review from n-eiling and stv0g January 25, 2026 00:52
@pjungkamp
Copy link
Contributor Author

The test:python failure in the CI is unrelated to this MR.

@pjungkamp
Copy link
Contributor Author

I fixed the pkg:nix:arx CI by switching from NixOS/bundlers to nix-community/nix-bundle.

https://github.com/NixOS/bundlers/blob/88ada423d9086c5e556da4243086f03d2d030f76/flake.nix#L52

This shouldn't affect behavior since NixOS/bundlers#bundlers.${system}.toArx uses a slightly out-of-date nix-community/nix-bundle under the hood, which caused the CI to fail.

@pjungkamp
Copy link
Contributor Author

pjungkamp commented Jan 25, 2026

It seems like there's some bug with the CI artifact upload. Maybe it's out of artifact/container storage? Looks like the entire CI broke down.

Signed-off-by: Philipp Jungkamp <philipp.jungkamp@rwth-aachen.de>

Signed-off-by: Steffen Vogel <steffen.vogel@opal-rt.com>
Signed-off-by: Philipp Jungkamp <philipp.jungkamp@rwth-aachen.de>

Signed-off-by: Steffen Vogel <steffen.vogel@opal-rt.com>
Signed-off-by: Philipp Jungkamp <philipp.jungkamp@rwth-aachen.de>

Signed-off-by: Steffen Vogel <steffen.vogel@opal-rt.com>
Signed-off-by: Philipp Jungkamp <philipp.jungkamp@rwth-aachen.de>

Signed-off-by: Steffen Vogel <steffen.vogel@opal-rt.com>
Signed-off-by: Philipp Jungkamp <philipp.jungkamp@rwth-aachen.de>

Signed-off-by: Steffen Vogel <steffen.vogel@opal-rt.com>
Signed-off-by: Philipp Jungkamp <philipp.jungkamp@rwth-aachen.de>

Signed-off-by: Steffen Vogel <steffen.vogel@opal-rt.com>
Signed-off-by: Philipp Jungkamp <philipp.jungkamp@rwth-aachen.de>

Signed-off-by: Steffen Vogel <steffen.vogel@opal-rt.com>
Signed-off-by: Philipp Jungkamp <philipp.jungkamp@rwth-aachen.de>

Signed-off-by: Steffen Vogel <steffen.vogel@opal-rt.com>
Signed-off-by: Philipp Jungkamp <philipp.jungkamp@rwth-aachen.de>

Signed-off-by: Steffen Vogel <steffen.vogel@opal-rt.com>
Signed-off-by: Philipp Jungkamp <philipp.jungkamp@rwth-aachen.de>

Signed-off-by: Steffen Vogel <steffen.vogel@opal-rt.com>
Signed-off-by: Philipp Jungkamp <philipp.jungkamp@rwth-aachen.de>

Signed-off-by: Steffen Vogel <steffen.vogel@opal-rt.com>
Signed-off-by: Philipp Jungkamp <philipp.jungkamp@rwth-aachen.de>

Signed-off-by: Steffen Vogel <steffen.vogel@opal-rt.com>
Signed-off-by: Philipp Jungkamp <philipp.jungkamp@rwth-aachen.de>

Signed-off-by: Steffen Vogel <steffen.vogel@opal-rt.com>
Signed-off-by: Philipp Jungkamp <philipp.jungkamp@rwth-aachen.de>

Signed-off-by: Steffen Vogel <steffen.vogel@opal-rt.com>
Signed-off-by: Philipp Jungkamp <philipp.jungkamp@rwth-aachen.de>

Signed-off-by: Steffen Vogel <steffen.vogel@opal-rt.com>
Signed-off-by: Philipp Jungkamp <philipp.jungkamp@rwth-aachen.de>

Signed-off-by: Steffen Vogel <steffen.vogel@opal-rt.com>
Signed-off-by: Philipp Jungkamp <philipp.jungkamp@rwth-aachen.de>

Signed-off-by: Steffen Vogel <steffen.vogel@opal-rt.com>
…nt64_t

Signed-off-by: Philipp Jungkamp <philipp.jungkamp@rwth-aachen.de>

Signed-off-by: Steffen Vogel <steffen.vogel@opal-rt.com>
Signed-off-by: Philipp Jungkamp <philipp.jungkamp@rwth-aachen.de>

Signed-off-by: Steffen Vogel <steffen.vogel@opal-rt.com>
Signed-off-by: Philipp Jungkamp <philipp.jungkamp@rwth-aachen.de>

Signed-off-by: Steffen Vogel <steffen.vogel@opal-rt.com>
Signed-off-by: Philipp Jungkamp <philipp.jungkamp@rwth-aachen.de>

Signed-off-by: Steffen Vogel <steffen.vogel@opal-rt.com>
Signed-off-by: Philipp Jungkamp <philipp.jungkamp@rwth-aachen.de>

Signed-off-by: Steffen Vogel <steffen.vogel@opal-rt.com>
Signed-off-by: Philipp Jungkamp <philipp.jungkamp@rwth-aachen.de>

Signed-off-by: Steffen Vogel <steffen.vogel@opal-rt.com>
Signed-off-by: Philipp Jungkamp <philipp.jungkamp@rwth-aachen.de>

Signed-off-by: Steffen Vogel <steffen.vogel@opal-rt.com>
Signed-off-by: Philipp Jungkamp <philipp.jungkamp@rwth-aachen.de>

Signed-off-by: Steffen Vogel <steffen.vogel@opal-rt.com>
Signed-off-by: Philipp Jungkamp <philipp.jungkamp@rwth-aachen.de>

Signed-off-by: Steffen Vogel <steffen.vogel@opal-rt.com>
@stv0g
Copy link
Contributor

stv0g commented Jan 26, 2026

I fixed the broken test:python and packaging:nix:arx CI jobs in master and rebased this PR onto it.

Copy link
Contributor

@stv0g stv0g left a comment

Choose a reason for hiding this comment

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

Thanks :)

@stv0g stv0g merged commit a960050 into master Jan 26, 2026
3 checks passed
@stv0g stv0g deleted the clang-tidy branch January 26, 2026 09:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants