-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Closed
Labels
Description
Describe the bug
I have a project A that generates a tag file, that my project B consumes.
The documentation step of project A goes fine. It uploads its tag file.
Then, project B picks up the tag file of project A and builds its own documentation. At that point, I'm seeing the following issue:
error: no uniquely matching class member found forI've been able to reproduce it, see below.
To Reproduce
Here is a self-contained reproducer using `Docker`.
You can build it with:
docker buildx build --progress plain --tag my-reproducer-image - < reproducer.dockerfileand the build will fail, demonstrating the issue.
FROM ubuntu:24.04
# Install system requirements.
RUN <<EOF
set -ex
apt update
apt --yes --no-install-recommends install gcc g++ python3 cmake make git flex bison ca-certificates
EOF
# Install custom Doxygen version from GitHub.
ARG DOXYGEN_VERSION=1.13.2
RUN <<EOF
git clone --depth=1 --branch Release_$(echo ${DOXYGEN_VERSION} | tr . _) https://github.com/doxygen/doxygen doxygen
cd doxygen
cmake -S . -B build -DCMAKE_INSTALL_PREFIX=/opt/doxygen-${DOXYGEN_VERSION}
cmake --build build -j4 --target install
EOF
ENV Doxygen_ROOT=/opt/doxygen-${DOXYGEN_VERSION}
# This is the problematic file.
COPY <<EOF generate-invalid-tag-file/MyLibrary.hpp
#ifndef MYLIBRARY_HPP
#define MYLIBRARY_HPP
#include <iostream>
#include <memory>
namespace mylib
{
//! Default implementation of a helper @c struct.
template <typename T>
struct MyHelper
{
//! Say hello to your developer.
void say_hello(const T value) const {
printf("Default %s %f\\n", __PRETTY_FUNCTION__, value);
}
};
//! Specialization for @c int.
template <>
struct MyHelper<int>
{
//! Deletor for @ref member.
struct Deletor
{
//! This is some documentation.
void operator()(const int*) const {}
};
void say_hello(const int value) const {
printf("Specialized %s %d\\n", __PRETTY_FUNCTION__, value);
}
using impl_event_t = int;
using event_storage_t = std::unique_ptr<impl_event_t, Deletor>;
event_storage_t member; //!< Member documentation.
};
//! This class call operator interfers with the above.
struct Other
{
template <typename T>
void operator()(const T&) const {
printf("%s\\n", __PRETTY_FUNCTION__);
}
};
//! This class call operator also interfers with the above.
struct YetAnOther
{
template <typename T>
void operator()(const T&) const {
printf("%s\\n", __PRETTY_FUNCTION__);
}
};
} // namespace mylib
#endif // MYLIBRARY_HPP
EOF
# A simple test to check it's valid C++.
COPY <<EOF generate-invalid-tag-file/test_mylib.cpp
#include "MyLibrary.hpp"
int main()
{
mylib::MyHelper<int >{}.say_hello(42);
mylib::MyHelper<double>{}.say_hello(42.);
mylib::Other {}.operator()<char>(char(42));
}
EOF
# This is a project that will generate an invalid tag file.
COPY <<EOF generate-invalid-tag-file/CMakeLists.txt
cmake_minimum_required(VERSION 3.25)
project(GenerateInvalidTagFile LANGUAGES CXX)
add_executable(test)
target_sources(test PRIVATE test_mylib.cpp)
find_package(Doxygen ${DOXYGEN_VERSION} REQUIRED)
set(DOXYGEN_EXTRACT_ALL YES)
set(DOXYGEN_WARN_AS_ERROR YES)
set(DOXYGEN_WARN_IF_UNDOCUMENTED NO)
set(DOXYGEN_GENERATE_TAGFILE "$\{CMAKE_SOURCE_DIR\}/invalid-tag-file.tag")
doxygen_add_docs(docs MyLibrary.hpp)
EOF
RUN <<EOF
set -ex
cd generate-invalid-tag-file
cmake -S . -B build
cmake --build build --target=test
./build/test
cmake --build build --target=docs
test -f invalid-tag-file.tag
EOF
# This is a project that will try to consume the invalid tag file.
COPY <<EOF consume-invalid-tag-file/test_empty.hpp
//! This does not matter.
void empty();
EOF
COPY <<EOF consume-invalid-tag-file/CMakeLists.txt
cmake_minimum_required(VERSION 3.25)
project(ConsumeInvalidTagFile LANGUAGES CXX)
find_package(Doxygen ${DOXYGEN_VERSION} REQUIRED)
set(DOXYGEN_EXTRACT_ALL YES)
set(DOXYGEN_WARN_AS_ERROR YES)
set(DOXYGEN_WARN_IF_UNDOCUMENTED NO)
set(DOXYGEN_TAGFILES "/generate-invalid-tag-file/invalid-tag-file.tag")
if(NOT EXISTS $\{DOXYGEN_TAGFILES\})
message(FATAL_ERROR "The tag file $\{DOXYGEN_TAGFILES\} path is not valid.")
endif()
doxygen_add_docs(docs test_empty.hpp)
EOF
RUN <<EOF
set -ex
cd consume-invalid-tag-file
cmake -S . -B build
cmake --build build --target=docs
EOFHere is the relevant output:
#18 0.464 + cmake --build build --target=docs
#18 0.519 [100%] Generate API documentation for docs
#18 0.533 /generate-invalid-tag-file/invalid-tag-file.tag:17: error: no uniquely matching class member found for
#18 0.533 void mylib::MyHelper< int >::Deletor::operator()(const int *) const
#18 0.533 Possible candidates:
#18 0.533 'void mylib::Other::operator()(const T &) const' at line 87 of file /generate-invalid-tag-file/invalid-tag-file.tag
#18 0.533 'void mylib::YetAnOther::operator()(const T &) const' at line 98 of file /generate-invalid-tag-file/invalid-tag-file.tag (warning treated as error, aborting now)
#18 0.533 Doxygen version used: 1.13.2 (26342b775ea25e6fefb53220926b20702c56fcb3)
#18 0.533 Searching for include files...
#18 0.533 Searching for example files...Expected behavior
The generator tag file should be valid, and reusable in downstream projects.
Version
Using Doxygen 1.13.2.