Bug 40641

Summary: gcc10 fails to build code using "constexpr" on ppc64le
Product: Sisyphus Reporter: Николай Костригин <nickel>
Component: gccAssignee: Egor Ignatov <egori>
Status: ASSIGNED --- QA Contact: qa-sisyphus
Severity: normal    
Priority: P5 CC: egori, glebfm, ilyakurdyukov, ldv, mike
Version: unstable   
Hardware: ppc   
OS: Linux   
Attachments:
Description Flags
build MySQL-8.0.26-alt1 with gcc 10.3.1-alt2 on ppc64le log none

Description Николай Костригин 2021-08-03 11:38:59 MSK
Created attachment 9551 [details]
build MySQL-8.0.26-alt1 with gcc 10.3.1-alt2 on ppc64le log

rpmi: gcc10-c++-10.3.1-alt2 sisyphus+277353.100.2.1 1625527709 installed


[00:08:06] /usr/src/RPM/BUILD/MySQL-8.0.26/unittest/gunit/innodb/ut0new-t.cc:58:63: error: '(2.00416836000897277799610805135016e-292l + 1.0e+0l)' is not a constant expression
[00:08:06]    58 |   static constexpr T INIT_VAL = std::numeric_limits<T>::min() + 1;
[00:08:06]       |                                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~
[00:08:06] gmake[2]: *** [unittest/gunit/innodb/CMakeFiles/merge_innodb_tests-t.dir/build.make:233: unittest/gunit/innodb/CMakeFiles/merge_innodb_tests-t.dir/ut0new-t.cc.o] Error 1

More details in the attached build log file and in task #281108
Comment 1 ilyakurdyukov 2021-08-04 09:08:08 MSK
Попробуйте так:

template <class T>
struct wrapper {
 public:
  static constexpr T INIT_VAL = std::numeric_limits<T>::min() + 1;
  wrapper(T data = INIT_VAL) : data(data) {}
  T data;
};

template <>
struct wrapper<long double> {
 public:
  static constexpr long double INIT_VAL = 1;
  wrapper(long double data = INIT_VAL) : data(data) {}
  long double data;
};

Для float типов должна получаться просто единица. Так что попробуйте добавить таких специализированных темплейтов.
Comment 2 Egor Ignatov 2021-08-04 09:25:53 MSK
(In reply to ilyakurdyukov from comment #1)
> Для float типов должна получаться просто единица.
Почему это для float типов должна быть единица?


Тут проблема в том, что ppc испобльзует ibmlongdouble. С флагом -mabi=ieeelongdouble данный код компилируется, но возникают другие ошибки при сборке MySQL.

Я думаю проще будет отключить этот тест для ppc:

#if defined(__powerpc__) || defined(__ppc__) || defined(__ppc64__)
using floating_point_types = ::testing::Types<float, double>;
#else
using floating_point_types = ::testing::Types<float, double, long double>;
#endif

see also: https://bugzilla.redhat.com/show_bug.cgi?id=1538817
Comment 3 Egor Ignatov 2021-08-04 09:27:44 MSK
(In reply to Egor Ignatov from comment #2)
> (In reply to ilyakurdyukov from comment #1)
> > Для float типов должна получаться просто единица.
> Почему это для float типов должна быть единица?

Понял почему :)
Comment 4 Egor Ignatov 2021-08-04 09:43:41 MSK
(In reply to ilyakurdyukov from comment #1)
> Попробуйте так:
> 
> template <class T>
> struct wrapper {
>  public:
>   static constexpr T INIT_VAL = std::numeric_limits<T>::min() + 1;
>   wrapper(T data = INIT_VAL) : data(data) {}
>   T data;
> };
>
#if defined(__powerpc__) || defined(__ppc__) || defined(__ppc64__)
> template <>
> struct wrapper<long double> {
>  public:
>   static constexpr long double INIT_VAL = 1;
>   wrapper(long double data = INIT_VAL) : data(data) {}
>   long double data;
> };
#endif

Хотя такое решение возможно будет лучше, сейчас пробую.
Comment 5 Egor Ignatov 2021-08-04 09:54:22 MSK
> Попробуйте так:
> 
> template <class T>
> struct wrapper {
>  public:
>   static constexpr T INIT_VAL = std::numeric_limits<T>::min() + 1;
>   wrapper(T data = INIT_VAL) : data(data) {}
>   T data;
> };
> 
> template <>
> struct wrapper<long double> {
>  public:
>   static constexpr long double INIT_VAL = 1;
>   wrapper(long double data = INIT_VAL) : data(data) {}
>   long double data;
> };

ld: CMakeFiles/merge_innodb_tests-t.dir/ut0new-t.cc.o:(.toc+0x108): undefined reference to `innodb_ut0new_unittest::wrapper<__float128>::INIT_VAL'
Comment 6 ilyakurdyukov 2021-08-04 10:03:16 MSK
Возможно так нужно добавить:

template <class T>
struct wrapper {
 public:
  static constexpr T INIT_VAL = std::numeric_limits<T>::min() + 1;
  wrapper(T data = INIT_VAL) : data(data) {}
  T data;
};

template <class T>
constexpr T wrapper<T>::INIT_VAL;

#if defined(__powerpc__) || defined(__ppc__) || defined(__ppc64__)

template <>
struct wrapper<long double> {
 public:
  static constexpr long double INIT_VAL = 1;
  wrapper(long double data = INIT_VAL) : data(data) {}
  long double data;
};

constexpr long double wrapper<long double>::INIT_VAL;

#endif
Comment 7 Egor Ignatov 2021-08-04 10:23:54 MSK
(In reply to ilyakurdyukov from comment #6)
> Возможно так нужно добавить:
> 
> template <class T>
> struct wrapper {
>  public:
>   static constexpr T INIT_VAL = std::numeric_limits<T>::min() + 1;
>   wrapper(T data = INIT_VAL) : data(data) {}
>   T data;
> };
> 
> template <class T>
> constexpr T wrapper<T>::INIT_VAL;
> 
> #if defined(__powerpc__) || defined(__ppc__) || defined(__ppc64__)
> 
> template <>
> struct wrapper<long double> {
>  public:
>   static constexpr long double INIT_VAL = 1;
>   wrapper(long double data = INIT_VAL) : data(data) {}
>   long double data;
> };
> 
> constexpr long double wrapper<long double>::INIT_VAL;
> 
> #endif

Все собралось, спасибо!