jnikula / hawkmoth

Hawkmoth - Sphinx Autodoc for C

Home Page:https://jnikula.github.io/hawkmoth/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

C++: hawkmoth warns about `#pragma once in main file`

stephanlachnit opened this issue · comments

hawkmoth (or more likely, clang) warns about #pragma once in main file.

To reproduce, try to add documentation for this file:

#pragma once

/*
 * Test doc
 */
void test_function() {}

The warning has no impact on the output.

It does work for me, though.

What's your platform and clang --version?

Also, what's the warning, exactly? If it can be reproduced on the hawkmoth command-line, all the better.

What's your platform and clang --version?

Debian clang version 16.0.6 (17)
Target: x86_64-pc-linux-gnu

On Debian Sid.

Also, what's the warning, exactly? If it can be reproduced on the hawkmoth command-line, all the better.

Interestingly, this does not appear when I run hawkmoth --verbose --domain cpp test.hpp, only when I add this file to sphinx via cpp:autodoc.

Interestingly, this does not appear when I run hawkmoth --verbose --domain cpp test.hpp, only when I add this file to sphinx via cpp:autodoc.

Oh? I only tested on the command-line, I'll need to try via the Sphinx extension.

Looks like this is related to having #pragma once in a file with suffix .c or .cpp i.e. not as a header guard in .h or .hpp.

Please either avoid doing that, or add -Wno-pragma-once-outside-header to hawkmoth_clang https://jnikula.github.io/hawkmoth/stable/extension.html#hawkmoth_clang

$ echo "#pragma once" > test.hpp
$ echo "#pragma once" > test.cpp
$ hawkmoth --domain=cpp test.hpp
$ hawkmoth --domain=cpp test.cpp
WARNING: test.cpp:1: #pragma once in main file
$ hawkmoth --domain=cpp --clang=-Wno-pragma-once-outside-header test.cpp

Looks like this is related to having #pragma once in a file with suffix .c or .cpp i.e. not as a header guard in .h or .hpp.

Nope, it definitely does for me when I use it via sphinx:

/home/stephan/Projects/constellation_asio_sd/docs/source/api.rst:9: WARNING: /home/stephan/Projects/constellation_asio_sd/test.hpp:1: #pragma once in main file

But I can confirm that renaming test.hpp to test.cpp and running hawkmoth via CLI does trigger it.

Okay, I can reproduce the behaviour, but I'm pretty confused why the result is different via CLI vs. Sphinx/pytest. It's reproducible also in the CLI test that gets run via pytest. I understand the warning, but not the difference.

There's basically three ways to work around this:

  • Passing -Wno-pragma-once-outside-header to Clang
  • Passing -xc-header or -xc++-header to Clang when parsing .h or .hpp
  • Using the traditional #ifndef header guards. (Unsolicited opinion, I'd always go for that instead of #pragma once, because the pragma is non-standard and can lead to issues.)

Hawkmoth could identify headers and pass the -x option, but I'd prefer not doing that until we've figured out where the difference comes from. Maybe there's a way to make the libclang detection work as it should instead.

If it this a clang issue, then I'm perfectly fine with adding -Wno-pragma-once-outside-header to the compile arguments. Thanks for looking into it!

Edit: this seams unrelated

It seems to be a bit ore interesting than just pragma once. For example, this code:

#include <exception>
#include <string>

namespace cnstln {
namespace CHIRP {

/**
 * Error thrown when a Message was not decoded successfully
*/
class DecodeError : public std::exception {
public:
    /**
     * @param error_message Error message
    */
    DecodeError(std::string error_message) : error_message_(std::move(error_message)) {}
    /**
     * @return Error message
    */
    const char* what() const noexcept override { return error_message_.c_str(); }
protected:
    /** The error message */
    std::string error_message_;
};

}
}

Produces no errors with the CLI, but gives

Exception occurred:
  File "/home/stephan/Projects/constellation_asio_sd/venv/lib/python3.11/site-packages/clang/cindex.py", line 650, in from_id
    raise ValueError('Unknown template argument kind %d' % id)
ValueError: Unknown template argument kind 604

via sphinx (using #211, but the error is happens after cursor.kind == CursorKind.UNEXPOSED_DECL)

Okay, I can reproduce the behaviour, but I'm pretty confused why the result is different via CLI vs. Sphinx/pytest. It's reproducible also in the CLI test that gets run via pytest. I understand the warning, but not the difference.

I found the bug, it comes from this lines:

clang_args = ['-xc++'] if self._domain == 'cpp' else []

I think this line can simply be removed, at least as far as my testing goes.

Are you sure your libclang and its python bindings are of the same version? ValueError: Unknown template argument kind 604 does not seem like something Hawkmoth could trigger.

Edit: this seams unrelated

Agreed.

Agreed.

FYI it looks like a C++20 bug in clang 16.

Okay, our -x<language> option usage was pretty inconsistent. I've hopefully fixed it in #213.

@stephanlachnit Many thanks for the report and debugging! There was more to this than met the eye at first.