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

Bug: Extension error on double definition #54

Open
arwedus opened this issue Nov 10, 2023 · 0 comments
Open

Bug: Extension error on double definition #54

arwedus opened this issue Nov 10, 2023 · 0 comments

Comments

@arwedus
Copy link

arwedus commented Nov 10, 2023

When running sphinx-build (5.3) with sphinxcontrib.doxylink (1.12.2) added on a doxygen XML generated with doxygen 1.9.7, I get the following errors in the build.

Example 1: the same local definition, but different

Extension error (sphinxcontrib.doxylink.doxylink):
Handler <function setup_doxylink_roles at 0x7f57602343a0> for event 'builder-inited' threw an exception (exception: Cannot add override to non-function 'msr::g_stopWatch')

I can't post the full example because the project is huge (and proprietary), so maybe could you give a few hints for which things to look out first?

The symbol that sphinx complains about is a global variable in two files:

// file: msr_rsp_runnable.cpp
namespace msr
{
extern msr::CStopWatch g_stopWatch;
}

second cpp file:

// file: msr_sfm_runnable.cpp
namespace msr
{
msr::CStopWatch g_stopWatch(12000);
} // namespace msr

The doxygen.tag file contains the symbol 4 times:

  <compound kind="file">
    <name>msr_rsp_runnable.cpp</name>
    <path>msr/msr_rsp/src/</path>
    <filename>msr__rsp__runnable_8cpp.html</filename>
    <namespace>msr</namespace>
    <member kind="variable">
      <type>msr::CStopWatch</type>
      <name>g_stopWatch</name>
      <anchorfile>namespacemsr.html</anchorfile>
      <anchor>a8dd8d700e0974fec9a7f7e38c55d1642</anchor>
      <arglist></arglist>
    </member>
  </compound>
  <compound kind="file">
    <name>msr_sfm_runnable.cpp</name>
    <path>msr/msr_sfm/src/</path>
    <filename>msr__sfm__runnable_8cpp.html</filename>
    <namespace>msr</namespace>
    <member kind="function">
      <type>msr::CStopWatch</type>
      <name>g_stopWatch</name>
      <anchorfile>namespacemsr.html</anchorfile>
      <anchor>af171e57ba75ecc541531fc57d7452bc5</anchor>
      <arglist>(12000)</arglist>
    </member>
  <compound kind="namespace">
    <name>msr</name>
    <filename>namespacemsr.html</filename>
    <member kind="function">
      <type>msr::CStopWatch</type>
      <name>g_stopWatch</name>
      <anchorfile>namespacemsr.html</anchorfile>
      <anchor>af171e57ba75ecc541531fc57d7452bc5</anchor>
      <arglist>(12000)</arglist>
    </member>
    <member kind="variable">
      <type>msr::CStopWatch</type>
      <name>g_stopWatch</name>
      <anchorfile>namespacemsr.html</anchorfile>
      <anchor>a8dd8d700e0974fec9a7f7e38c55d1642</anchor>
      <arglist></arglist>
    </member>
    <!-- ... -->
  </compound>

I think it is a problem of doxygen that it adds the variable with initalizer value as a function. Anyhow, would it be possible to catch this gently?

Example 2: Overriding #define

The same problem occurs in other kinds of "double definition by doxygen" situations, like:

// NEON_2_SSE.h
_NEON2SSESTORAGE uint8x8_t vadd_u8(uint8x8_t a, uint8x8_t b); // VADD.I8 d0,d0,d0
#define vadd_u8 vadd_s8

Doxygen XML:

  <compound kind="file">
    <name>NEON_2_SSE.h</name>
    <member kind="define">
      <type>#define</type>
      <name>vadd_u8</name>
      <anchorfile>NEON__2__SSE_8h.html</anchorfile>
      <anchor>a8744a9ca1aa66ab5e9cf9bc706a318c1</anchor>
      <arglist></arglist>
    </member>
    <member kind="function" static="yes">
      <type>static uint8x8_t</type>
      <name>vadd_u8</name>
      <anchorfile>NEON__2__SSE_8h.html</anchorfile>
      <anchor>a13f1019c21aa0d41088901b549d40570</anchor>
      <arglist>(uint8x8_t a, uint8x8_t b)</arglist>
    </member>

Doxylink error:

Extension error (sphinxcontrib.doxylink.doxylink):
Handler <function setup_doxylink_roles at 0x7f7b9b5ba3a0> for event 'builder-inited' threw an exception (exception: Cannot add override to non-function 'cfc_NEON_2_SSE.hpp::vadd_u8')

None of that code is nice, but I'd argue that this code exists and C/C++ builds it, so it should not lead to a crash of sphinxcontrib.doxylink.

Example 3: SFINAE

Here, I have totally valid C++ SFINAE template code that causes the dreaded error again:

Extension error (sphinxcontrib.doxylink.doxylink):
Handler <function setup_doxylink_roles at 0x7f22564e33a0> for event 'builder-inited' threw an exception (exception: Cannot add override to non-function 'loft2_int::exporter::has_method::test')

The C++ code (header file):

#include <type_traits>

namespace loft2_int
{
namespace exporter
{

// The template has_method<T> exports a boolean constant
// value that is true iff T provides int T::getDetectionID() const
template <typename ObjectType>
struct has_method
{
    // SFINAE: ensure correct signature via function pointer
    template <typename InternalObjectType>
    static std::true_type test(int (InternalObjectType::*)() const)
    {
        return std::true_type();
    }

    // SFINAE: ensure that method exists
    template <typename InternalObjectType>
    static decltype(test(&InternalObjectType::getDetectionID))
    test(decltype(&InternalObjectType::getDetectionID), void*)
    {
        // method exists, now check for correct signature
        using Return_type = decltype(test(&InternalObjectType::getDetectionID));
        return Return_type();
    }

    // SFINAE: otherwise return false type
    template <typename InternalObjectType>
    static std::false_type test(...)
    {
        return std::false_type();
    }

    // This will be either std::true_type or std::false_type
    using ResultType = decltype(test<ObjectType>(nullptr, nullptr));

    // make value accessible from outside
    static constexpr bool value = ResultType::value;
};

Doxygen gets the last one wrong:

  <compound kind="struct">
    <name>loft2_int::exporter::has_method</name>
    <filename>structloft2__int_1_1exporter_1_1has__method.html</filename>
    <templarg>typename ObjectType</templarg>
    <!-- ... -->
    <member kind="function" static="yes">
      <type>static std::true_type</type>
      <name>test</name>
      <anchorfile>structloft2__int_1_1exporter_1_1has__method.html</anchorfile>
      <anchor>aa271aedf2af8565e5c7fb5190032809e</anchor>
      <arglist>(int(InternalObjectType::*)() const)</arglist>
    </member>
    <member kind="function" static="yes">
      <type>static std::false_type</type>
      <name>test</name>
      <anchorfile>structloft2__int_1_1exporter_1_1has__method.html</anchorfile>
      <anchor>a604f0c99be193a6e7d9d455174c528c4</anchor>
      <arglist>(...)</arglist>
    </member>
    <member kind="variable" static="yes">
      <type>static decltype(test(&amp;InternalObjectType::getDetectionID))</type>
      <name>test</name>
      <anchorfile>structloft2__int_1_1exporter_1_1has__method.html</anchorfile>
      <anchor>a4553d86d6a8ba6c1045e0e65a34ff915</anchor>
      <arglist>(decltype(&amp;InternalObjectType::getDetectionID), void *)</arglist>
    </member>
@arwedus arwedus changed the title Bug: Extension error Bug: Extension error on double definition Nov 10, 2023
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

No branches or pull requests

1 participant