Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

decltype for lambda capture gives wrong type #37673

Closed
apolukhin opened this issue Jul 26, 2018 · 2 comments
Closed

decltype for lambda capture gives wrong type #37673

apolukhin opened this issue Jul 26, 2018 · 2 comments
Labels
bugzilla Issues migrated from bugzilla clang:frontend Language frontend issues, e.g. anything involving "Sema" invalid Resolved as invalid, i.e. not a bug

Comments

@apolukhin
Copy link
Member

Bugzilla Link 38325
Version trunk
OS Linux
CC @apolukhin,@dwblaikie,@egorpugin,@zygoloid

Extended Description

According to my reading of the http://eel.is/c++draft/expr.prim.id.unqual#2 the following code should compile:

#include <type_traits>
#include

constexpr std::true_type is_const(int const &) { return {}; }
constexpr std::false_type is_const(int &) { return {}; }

int main() {
int x = 0;
[y = x, x] {
const int z = 0;
assert(is_const(x)); // OK
assert(is_const(y)); // OK
assert(is_const(z)); // OK

static_assert(!decltype(is_const(x))::value, "");
static_assert(decltype(is_const(y))::value, ""); // Fails (OK on GCC)
static_assert(decltype(is_const(z))::value, "");

static_assert(!std::is_const<decltype(x)>::value, "");
static_assert(std::is_const<decltype(y)>::value, ""); // Fails (OK on GCC)
static_assert(std::is_const<decltype(z)>::value, "");

} ();
}

However, two lines marked with "Fails (OK on GCC)" do not pass the asserts.

@zygoloid
Copy link
Mannequin

zygoloid mannequin commented Jul 26, 2018

I don't agree. Per [expr.prim.id.unqual]p2, the type of 'x' or 'y' within the lambda is the type of a class member access expression naming the corresponding capture. Those members are of type (non-const) int, but the lambda's *this parameter is const-qualified, so the correct behavior would be:

static_assert(decltype(is_const(x))::value, "");
static_assert(decltype(is_const(y))::value, "");
static_assert(decltype(is_const(z))::value, "");

static_assert(!std::is_const<decltype(x)>::value, "");
static_assert(!std::is_const<decltype(y)>::value, "");
static_assert(std::is_const<decltype(z)>::value, "");

decltype(x) is decltype((lambda).x), which is the type of the member, which is int.
decltype(is_const(x)) doesn't match the special case decltype(id-expression) pattern, so it gives the type of the expression, which doesn't care whether 'x' occurs in an unevaluated operand.

Now, this changed in P0588R1, which clang does not yet implement. Prior to that, the lambda transformation was not applied in unevaluated operands, meaning that 'x' and 'y' were both non-const inside the decltype, and Clang's current behavior is correct in that model.

Note in particular that [y = x] behaves as if a variable

auto y = x;

is declared outside the lambda and then captured (see [expr.prim.lambda.capture]p6), so any difference in behavior between the x and y cases is a bug (in GCC in this case).

We can certainly keep this open to track the fact that clang doesn't implement P0588R1 yet, but that's already tracked on the cxx_status page (or it would be, if our website ever updated to match svn).

@llvmbot llvmbot transferred this issue from llvm/llvm-bugzilla-archive Dec 10, 2021
@cor3ntin cor3ntin added the invalid Resolved as invalid, i.e. not a bug label Aug 30, 2023
@cor3ntin
Copy link
Contributor

Per Richard's comment not a bug, and we already track P0588 in multiple places

@Endilll Endilll closed this as not planned Won't fix, can't repro, duplicate, stale Aug 30, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bugzilla Issues migrated from bugzilla clang:frontend Language frontend issues, e.g. anything involving "Sema" invalid Resolved as invalid, i.e. not a bug
Projects
None yet
Development

No branches or pull requests

3 participants