[flang] Fix template step limit issue with clang
authorJean Perier <jperier@nvidia.com>
Tue, 4 Feb 2020 18:30:16 +0000 (10:30 -0800)
committerJean Perier <jperier@nvidia.com>
Tue, 4 Feb 2020 18:30:16 +0000 (10:30 -0800)
While working on PR 959, I instanciated a `common::TupleToVariant`
with ~50+ types inside the tuple. Clang would then crash after
1hr compilation with message:
"constexpr evaluation hit maximum step limit; possible infinite loop"
After investigating, it turned out clang handles very badly the way
`common::AreTypesDistinctHelper` was implemented.
Its "number of steps" was exponential with the number of types.
This fix makes this number quadratic which solves the issue.

Original-commit: flang-compiler/f18@4542cb57082eaf578799c76482d4b706ae5da077
Reviewed-on: https://github.com/flang-compiler/f18/pull/968

flang/include/flang/common/template.h

index c8a18e7..460f1a8 100644 (file)
@@ -153,15 +153,12 @@ template<typename... Ts> struct VariantToTupleHelper<std::variant<Ts...>> {
 template<typename VARIANT>
 using VariantToTuple = typename VariantToTupleHelper<VARIANT>::type;
 
-template<typename A, typename B, typename... REST>
-struct AreTypesDistinctHelper {
+template<typename A, typename... REST> struct AreTypesDistinctHelper {
   static constexpr bool value() {
-    if constexpr (std::is_same_v<A, B>) {
-      return false;
-    }
     if constexpr (sizeof...(REST) > 0) {
-      return AreTypesDistinctHelper<A, REST...>::value() &&
-          AreTypesDistinctHelper<B, REST...>::value();
+      // extra () for clang-format
+      return ((... && !std::is_same_v<A, REST>)) &&
+          AreTypesDistinctHelper<REST...>::value();
     }
     return true;
   }