[llvm] 95abf86 - [ADT] Work around MSVC bug affecting `get(enumerator_result)`

Jakub Kuderski via llvm-commits llvm-commits at lists.llvm.org
Mon Mar 27 07:36:15 PDT 2023


Author: Jakub Kuderski
Date: 2023-03-27T10:35:09-04:00
New Revision: 95abf86060ec7de63f59290e5fb2902839293938

URL: https://github.com/llvm/llvm-project/commit/95abf86060ec7de63f59290e5fb2902839293938
DIFF: https://github.com/llvm/llvm-project/commit/95abf86060ec7de63f59290e5fb2902839293938.diff

LOG: [ADT] Work around MSVC bug affecting `get(enumerator_result)`

This happened on a small number of MSVC releases (19.31.31xxx, Visual Studio 2022 17.1.x), and worked fine on everything else.

The issue seemed to be related to return type deduction on a function with and `if constexpr`; the compiler got confused and deduced different function return type from the type of the return statement.

The workaround is to split `get` into two functions using `enable_if`.

Reviewed By: dstuttard

Differential Revision: https://reviews.llvm.org/D146893

Added: 
    

Modified: 
    llvm/include/llvm/ADT/STLExtras.h

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/ADT/STLExtras.h b/llvm/include/llvm/ADT/STLExtras.h
index d19e2f9d067e..155d5c31408a 100644
--- a/llvm/include/llvm/ADT/STLExtras.h
+++ b/llvm/include/llvm/ADT/STLExtras.h
@@ -2311,14 +2311,21 @@ template <typename... Refs> struct enumerator_result<std::size_t, Refs...> {
       return Storage;
   }
 
-  /// Returns the value at index `I`. This includes the index.
-  template <std::size_t I>
-  friend decltype(auto) get(const enumerator_result &Result) {
-    static_assert(I < NumValues, "Index out of bounds");
-    if constexpr (I == 0)
-      return Result.Idx;
-    else
-      return std::get<I - 1>(Result.Storage);
+  /// Returns the value at index `I`. This case covers the index.
+  template <std::size_t I, typename = std::enable_if_t<I == 0>>
+  friend std::size_t get(const enumerator_result &Result) {
+    return Result.Idx;
+  }
+
+  /// Returns the value at index `I`. This case covers references to the
+  /// iteratees.
+  template <std::size_t I, typename = std::enable_if_t<I != 0>>
+  friend std::tuple_element_t<I, value_reference_tuple>
+  get(const enumerator_result &Result) {
+    // Note: This is a separate function from the other `get`, instead of an
+    // `if constexpr` case, to work around an MSVC 19.31.31XXX compiler
+    // (Visual Studio 2022 17.1) return type deduction bug.
+    return std::get<I - 1>(Result.Storage);
   }
 
   template <typename... Ts>


        


More information about the llvm-commits mailing list