Commit Graph

11 Commits

Author SHA1 Message Date
Nathan James cb559c8d5e
[Sema] Add some basic lambda capture fix-its
Adds fix-its when users forget to explicitly capture variables or this in lambdas

Addresses https://github.com/clangd/clangd/issues/697

Reviewed By: kbobyrev

Differential Revision: https://reviews.llvm.org/D96975
2021-03-11 13:46:25 +00:00
Richard Smith 42a22370f2 Revert r350917 "[Sema] If CheckPlaceholderExpr rewrites the initializer
of an auto"

This commit changed the initializer expression passed into
initialization (stripping off an enclosing pair of parentheses or
braces) and subtly changing the meaning of programs, typically by
inserting bogus calls to copy constructors.

See the added testcase in test/SemaCXX/cxx1y-init-captures.cpp for an
example of the breakage.

llvm-svn: 359066
2019-04-24 02:22:38 +00:00
Richard Smith b3d203ff7f PR24164, PR39336: init-captures are not distinct full-expressions.
Rather, they are subexpressions of the enclosing lambda-expression, and
any temporaries in them are destroyed at the end of that
full-expression, or when the corresponding lambda-expression is
destroyed if they are lifetime-extended.

llvm-svn: 344801
2018-10-19 19:01:34 +00:00
Volodymyr Sapsai b0f1aae9b3 [Parser] Correct initalizer typos before lambda capture type is deduced.
This is the same assertion as in https://reviews.llvm.org/D25206 that is
triggered when RecordLayoutBuilder tries to compute the size of a field
(for capture "typo_boo" in the test case) whose type hasn't been
deduced.

The fix is to add CorrectDelayedTyposInExpr call to the cases when we
aren't disambiguating between an Obj-C message send and a lambda
expression.

rdar://problem/31760839

Reviewers: rsmith, ahatanak

Reviewed By: arphaman

Subscribers: cfe-commits

Differential Revision: https://reviews.llvm.org/D36853

llvm-svn: 311480
2017-08-22 17:55:19 +00:00
Manman Ren ebe8cf55ac C++14 init-capture: error out instead of crashing.
When we have template arguments, we have a function and a pattern, the variable
in init-capture belongs to the pattern decl when checking if the lhs of
"max = current" is modifiable:
  auto find = [max = init](auto current) {
    max = current;
  };

In function isReferenceToNonConstCapture, we handle the case where the decl
context for the variable is not part of the current context.

Instead of crashing, we emit an error message:
cannot assign to a variable captured by copy in a non-mutable lambda

rdar://26997922

llvm-svn: 274392
2016-07-01 22:27:16 +00:00
Richard Smith 42b1057244 N3922: direct-list-initialization of an auto-typed variable no longer deduces a
std::initializer_list<T> type. Instead, the list must contain a single element
and the type is deduced from that.

In Clang 3.7, we warned by default on all the cases that would change meaning
due to this change. In Clang 3.8, we will support only the new rules -- per
the request in N3922, this change is applied as a Defect Report against earlier
versions of the C++ standard.

This change is not entirely trivial, because for lambda init-captures we
previously did not track the difference between direct-list-initialization and
copy-list-initialization. The difference was not previously observable, because
the two forms of initialization always did the same thing (the elements of the
initializer list were always copy-initialized regardless of the initialization
style used for the init-capture).

llvm-svn: 252688
2015-11-11 01:36:17 +00:00
James Dennett dd2ffea288 Replace the broken LambdaCapture::isInitCapture API.
A LambdaCapture does not have sufficient information
to correctly determine whether it is an init-capture or not.
Doing so requires knowledge held in the LambdaExpr itself.

It the case of a nested capture of an init-capture it is not
sufficient to check (as LambdaCapture::isInitCapture did)
whether the associated VarDecl was from an init-capture.

This patch moves isInitCapture to LambdaExpr and updates
Capture->isInitCapture() to Lambda->isInitCapture(Capture).

llvm-svn: 236760
2015-05-07 18:48:18 +00:00
Faisal Vali c9c5d1604f Move a generic lambda test into the more logical test file.
llvm-svn: 196723
2013-12-08 15:11:48 +00:00
Faisal Vali 5ab61b09be Fix an assertion introduced by my previous refactoring.
Add back the test that was triggering the assertion (which I removed mistakenly thinking it was triggering just a warning and not an assertion).  My error was brought to my attention by Rafael (Thanks!).

llvm-svn: 196721
2013-12-08 15:00:29 +00:00
Faisal Vali 5fb7c3c4ed Fix init-captures for generic lambdas.
For an init capture, process the initialization expression
right away.  For lambda init-captures such as the following:
const int x = 10;
 auto L = [i = x+1](int a) {
   return [j = x+2,
          &k = x](char b) { };
 };
keep in mind that each lambda init-capture has to have:
 - its initialization expression executed in the context
   of the enclosing/parent decl-context.
 - but the variable itself has to be 'injected' into the
   decl-context of its lambda's call-operator (which has
   not yet been created).
Each init-expression is a full-expression that has to get
Sema-analyzed (for capturing etc.) before its lambda's
call-operator's decl-context, scope & scopeinfo are pushed on their
respective stacks.  Thus if any variable is odr-used in the init-capture
it will correctly get captured in the enclosing lambda, if one exists.
The init-variables above are created later once the lambdascope and
call-operators decl-context is pushed onto its respective stack.

Since the lambda init-capture's initializer expression occurs in the
context of the enclosing function or lambda, therefore we can not wait
till a lambda scope has been pushed on before deciding whether the
variable needs to be captured.  We also need to process all
lvalue-to-rvalue conversions and discarded-value conversions,
so that we can avoid capturing certain constant variables.
For e.g.,
 void test() {
  const int x = 10;
  auto L = [&z = x](char a) { <-- don't capture by the current lambda
    return [y = x](int i) { <-- don't capture by enclosing lambda
         return y;
    }
  };
If x was not const, the second use would require 'L' to capture, and
that would be an error.
Make sure TranformLambdaExpr is also aware of this.

Patch approved by Richard (Thanks!!) 
http://llvm-reviews.chandlerc.com/D2092

llvm-svn: 196454
2013-12-05 01:40:41 +00:00
Richard Smith 846f13ca14 Add extra testing for init-captures.
llvm-svn: 191608
2013-09-28 05:23:21 +00:00