llvm / llvm-project

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.
http://llvm.org
Other
27.84k stars 11.47k forks source link

lambda expression is not a constant expression when auto (generic) parameter is used. #35052

Open llvmbot opened 6 years ago

llvmbot commented 6 years ago
Bugzilla Link 35704
Version trunk
OS Windows NT
Attachments sample cpp file
Reporter LLVM Bugzilla Contributor

Extended Description

When constexpr lambda used in constant expression it going non constant when its parameter is auto.

In this sample got an error:

1> ConsoleApplication1.cpp(20,16): error : constexpr if condition is not a constant expression 1> if constexpr (f(TypeTag::value)) 1> ^~~~~~~~

But if

auto predicate = [](auto v) constexpr -> bool

replaced by

auto predicate = [](size_t v) constexpr -> bool

all ok.


include

template struct TypeTag { constexpr static size_t value = 1; };

template<> struct TypeTag { constexpr static size_t value = 2; };

template<typename T, typename F> constexpr auto func(F f) { if constexpr (f(TypeTag::value)) { return int{1}; } else { return float{2.2f}; } }

int main() { auto predicate = [](auto v) constexpr -> bool // does not compile when v is auto { return v == 1; };

constexpr auto ok = predicate(75);

constexpr auto fail = func<int>(predicate);

return 0;

}

wheatman commented 10 months ago

This is still being rejected with post 17 trunk(cf7d4f543c73c2707e0c53bae1e7b8419e12b871) https://godbolt.org/z/rGvqfjYTP

I have simplified the code a bit.

The code will compile fine if either the argument type of the lambda is specified, or the return type of the lambda is not specified.

code

// compile with -std=c++17 
template<typename F>
constexpr int func(F f)
{
    if constexpr (f(1UL)) {
        return 1;
    }
    return 0;
}

int main()
{
    auto predicate = [](auto v) constexpr -> bool   // does not compile when v is auto and the return type is specified
    {
        return v == 1;
    };

    return func(predicate);
}

error

<source>:5:16: error: constexpr if condition is not a constant expression
    5 |         if constexpr (f(1UL)) {
      |                       ^~~~~~
<source>:19:9: note: in instantiation of function template specialization 'func<(lambda at <source>:14:19)>' requested here
   19 |         return func(predicate);
      |                ^
<source>:5:16: note: undefined function 'operator()<unsigned long>' cannot be used in a constant expression
    5 |         if constexpr (f(1UL)) {
      |                       ^
<source>:14:19: note: declared here
   14 |         auto predicate = [](auto v) constexpr -> bool   // does not compile when v is auto and the return type is specified
      |                          ^
1 error generated.
Compiler returned: 1
llvmbot commented 10 months ago

@llvm/issue-subscribers-clang-frontend

Author: None (llvmbot)

| | | | --- | --- | | Bugzilla Link | [35704](https://llvm.org/bz35704) | | Version | trunk | | OS | Windows NT | | Attachments | [sample cpp file](https://user-images.githubusercontent.com/60944935/143756747-1ebddae5-0c33-4886-ae99-12a8f1d0fed6.gz) | | Reporter | LLVM Bugzilla Contributor | ## Extended Description When constexpr lambda used in constant expression it going non constant when its parameter is auto. In this sample got an error: 1> ConsoleApplication1.cpp(20,16): error : constexpr if condition is not a constant expression 1> if constexpr (f(TypeTag<T>::value)) 1> ^~~~~~~~~~~~~~~~~~~~ But if auto predicate = [](auto v) constexpr -> bool replaced by auto predicate = [](*size_t* v) constexpr -> bool all ok. ---------------------------------------------- #include <iostream> template<typename T> struct TypeTag { constexpr static size_t value = 1; }; template<> struct TypeTag<float> { constexpr static size_t value = 2; }; template<typename T, typename F> constexpr auto func(F f) { if constexpr (f(TypeTag<T>::value)) { return int{1}; } else { return float{2.2f}; } } int main() { auto predicate = [](auto v) constexpr -> bool // does not compile when v is auto { return v == 1; }; constexpr auto ok = predicate(75); constexpr auto fail = func<int>(predicate); return 0; }
shafik commented 9 months ago

I wonder if this is related to: https://github.com/llvm/llvm-project/issues/71015

zyn0217 commented 1 month ago

Reopen it as the PR has been reverted in https://github.com/llvm/llvm-project/pull/98991.