Skip to content

Instantly share code, notes, and snippets.

@rzarzynski
Last active January 18, 2022 15:32
Show Gist options
  • Save rzarzynski/d6d2df6888923bef6a3e764f4856853f to your computer and use it in GitHub Desktop.
Save rzarzynski/d6d2df6888923bef6a3e764f4856853f to your computer and use it in GitHub Desktop.

dout & need_dynamic on GCC 12

The bug report

rzarzynski: question about need_dynamic stuff in dout.h? see https://paste.centos.org/view/e8c376ec.

full log at https://kojipkgs.fedoraproject.org//work/tasks/2255/81372255/build.log

Sandbox

The following sippet is available on goldbot.org.

#include <iostream>
#include <utility>

namespace ceph::dout {

template<typename T>
struct dynamic_marker_t {
  T value;
  operator T() const { return value; }
};

template<typename T>
dynamic_marker_t<T> need_dynamic(T&& t) {
  return dynamic_marker_t<T>{ std::forward<T>(t) };
}

template<typename T>
struct is_dynamic : public std::false_type {};

template<typename T>
struct is_dynamic<dynamic_marker_t<T>> : public std::true_type {};

} // ceph::dout

#define dout_impl(cct, sub, v)                                          \
  do {                                                                  \
  const bool dyn_or_stat = [&](const auto cctX) {                     \
    if constexpr (ceph::dout::is_dynamic<decltype(sub)>::value ||       \
                  ceph::dout::is_dynamic<decltype(v)>::value) {         \
      return true;                 \
    } else {                                                            \
      /* The parentheses are **essential** because commas in angle      \
       * brackets are NOT ignored on macro expansion! A language's      \
       * limitation, sorry. */                                          \
      return false;    \
    }                                                                   \
  }(cct);                                                               \
                                                                        \
  if (true) {                                                  \
    std::cout << (dyn_or_stat ? "dynamic " : "static ")

#define dendl_impl std::endl;                                          \
  }                                                                     \
  } while (0)


#define ldpp_dout(dpp, v)                                               \
  if (decltype(auto) pdpp = (dpp); pdpp) /* workaround -Wnonnull-compare for 'this' */ \
    dout_impl(nullptr, ceph::dout::need_dynamic(42), v)

int main (void)
{
  ldpp_dout(42, 20) << "OK!" << dendl_impl;
}

Fix?

It is unkwnown whether the following patch fixes the issue or not. Unfortunately, an environment with GCC-12 onboard isn't easily available yet. Under x86-64 gcc (trunk) on goldbot.org the problem does not replicate.

diff --git a/src/common/dout.h b/src/common/dout.h
index 421222d535f..3a76a842704 100644
--- a/src/common/dout.h
+++ b/src/common/dout.h
@@ -99,11 +99,14 @@ namespace ceph::dout {
 template<typename T>
 struct dynamic_marker_t {
   T value;
-  operator T() const { return value; }
+  // constexpr ctor isn't needed as it's an aggregate type
+  constexpr operator T() const { return value; }
 };
 
 template<typename T>
-dynamic_marker_t<T> need_dynamic(T&& t) {
+constexpr dynamic_marker_t<T> need_dynamic(T&& t) {
+  // deprecated in C++17 but that's fine for testing
+  static_assert(std::is_literal_type_v<T>);
+  static_assert(std::is_literal_type_v<dynamic_marker_t<T>>);
   return dynamic_marker_t<T>{ std::forward<T>(t) };
 }
@rzarzynski
Copy link
Author

Archiving the links:

  1. https://paste.centos.org/view/e8c376ec
This code:
 
...
template<typename T>
dynamic_marker_t<T> need_dynamic(T&& t) {
  return dynamic_marker_t<T>{ std::forward<T>(t) };
}
...
#define ldpp_dout(dpp, v)                                               \
  if (decltype(auto) pdpp = (dpp); pdpp) /* workaround -Wnonnull-compare for 'this' */ \
    dout_impl(pdpp->get_cct(), ceph::dout::need_dynamic(pdpp->get_subsys()), v) \
      pdpp->gen_prefix(*_dout)
...
 
 
Is giving this compile error with gcc-12:
 
...
/builddir/build/BUILD/ceph-16.2.7/src/common/dout.h:185:56: error: call to non-'constexpr' function 'ceph::dout::dynamic_marker_t<T> ceph::dout::need_dynamic(T&&) [with T = unsigned int]'
  185 |     dout_impl(pdpp->get_cct(), ceph::dout::need_dynamic(pdpp->get_subsys()), v) \
      |                                ~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~
...
  1. Important parts of https://kojipkgs.fedoraproject.org//work/tasks/2255/81372255/build.log:
FAILED: src/common/CMakeFiles/common-common-objs.dir/LogClient.cc.o 
/usr/bin/g++ -DBOOST_ASIO_DISABLE_THREAD_KEYWORD_EXTENSION -DBOOST_ASIO_USE_TS_EXECUTOR_AS_DEFAULT -DCEPH_DATADIR=\"/usr/share/ceph\" -DCEPH_LIBDIR=\"/usr/lib64\" -DCEPH_PKGLIBDIR=\"/usr/lib64/ceph\" -DHAVE_CONFIG_H -D_FILE_OFFSET_BITS=64 -D_FORTIFY_SOURCE=2 -D_GNU_SOURCE -D_REENTRANT -D_THREAD_SAFE -D__CEPH__ -D__STDC_FORMAT_MACROS -D__linux__ -I/builddir/build/BUILD/ceph-16.2.7/build/redhat-linux-build/src/include -I/builddir/build/BUILD/ceph-16.2.7/src -isystem /builddir/build/BUILD/ceph-16.2.7/build/redhat-linux-build/include -isystem /builddir/build/BUILD/ceph-16.2.7/src/xxHash -isystem /builddir/build/BUILD/ceph-16.2.7/src/rapidjson/include -O2  -fexceptions -g -grecord-gcc-switches -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -fstack-protector-strong -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1  -m64  -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -O2 -g -DNDEBUG -fPIC   -U_FORTIFY_SOURCE -Wall -fno-strict-aliasing -fsigned-char -Wtype-limits -Wignored-qualifiers -Wpointer-arith -Werror=format-security -Winit-self -Wno-unknown-pragmas -Wnon-virtual-dtor -Wno-ignored-qualifiers -ftemplate-depth-1024 -Wpessimizing-move -Wredundant-move -Wstrict-null-sentinel -Woverloaded-virtual -fno-new-ttp-matching -fstack-protector-strong -fdiagnostics-color=auto -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-free -std=c++17 -MD -MT src/common/CMakeFiles/common-common-objs.dir/LogClient.cc.o -MF src/common/CMakeFiles/common-common-objs.dir/LogClient.cc.o.d -o src/common/CMakeFiles/common-common-objs.dir/LogClient.cc.o -c /builddir/build/BUILD/ceph-16.2.7/src/common/LogClient.cc
In file included from /builddir/build/BUILD/ceph-16.2.7/src/mon/Session.h:22,
                 from /builddir/build/BUILD/ceph-16.2.7/src/messages/PaxosServiceMessage.h:7,
                 from /builddir/build/BUILD/ceph-16.2.7/src/messages/MLog.h:19,
                 from /builddir/build/BUILD/ceph-16.2.7/src/common/LogClient.cc:17:
/builddir/build/BUILD/ceph-16.2.7/src/include/xlist.h:162:24: warning: 'template<class _Category, class _Tp, class _Distance, class _Pointer, class _Reference> struct std::iterator' is deprecated [-Wdeprecated-declarations]
  162 |   class iterator: std::iterator<std::forward_iterator_tag, T> {
      |                        ^~~~~~~~
In file included from /usr/include/c++/12/bits/stl_algobase.h:65,
                 from /usr/include/c++/12/bits/specfun.h:45,
                 from /usr/include/c++/12/cmath:1935,
                 from /usr/include/c++/12/math.h:36,
                 from /builddir/build/BUILD/ceph-16.2.7/src/include/utime.h:18,
                 from /builddir/build/BUILD/ceph-16.2.7/src/common/LogEntry.h:18,
                 from /builddir/build/BUILD/ceph-16.2.7/src/common/LogClient.h:19,
                 from /builddir/build/BUILD/ceph-16.2.7/src/common/LogClient.cc:15:
/usr/include/c++/12/bits/stl_iterator_base_types.h:127:34: note: declared here
  127 |     struct _GLIBCXX17_DEPRECATED iterator
      |                                  ^~~~~~~~
In file included from /builddir/build/BUILD/ceph-16.2.7/src/mon/Session.h:22,
                 from /builddir/build/BUILD/ceph-16.2.7/src/messages/PaxosServiceMessage.h:7,
                 from /builddir/build/BUILD/ceph-16.2.7/src/messages/MLog.h:19,
                 from /builddir/build/BUILD/ceph-16.2.7/src/common/LogClient.cc:17:
/builddir/build/BUILD/ceph-16.2.7/src/include/xlist.h:186:30: warning: 'template<class _Category, class _Tp, class _Distance, class _Pointer, class _Reference> struct std::iterator' is deprecated [-Wdeprecated-declarations]
  186 |   class const_iterator: std::iterator<std::forward_iterator_tag, T> {
      |                              ^~~~~~~~
In file included from /usr/include/c++/12/bits/stl_algobase.h:65,
                 from /usr/include/c++/12/bits/specfun.h:45,
                 from /usr/include/c++/12/cmath:1935,
                 from /usr/include/c++/12/math.h:36,
                 from /builddir/build/BUILD/ceph-16.2.7/src/include/utime.h:18,
                 from /builddir/build/BUILD/ceph-16.2.7/src/common/LogEntry.h:18,
                 from /builddir/build/BUILD/ceph-16.2.7/src/common/LogClient.h:19,
                 from /builddir/build/BUILD/ceph-16.2.7/src/common/LogClient.cc:15:
/usr/include/c++/12/bits/stl_iterator_base_types.h:127:34: note: declared here
  127 |     struct _GLIBCXX17_DEPRECATED iterator
      |                                  ^~~~~~~~
In file included from /builddir/build/BUILD/ceph-16.2.7/src/librados/ListObjectImpl.h:19,
                 from /builddir/build/BUILD/ceph-16.2.7/src/osd/osd_types.h:51,
                 from /builddir/build/BUILD/ceph-16.2.7/src/osd/OSDMap.h:38,
                 from /builddir/build/BUILD/ceph-16.2.7/src/mon/Session.h:29,
                 from /builddir/build/BUILD/ceph-16.2.7/src/messages/PaxosServiceMessage.h:7,
                 from /builddir/build/BUILD/ceph-16.2.7/src/messages/MLog.h:19,
                 from /builddir/build/BUILD/ceph-16.2.7/src/common/LogClient.cc:17:
/builddir/build/BUILD/ceph-16.2.7/src/include/rados/librados.hpp:107:54: warning: 'template<class _Category, class _Tp, class _Distance, class _Pointer, class _Reference> struct std::iterator' is deprecated [-Wdeprecated-declarations]
  107 |   class CEPH_RADOS_API NObjectIterator : public std::iterator <std::forward_iterator_tag, ListObject> {
      |                                                      ^~~~~~~~
In file included from /usr/include/c++/12/bits/stl_algobase.h:65,
                 from /usr/include/c++/12/bits/specfun.h:45,
                 from /usr/include/c++/12/cmath:1935,
                 from /usr/include/c++/12/math.h:36,
                 from /builddir/build/BUILD/ceph-16.2.7/src/include/utime.h:18,
                 from /builddir/build/BUILD/ceph-16.2.7/src/common/LogEntry.h:18,
                 from /builddir/build/BUILD/ceph-16.2.7/src/common/LogClient.h:19,
                 from /builddir/build/BUILD/ceph-16.2.7/src/common/LogClient.cc:15:
/usr/include/c++/12/bits/stl_iterator_base_types.h:127:34: note: declared here
  127 |     struct _GLIBCXX17_DEPRECATED iterator
      |                                  ^~~~~~~~
In file included from /builddir/build/BUILD/ceph-16.2.7/src/include/Context.h:19,
                 from /builddir/build/BUILD/ceph-16.2.7/src/msg/Message.h:24,
                 from /builddir/build/BUILD/ceph-16.2.7/src/messages/PaxosServiceMessage.h:6,
                 from /builddir/build/BUILD/ceph-16.2.7/src/messages/MLog.h:19,
                 from /builddir/build/BUILD/ceph-16.2.7/src/common/LogClient.cc:17:
/builddir/build/BUILD/ceph-16.2.7/src/osd/osd_types.h: In lambda function:
/builddir/build/BUILD/ceph-16.2.7/src/common/dout.h:185:56: error: call to non-'constexpr' function 'ceph::dout::dynamic_marker_t<T> ceph::dout::need_dynamic(T&&) [with T = unsigned int]'
  185 |     dout_impl(pdpp->get_cct(), ceph::dout::need_dynamic(pdpp->get_subsys()), v) \
      |                                ~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~
/builddir/build/BUILD/ceph-16.2.7/src/common/dout.h:156:58: note: in definition of macro 'dout_impl'
  156 |       return (cctX->_conf->subsys.template should_gather<sub, v>());    \
      |                                                          ^~~
/builddir/build/BUILD/ceph-16.2.7/src/osd/osd_types.h:3570:3: note: in expansion of macro 'ldpp_dout'
 3570 |   ldpp_dout(dpp, 10) << "build_prior all_probe " << all_probe << dendl;
      |   ^~~~~~~~~
/builddir/build/BUILD/ceph-16.2.7/src/common/dout.h:106:21: note: 'ceph::dout::dynamic_marker_t<T> ceph::dout::need_dynamic(T&&) [with T = unsigned int]' declared here
  106 | dynamic_marker_t<T> need_dynamic(T&& t) {
      |                     ^~~~~~~~~~~~
/builddir/build/BUILD/ceph-16.2.7/src/osd/osd_types.h: In lambda function:
/builddir/build/BUILD/ceph-16.2.7/src/common/dout.h:185:56: error: call to non-'constexpr' function 'ceph::dout::dynamic_marker_t<T> ceph::dout::need_dynamic(T&&) [with T = unsigned int]'
  185 |     dout_impl(pdpp->get_cct(), ceph::dout::need_dynamic(pdpp->get_subsys()), v) \
      |                                ~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~
/builddir/build/BUILD/ceph-16.2.7/src/common/dout.h:156:58: note: in definition of macro 'dout_impl'
  156 |       return (cctX->_conf->subsys.template should_gather<sub, v>());    \
      |                                                          ^~~
/builddir/build/BUILD/ceph-16.2.7/src/osd/osd_types.h:3589:7: note: in expansion of macro 'ldpp_dout'
 3589 |       ldpp_dout(dpp, 10) << "build_prior maybe_rw interval:" << start
      |       ^~~~~~~~~
/builddir/build/BUILD/ceph-16.2.7/src/common/dout.h:106:21: note: 'ceph::dout::dynamic_marker_t<T> ceph::dout::need_dynamic(T&&) [with T = unsigned int]' declared here
  106 | dynamic_marker_t<T> need_dynamic(T&& t) {
      |                     ^~~~~~~~~~~~
/builddir/build/BUILD/ceph-16.2.7/src/osd/osd_types.h: In lambda function:
/builddir/build/BUILD/ceph-16.2.7/src/common/dout.h:185:56: error: call to non-'constexpr' function 'ceph::dout::dynamic_marker_t<T> ceph::dout::need_dynamic(T&&) [with T = unsigned int]'
  185 |     dout_impl(pdpp->get_cct(), ceph::dout::need_dynamic(pdpp->get_subsys()), v) \
      |                                ~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~
/builddir/build/BUILD/ceph-16.2.7/src/common/dout.h:156:58: note: in definition of macro 'dout_impl'
  156 |       return (cctX->_conf->subsys.template should_gather<sub, v>());    \
      |                                                          ^~~
/builddir/build/BUILD/ceph-16.2.7/src/osd/osd_types.h:3610:11: note: in expansion of macro 'ldpp_dout'
 3610 |           ldpp_dout(dpp, 10) << "build_prior  prior osd." << so.osd
      |           ^~~~~~~~~
/builddir/build/BUILD/ceph-16.2.7/src/common/dout.h:106:21: note: 'ceph::dout::dynamic_marker_t<T> ceph::dout::need_dynamic(T&&) [with T = unsigned int]' declared here
  106 | dynamic_marker_t<T> need_dynamic(T&& t) {
      |                     ^~~~~~~~~~~~
/builddir/build/BUILD/ceph-16.2.7/src/osd/osd_types.h: In lambda function:
/builddir/build/BUILD/ceph-16.2.7/src/common/dout.h:185:56: error: call to non-'constexpr' function 'ceph::dout::dynamic_marker_t<T> ceph::dout::need_dynamic(T&&) [with T = unsigned int]'
  185 |     dout_impl(pdpp->get_cct(), ceph::dout::need_dynamic(pdpp->get_subsys()), v) \
      |                                ~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~
/builddir/build/BUILD/ceph-16.2.7/src/common/dout.h:156:58: note: in definition of macro 'dout_impl'
  156 |       return (cctX->_conf->subsys.template should_gather<sub, v>());    \
      |                                                          ^~~
/builddir/build/BUILD/ceph-16.2.7/src/osd/osd_types.h:3615:11: note: in expansion of macro 'ldpp_dout'
 3615 |           ldpp_dout(dpp, 10) << "build_prior  prior osd." << so.osd
      |           ^~~~~~~~~
/builddir/build/BUILD/ceph-16.2.7/src/common/dout.h:106:21: note: 'ceph::dout::dynamic_marker_t<T> ceph::dout::need_dynamic(T&&) [with T = unsigned int]' declared here
  106 | dynamic_marker_t<T> need_dynamic(T&& t) {
      |                     ^~~~~~~~~~~~
/builddir/build/BUILD/ceph-16.2.7/src/osd/osd_types.h: In lambda function:
/builddir/build/BUILD/ceph-16.2.7/src/common/dout.h:185:56: error: call to non-'constexpr' function 'ceph::dout::dynamic_marker_t<T> ceph::dout::need_dynamic(T&&) [with T = unsigned int]'
  185 |     dout_impl(pdpp->get_cct(), ceph::dout::need_dynamic(pdpp->get_subsys()), v) \
      |                                ~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~
/builddir/build/BUILD/ceph-16.2.7/src/common/dout.h:156:58: note: in definition of macro 'dout_impl'
  156 |       return (cctX->_conf->subsys.template should_gather<sub, v>());    \
      |                                                          ^~~
/builddir/build/BUILD/ceph-16.2.7/src/osd/osd_types.h:3621:11: note: in expansion of macro 'ldpp_dout'
 3621 |           ldpp_dout(dpp, 10) << "build_prior  prior osd." << so.osd
      |           ^~~~~~~~~
/builddir/build/BUILD/ceph-16.2.7/src/common/dout.h:106:21: note: 'ceph::dout::dynamic_marker_t<T> ceph::dout::need_dynamic(T&&) [with T = unsigned int]' declared here
  106 | dynamic_marker_t<T> need_dynamic(T&& t) {
      |                     ^~~~~~~~~~~~
/builddir/build/BUILD/ceph-16.2.7/src/osd/osd_types.h: In lambda function:
/builddir/build/BUILD/ceph-16.2.7/src/common/dout.h:185:56: error: call to non-'constexpr' function 'ceph::dout::dynamic_marker_t<T> ceph::dout::need_dynamic(T&&) [with T = unsigned int]'
  185 |     dout_impl(pdpp->get_cct(), ceph::dout::need_dynamic(pdpp->get_subsys()), v) \
      |                                ~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~
/builddir/build/BUILD/ceph-16.2.7/src/common/dout.h:156:58: note: in definition of macro 'dout_impl'
  156 |       return (cctX->_conf->subsys.template should_gather<sub, v>());    \
      |                                                          ^~~
/builddir/build/BUILD/ceph-16.2.7/src/osd/osd_types.h:3635:9: note: in expansion of macro 'ldpp_dout'
 3635 |         ldpp_dout(dpp, 10) << "build_prior  possibly went active+rw,"
      |         ^~~~~~~~~
/builddir/build/BUILD/ceph-16.2.7/src/common/dout.h:106:21: note: 'ceph::dout::dynamic_marker_t<T> ceph::dout::need_dynamic(T&&) [with T = unsigned int]' declared here
  106 | dynamic_marker_t<T> need_dynamic(T&& t) {
      |                     ^~~~~~~~~~~~
/builddir/build/BUILD/ceph-16.2.7/src/osd/osd_types.h: In lambda function:
/builddir/build/BUILD/ceph-16.2.7/src/common/dout.h:185:56: error: call to non-'constexpr' function 'ceph::dout::dynamic_marker_t<T> ceph::dout::need_dynamic(T&&) [with T = unsigned int]'
  185 |     dout_impl(pdpp->get_cct(), ceph::dout::need_dynamic(pdpp->get_subsys()), v) \
      |                                ~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~
/builddir/build/BUILD/ceph-16.2.7/src/common/dout.h:156:58: note: in definition of macro 'dout_impl'
  156 |       return (cctX->_conf->subsys.template should_gather<sub, v>());    \
      |                                                          ^~~
/builddir/build/BUILD/ceph-16.2.7/src/osd/osd_types.h:3645:3: note: in expansion of macro 'ldpp_dout'
 3645 |   ldpp_dout(dpp, 10) << "build_prior final: probe " << probe
      |   ^~~~~~~~~
/builddir/build/BUILD/ceph-16.2.7/src/common/dout.h:106:21: note: 'ceph::dout::dynamic_marker_t<T> ceph::dout::need_dynamic(T&&) [with T = unsigned int]' declared here
  106 | dynamic_marker_t<T> need_dynamic(T&& t) {
      |                     ^~~~~~~~~~~~

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment