Bug #1435
openProblematic tracepoint provider header files in LTTng-UST test suite
0%
Description
Dear LTTng developers,
We are long time happy users of LTTng-UST technology. Thank you for developing and maintaining it.
TLDR: We have stumbled upon build problem involving modern Clang versions and tracepoint provider header files in the LTTng-UST test suite, which I believe is coding error in those files. The fix appears to be easy: just remove some offending include directives from affected files.
Recently we have upgraded our toolchain to LLVM 20 + libstdc++ from GCC 15. We are also evaluating upgrade of our LTTng dependencies to latest versions. By default we provide -std=gnu++23 to CXXFLAGS building all components. Rebuilding LTTng-UST v2.13.9 and also from stable-2.15 branch, I've stumbled on compilation error in one of the tests. Here is a Dockerfile for convenience so you can reproduce it yourselves:
FROM quay.io/centos/centos:stream9
RUN dnf -y group install "Development Tools" && \
dnf -y install llvm clang lld
ARG WORKDIR=/work
ARG DISTDIR=/work/dist
ARG URCU_BRANCH=stable-0.15
ARG LTTNG_UST_BRANCH=stable-2.15
RUN mkdir $WORKDIR && cd $WORKDIR && \
git clone -b $URCU_BRANCH https://github.com/urcu/userspace-rcu.git && \
git clone -b $LTTNG_UST_BRANCH https://github.com/lttng/lttng-ust.git
WORKDIR $WORKDIR
ARG CC=clang CXX=clang++
ARG CXX_STANDARD=20
ENV CC=$CC CXX=$CXX
ENV CXXFLAGS="-std=gnu++${CXX_STANDARD}"
ENV PKG_CONFIG_PATH=$DISTDIR/lib/pkgconfig
RUN <<EOF
#!/bin/sh
set -e
set -x
cd $WORKDIR/userspace-rcu
autoreconf -vi
./configure --prefix=$DISTDIR --disable-static
make -j8 V=1
make check
make install
EOF
# Save script for manual invocations with different parameters
COPY --chmod=0755 <<EOF $WORKDIR/build-lttng-ust.sh
#!/bin/sh
set -e
set -x
cd $WORKDIR/lttng-ust
autoreconf -vi
./configure --prefix=$DISTDIR --disable-static \
--disable-man-pages --without-sdt --disable-numa --disable-examples
make -j8 V=1
make check
EOF
RUN /work/build-lttng-ust.sh
When executed with Podman build command, it would fail like this:
podman build .
...
In file included from tp-cpp.cpp:8:
In file included from ./ust_tests_hello.h:62:
In file included from ../../../../include/lttng/tracepoint-event.h:67:
In file included from ../../../../include/lttng/ust-tracepoint-event.h:1189:
In file included from ./ust_tests_hello.h:14:
In file included from /usr/bin/../lib/clang/21/include/stddef.h:88:
/usr/bin/../lib/clang/21/include/__stddef_ptrdiff_t.h:18:1: error: expected expression
18 | typedef __PTRDIFF_TYPE__ ptrdiff_t;
| ^
In file included from tp-cpp.cpp:8:
In file included from ./ust_tests_hello.h:62:
In file included from ../../../../include/lttng/tracepoint-event.h:67:
../../../../include/lttng/ust-tracepoint-event.h:1204:15: error: invalid application of 'sizeof' to an incomplete type 'const struct lttng_ust_event_desc *const[]'
1204 | .nr_events = LTTNG_UST__TP_ARRAY_SIZE(LTTNG_UST__TP_COMBINE_TOKENS(lttng_ust__provider_event_desc___, LTTNG_UST_TRACEPOINT_PROVIDER)) - 1,
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
../../../../include/lttng/ust-tracepoint-event.h:97:46: note: expanded from macro 'LTTNG_UST__TP_ARRAY_SIZE'
97 | #define LTTNG_UST__TP_ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
| ^~~~~
This is due to include directive inside array initializer list in https://github.com/lttng/lttng-ust/blob/v2.13.9/include/lttng/ust-tracepoint-event.h#L1181
I was able to minimize repro case to this:
$ cat minrepro.cpp
#include <stddef.h>
[[maybe_unused]] static const int arr[] = {
#include <stddef.h>
0,
};
[[maybe_unused]] static const int len = (sizeof(arr) / sizeof((arr)[0]));
It happens to work with GCC, and it worked with older Clang versions thanks to #pragma once or equivalent guard:
$ clang++ -std=c++17 -Wall -Wextra -pedantic -c minrepro.cpp && echo OK OK $ g++ -std=c++23 -Wall -Wextra -pedantic -c minrepro.cpp && echo OK OK
But it fails to be compiled with modern Clang in modern C++ mode:
$ clang++ -std=c++20 -Wall -Wextra -pedantic -c minrepro.cpp && echo OK
In file included from minrepro.cpp:4:
In file included from /usr/bin/../lib/clang/21/include/stddef.h:88:
/usr/bin/../lib/clang/21/include/__stddef_ptrdiff_t.h:18:1: error: expected expression
18 | typedef __PTRDIFF_TYPE__ ptrdiff_t;
| ^
minrepro.cpp:8:48: error: invalid application of 'sizeof' to an incomplete type 'const int[]'
8 | [[maybe_unused]] static const int len = (sizeof(arr) / sizeof((arr)[0]));
| ^~~~~
2 errors generated.
This is because modern Clang implements magic of Clang Modules:
- https://clang.llvm.org/docs/Modules.html
- https://reviews.llvm.org/D159064
- https://github.com/llvm/llvm-project/blob/llvmorg-20.1.7/clang/lib/Headers/__stddef_ptrdiff_t.h
The repro can be further minimized to more clearly demonstrate that specific Clang trouble:
$ cat minrepro2.cpp
[[maybe_unused]] static const int arr[] = {
typedef int foo;
0,
};
Of course, for building LTTng-UST we can use older C++ standard like -std=c++17, or let LTTng configure default to c++11.
Cleaner solution would be avoid including anything in tracepoint provider header files:
$ git diff -- tests/compile/api0/hello.cxx/
diff --git a/tests/compile/api0/hello.cxx/ust_tests_hello.h b/tests/compile/api0/hello.cxx/ust_tests_hello.h
index 1963e737..a968cd8f 100644
--- a/tests/compile/api0/hello.cxx/ust_tests_hello.h
+++ b/tests/compile/api0/hello.cxx/ust_tests_hello.h
@@ -11,7 +11,6 @@
#define _TRACEPOINT_UST_TESTS_HELLO_H
#include <lttng/tracepoint.h>
-#include <stddef.h>
TRACEPOINT_ENUM(ust_tests_hello, my_enum,
TP_ENUM_VALUES(
I was able to build stable-2.15 by patching tracepoint provider header files in tests to remove all includes like stddef.h stdbool.h and the like -- basically all except strictly necessary lttng ones:
$ git status --short M tests/compile/api0/hello-many/ust_tests_hello_many.h M tests/compile/api0/hello.cxx/ust_tests_hello.h M tests/compile/api0/hello/ust_tests_hello.h M tests/compile/api1/hello-many/ust_tests_hello_many.h M tests/compile/api1/hello.cxx/ust_tests_hello.h M tests/compile/api1/hello/ust_tests_hello.h M tests/compile/api1/test-app-ctx/ust_tests_hello.h M tests/regression/abi0-conflict/ust_tests_hello.h $
Thankfully, example in the official documentation is clean in this regard: https://lttng.org/docs/v2.15/#doc-tracing-your-own-user-application