<table border="1" cellspacing="0" cellpadding="8">
    <tr>
        <th>Issue</th>
        <td>
            <a href=https://github.com/llvm/llvm-project/issues/58872>58872</a>
        </td>
    </tr>

    <tr>
        <th>Summary</th>
        <td>
            Incorrect `if constexpr` evaluation in nested generic lambda with explicit template parameters
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
      </td>
    </tr>

    <tr>
      <th>Assignees</th>
      <td>
      </td>
    </tr>

    <tr>
      <th>Reporter</th>
      <td>
          cschreib
      </td>
    </tr>
</table>

<pre>
    The test code below does not compile (in C++20 mode) with any version of clang I could test in Compiler Explorer (up to and including clang 15):
```c++
#include <type_traits>

// Generic type holder, for types that cannot be instanciated.
template<typename T>
struct type_holder {};

// Generic type to create a function with a given signature.
template<typename T>
struct foo;

template<typename R, typename ... Args>
struct foo<R(Args...)> {
    static R bar(Args...) {}
};

// Offending code.
template<typename T, typename ... IArgs>
auto test(IArgs... inputs) {
    [&]<typename R, typename... Args>(type_holder<R(Args...)>, Args... values) {
        // This always works.
        foo<T>::bar(values...);

        // This does not always work.
        if constexpr (std::is_same_v<R, void>) {
            if constexpr (sizeof...(Args) > 0) {
                foo<T>::bar(values...);
            } else {
                foo<T>::bar();
            }
        } else {
            int return_value = 0;
            if constexpr (sizeof...(Args) > 0) {
                return_value = foo<T>::bar(values...);
            } else {
                return_value = foo<T>::bar();
            }
        }
    }(type_holder<T>{}, inputs...);
}

int main() {
    // <source>:35:32: error: assigning to 'int' from incompatible type 'void'
    //                 return_value = foo<T>::bar();
    //                                ^~~~~~~~~~~~~
    test<void()>();

    //<source>:28:29: error: too few arguments to function call, expected 1, have 0
    //                foo<T>::bar();
    //                ~~~~~~~~~~~ ^
    test<void(int)>(1);

    // works!
    test<int()>();

    //<source>:28:29: error: too few arguments to function call, expected 1, have 0
    //                foo<T>::bar();
    //                ~~~~~~~~~~~ ^
    test<int(int)>(1);

    return 0;
}
```

Test cases:
 1. As you can see from the errors reported, `test<void()>()` generates an error inside an `if constexpr` branch that should not be entered. `std::is_same_v<R, void>` should be true, but it took (or at least, also tried to compile) the false branch.  
 2. Similar story with `test<void(int)>(1)`. There it took the correct branch for the return type, but then took the wrong branch for the arguments. `sizeof...(Args) > 0` should be true, but it took (or at least, also tried to compile) the false branch.
 3. `test<int()>()` works fine, for some reason (it is the case that corresponds to the `else` branch for all `if constexpr` checks).
 4. `test<int(int)>(1)` fails again and takes the wrong branch for the return value and the arguments.

Extra information:
 - The code compiles if using `foo<R(Args...)>` instead of `foo<T>`, which should be equivalent. Weirdly enough, as this seems orthogonal to the `if constexpr` issue.
 - The code always failed to compile with clang since generic lambda with explicit template parameters were added (clang 9 with `-std=c++2a`).
 - The code compiles with GCC 8 (`-std=c++2a`) and above.
 - The code compiles with MSVC 19.30 and above.
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJztWE1z4jgQ_TXmohqXMQHMgUOGZKZy2NqqmdTuMSXbAmtHWKwkw2R__b6WbGLAJJPamdtSlINtdev1608l1-Xz8rESzAnrWKFLwXKh9IGVWlhWa3q23UklWJRmsmarKP2Ib5qwLdZG6YIdpKsYr5_ZXhgrdc30mhWK1xv2ANlGlUE1yQZNht1_3ylt8AM6mx1zGvIlVhSqKSUEg_h4CvXR5DZK7qLkNpol4VsEBO3TdBLEgG-ycs878eQMl85Gk_t2RbvuE77ss6iFkQWjhazSqhQmSldsrY1_ZJmrOCzmNRmeC0CyjteF5E6UcdDkxHancN9uV_OtYI_H3awzTeG8sqegn0Xzj9H8Lpp8fAsPaCiMgGrG2bqpC0dkBnbZRu5Fzazc1Nw1RrwHy1rrs82HxL4QD8e7OI7ZrdnYQV0rrM3oLVZ5D917G_06hg8oc7DpC8u5OVnZURGgXOPk9_Va1CEMEGGvWnoO-eEEM2_AKMUeQDy0KODRXYPoaMEcMUdTxNQsmt5d5aRPSZr1HDxECAl2O-65asTljn7XYPFjJS3j6sCfLTto883Gp8sC696xyIbJbeA16O22PGFySP8xn3sbne0jkbgaES--73xqWleGDaV9sqDgaR9sXbG9lqU3c8CoQU3yH6HXHqsnygsibpKrGt5pd18MkcWEsuK9il_Rd0brqxvI2jEjkKX1k4cKQ-9g6JDmn0PTxWa_jLcf3Ok9RPZSEDfnieU1h6KBqAu5ex7xx4Lir8T-lss6wDhL8pAO0Gt1YwoRYE-mdElxYcIYbegHt1RqqQahhETpHFpxZWujt9Sm0MdQ4nI0RV-48conRDq_2OsnMXhF29knmoKsH_ge1friOFkF8FlXurLhghIwnJGHxbgsTshzWrO1ODBuNs1W1M4SiceGVnClyJmIeVGgrbIx3VV8LxDmbxj8X8h6kxZP3xVqvP9bdsav0RPqd5SOLzR5Ff9zPMBxYOYHKA7J06ulL7nfDYd9kUc_0XKL5tsNkWyMJm7Zs25oyGNWiJDTDgOw59Zik5024IwYg8JXUmSWsA3NbxhL0L7roIBGRolpFPdY0C_wtD43mCarMGXayg_H7aQJHwqDIZOk3u67UNWKQxSjmaCXeYMp21FofKNmAizYRQlOA9AKbd9iGjIS0UCDZhjFqUSS7WtOdT-gi-HHQFYas69yKxU3mOm0eQ7D6AUpF56bJTFmDphzhEN7FNoYRGPHgZ-58bh1KhXSzgg8rl_kDkajDp9JHeM-EHa1b_5SolqaJnGPk4E0BwZfFdha1qI7bli9Jdu5RboSh0BkA00I2PYYQoTZna5Ln930ErqoQ_dCiXQh24eCrahEQbVo0QG9uQQ64DvYKBUCeoMu6s9ljn8T9rorWgeGlubXn_inn5H333E4Q4ZAdMupUr0k5geKmHD-bCm3NB41lpowUF05eRBeOqQJXtK587jwMbwjtg-VBNqXKBB_NxJgAS5mfwppSvWM7NPNpvLeJ0vhCpSGrWWoBJXe6JqrngfOeZbWNt05pW9HO2gTnSexFNIonHFhXiFCGcGRSfFtXvLwHtqVLChM26MP23GDYoAygeGdkouXJfSCkaBqcUzPD76A3LUH5ZR7IhYDCI9Me8nPqxXLSN9VFd69PNf7IXNPlf329Y8VGy_iSdITGonleDabZ4v5IstG5XJSLiYLPnLSKbF8qLsKMcCxoPDyIUP_SKgRwjD9vbSNGqOWlXM73xB8B9tApsljYMeNUvvuz4ed0X8BC269e5FGn6ZZNk9H1ZInQqSzIsmKm7yczbJpMsnSIlvzUuSzPJ2OFM-RpUs6U07vRnKZJmk6HidZkk0XN_N4PbspsnzGCzGfzmfZIrpJBEZWFdPGsTabkVl6DHmDUnaTKGmRR8eXYTYVotOPY26lzbKwRWWEzEce79KD_Re41SZZ">