This is an archive of the discontinued LLVM Phabricator instance.

Allow use of lambda expressions in array bounds
Needs ReviewPublic

Authored by ahatanak on Jun 9 2016, 10:21 AM.
This revision needs review, but there are no reviewers specified.

Details

Reviewers
None
Summary

clang currently errors out when a lambda expression is used to compute the size of an array even though clang supports variable-length arrays as a C99 extension. For example,

$ cat vla1.cpp

int foo3();

struct S1 {
  virtual ~S1();
};

struct S2 : S1 {
};

void foo(S1 *s1) {
  unsigned char a1[([](int a) {return a; })(1)];
  unsigned char a2[foo3()]; // This is OK.
  unsigned char a3[!dynamic_cast<S2 *>(s1) + 1];  // This is OK.
}

$ clang++ vla1.cpp -c -std=c++11
vla1.cpp:11:21: error: a lambda expression may not appear inside of a constant expression

unsigned char a1[([](int a) {return a; })(1)];
                  ^

1 error generated.

To handle VLAs in a more consistent way, this patch makes changes to allow lambda expressions to be used for array bounds if it is in a BlockContext.

Diff Detail

Event Timeline

ahatanak updated this revision to Diff 60193.Jun 9 2016, 10:21 AM
ahatanak retitled this revision from to Allow use of lambda expressions in array bounds.
ahatanak updated this object.
ahatanak added a subscriber: cfe-commits.
rsmith added a subscriber: rsmith.Jun 9 2016, 1:37 PM
rsmith added inline comments.
lib/Sema/SemaExpr.cpp
12825

This isn't correct; you still need to produce the diagnostic even if we're in an array bound, but it should be an ExtWarn controlled by -Wvla. A case like

void f() {
  int arr[ true ? 1 : []{return 0}() ];
}

is ill-formed in standard C++, but as we can evaluate the array bound as a constant, Clang will no longer diagnose it with this change in place.

12834–12839

If you accept lambdas inside VLA bounds, you need to do this step for them.

12848–12853

This also looks wrong for your lambda-in-VLA-bound case.

Perhaps the best thing to do is to check whether we have a VLA *before* we pop the ExpressionEvaluationContextRecord, and if so, convert the context from ConstantEvaluated to Evaluated.

Sorry for my late reply.

lib/Sema/SemaExpr.cpp
12825

Is this ill-formed too in standard c++?

int a[true ? 2 : !dynamic_cast<S2*>(s1) + 1];

clang doesn't warn or error out when compiling the expression above.

12848–12853

It seems like we won't be able to warn about lambdas in constant expressions at all if we change the context before popping ExpressionEvaluationContextRecord, so there would be no warnings for your example code (ternary expression used for array bound). Is that your intention?