From 95abf86060ec7de63f59290e5fb2902839293938 Mon Sep 17 00:00:00 2001 From: Jakub Kuderski Date: Mon, 27 Mar 2023 10:28:36 -0400 Subject: [PATCH] [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 --- llvm/include/llvm/ADT/STLExtras.h | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/llvm/include/llvm/ADT/STLExtras.h b/llvm/include/llvm/ADT/STLExtras.h index d19e2f9..155d5c3 100644 --- a/llvm/include/llvm/ADT/STLExtras.h +++ b/llvm/include/llvm/ADT/STLExtras.h @@ -2311,14 +2311,21 @@ template struct enumerator_result { return Storage; } - /// Returns the value at index `I`. This includes the index. - template - 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(Result.Storage); + /// Returns the value at index `I`. This case covers the index. + template > + 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 > + friend std::tuple_element_t + 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(Result.Storage); } template -- 2.7.4