Sfinae regression in cling when switching from gcc49 to gcc62

For some magic with sfinae I have the header below in my software package. When moving from x86_64-slc6-gcc49-opt to x86_64-centos7-gcc62-opt, the build fails (in dictionary generation with genreflex) with

Info in <TUnixSystem::ACLiC>: creating shared library /somelongpath/./c++14_compat_h.so
In file included from input_line_12:9:
/somelongpath/./c++14_compat.h:52:36: error: 
      type alias template redefinition with different types ('typename make_void<Ts...>::type' vs 'void')
    template<typename... Ts> using void_t = typename make_void<Ts...>::type;
                                   ^
/cvmfs/sft.cern.ch/lcg/contrib/gcc/6.2.0native/x86_64-centos7/bin/../lib/gcc/x86_64-pc-linux-gnu/6.2.0/../../../../include/c++/6.2.0/type_traits:2536:31: note: 
      previous definition is here
  template<typename...> using void_t = void;
                              ^
Error in <ACLiC>: Dictionary generation failed!

Trying to make the error easier to reproduce (and understand where it comes from) I arrived at the following reproducer:

SHELL > # do something to set up root
SHELL > root -n -b
root [0] .L c++14_compat.h++

And tried this using the root installations on /afs/cern.ch/sw/lcg/app/releases/ROOT/, /cvmfs/sft.cern.ch/lcg/views/LCG_88, /cvmfs/sft.cern.ch/lcg/views/dev, and trying gcc49 vs 62, and trying a centos7 machine and lxplus(slc6), i believe this is a regression when going from the gcc 4.9 builds to gcc 6.2.

Comments / thoughts?

header for reproduction:

/** @file c++14_compat.h
 *
 * @brief some required constructs from C++ 14 implemented using C++ 11
 */

#ifndef CPP14_COMPAT_H
#define CPP14_COMPAT_H

#if __cplusplus > 201103L // well, g++ and icpc have strange values here in c++14 mode
// C++14 - use the standard's facilities
#include <utility>
#elif __cplusplus >= 201103L
// C++11 - implement what's needed
// C++14 Compile-time integer sequences -- this can go once we use C++14...
namespace std {
    template<size_t... indexes>
    struct index_sequence {
        static constexpr size_t size() { return sizeof...(indexes); }
    };

    template<size_t currentIndex, size_t... indexes>
    struct make_index_sequence_helper;

    template<size_t...indexes>
    struct make_index_sequence_helper<0, indexes...> {
        typedef index_sequence<indexes...> type;
    };

    template<size_t currentIndex, size_t... indexes>
    struct make_index_sequence_helper {
        typedef typename make_index_sequence_helper<currentIndex - 1,
                currentIndex - 1, indexes...>::type type;
    };

    template<size_t N>
    struct make_index_sequence : public make_index_sequence_helper<N>::type
    { };
}
#else // __cplusplus
// not even C++11 support
#error "Your C++ compiler must support at least C++11."
#endif // __cplusplus

// FIXME: what is the defined value of compliant C++17 compilers?
#if __cplusplus > 201402L
#include <type_traits>
#else
namespace std {
    /// little helper for the SFINAE idiom we'll use (not required in C++17)
    template<typename... Ts> struct make_void { typedef void type;};
    /// little helper for the SFINAE idiom we'll use (not required in C++17)
    template<typename... Ts> using void_t = typename make_void<Ts...>::type;
}
#endif // __cplusplus

#endif // CPP14_COMPAT_H
1 Like

Isn’t the LCG build with gcc 6 using c++14? Wouldn’t that compat header cause havoc then? I think that’s what you are seeing… I’m surprised that compat header had no protection from c++14…

Yes, this should be c++14. cling also says:

root [0] std::cout << __cplusplus <<std::endl;
201402

but I claim the header is valid c++14. It then reduces to

#ifndef CPP14_COMPAT_H
#define CPP14_COMPAT_H

// C++14 branch
#include <utility>

// not c++17 branch
namespace std {
    /// little helper for the SFINAE idiom we'll use (not required in C++17)
    template<typename... Ts> struct make_void { typedef void type;};
    /// little helper for the SFINAE idiom we'll use (not required in C++17)
    template<typename... Ts> using void_t = typename make_void<Ts...>::type;
}

#endif // CPP14_COMPAT_H

and when handing this to the lcg 88 g++:

SHELL > source /cvmfs/sft.cern.ch/lcg/views/LCG_88/x86_64-centos7-gcc62-opt/setup.sh
SHELL > g++ --version
g++ (GCC) 6.2.0
SHELL > which g++
/cvmfs/sft.cern.ch/lcg/contrib/gcc/6.2/x86_64-centos7/bin/g++
SHELL > g++ -std=c++14 c++14_compat.h -c -o foobar.o -Wall -Wextra
SHELL ># no errors, no warnings

Adding static_assert(__STRICT_ANSI__, ""); to the top of your header shows the difference:
gcc parses it; rootcling says ./pseyfert.h:9:15: error: use of undeclared identifier '__STRICT_ANSI__'

$ echo | clang++ -x c++ -std=c++14 -E -dM -  | grep STRICT_ANSI
#define __STRICT_ANSI__ 1
$ echo | g++ -x c++ -std=c++14 -E -dM -  | grep STRICT_ANSI
#define __STRICT_ANSI__ 1

We’re simply missing this in rootcling, because we don’t initialize cling with “-std=…” (which would set it) but deduce the language standard from the build. I need to think :slight_smile:

Axel.

Hi Paul!

I pushed a commit that should fix this. I’ll check tomorrow on the nightlies for that platform.

Do you need this in 6.08?

Axel.

Cool,
for what i need it for, would be great to have it in the next lcg. if it’s “only” in 6.08 but doesn’t make it to lcg it won’t help much. (and i have to admit my ignorance about how/when/which root releases end up in lcg).

It’s now in v6-08-00-patches. I cannot yet tell whether the next LCG will be based on v6-08-… or v6-10-… But now you have it either way :slight_smile:

2 Likes

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.