C++2a default-constructible and assignable lambdas

Salutations all – brand-new, aspiring Clang hacker here.

In spelunking through AST/DeclCXX.cpp to familiarize myself with things, I stumbled upon the implementation of CXXRecordDecl::lambdaIsDefaultConstructibleAndAssignable(). It – very conveniently – cites the C++2a draft as per new rules involving lambda default construction and assignment:

C++2a [expr.prim.lambda.capture]p11:
The closure type associated with a lambda-expression has no default
constructor if the lambda-expression has a lambda-capture and a
defaulted default constructor otherwise. It has a deleted copy
assignment operator if the lambda-expression has a lambda-capture and
defaulted copy and move assignment operators otherwise.

By my reading, if a lambda has any captures whatsoever, its default constructor and copy assignment operators are deleted. However, the implementation in clang appears to only check for the presence of capture-defaults:

if (getLambdaCaptureDefault() != LCD_None)
return false;
return getASTContext().getLangOpts().CPlusPlus2a;

In fact, the commit where this feature was introduced (864949bda1db) very explicitly only provides for lambdas with `capture-default’s. This leads the following code to be (erroneously, by my reading) accepted by clang with -std=c++2a:

void f(int i) {
auto lam1 = [i] {};
decltype(lam1) lam2;
}

while the following is (correctly) rejected:

void f(int i) {
auto lam1 = [=] {};
decltype(lam1) lam2;
}

My question is: is the current implementation 1) intentional, and 2) correct?

– logan

Yeah, your reading sounds right to me.

Richard?

The current implementation is unintentionally wrong. Thanks for catching this! Are you interested in providing a fix?

Thanks for looking this over. I’d be happy to work on a fix.