diff options
author | Nicolas Lesser <blitzrakete@gmail.com> | 2018-10-25 20:15:03 +0000 |
---|---|---|
committer | Nicolas Lesser <blitzrakete@gmail.com> | 2018-10-25 20:15:03 +0000 |
commit | 5897428cd24e2deefbcc6f6744c0d7d233aa6747 (patch) | |
tree | 6e50d61fb9d487a5c6bfa3a2d1aaca299c97bcd0 | |
parent | e2c6f9622e58d1cf15204ef6cf26cc3a1c7d50c5 (diff) |
[C++17] Reject shadowing of capture by parameter in lambda
Summary:
This change rejects the shadowing of a capture by a parameter in lambdas in C++17.
```
int main() {
int a;
auto f = [a](int a) { return a; };
}
```
results in:
```
main.cpp:3:20: error: a lambda parameter cannot shadow an explicitly captured entity
auto f = [a](int a) { return a; };
^
main.cpp:3:13: note: variable a is explicitly captured here
auto f = [a](int a) { return a; };
^
```
Reviewers: rsmith
Reviewed By: rsmith
Subscribers: lebedev.ri, erik.pilkington, cfe-commits
Differential Revision: https://reviews.llvm.org/D53595
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@345308 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/clang/Basic/DiagnosticSemaKinds.td | 4 | ||||
-rw-r--r-- | include/clang/Sema/Sema.h | 4 | ||||
-rw-r--r-- | lib/Sema/SemaLambda.cpp | 20 | ||||
-rw-r--r-- | test/CXX/drs/dr22xx.cpp | 11 | ||||
-rw-r--r-- | test/SemaCXX/warn-shadow-in-lambdas.cpp | 5 | ||||
-rwxr-xr-x | www/cxx_dr_status.html | 2 |
6 files changed, 39 insertions, 7 deletions
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index aeaff242f7..2b899f2be1 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -6630,6 +6630,10 @@ let CategoryName = "Lambda Issue" in { def ext_star_this_lambda_capture_cxx17 : ExtWarn< "capture of '*this' by copy is a C++17 extension">, InGroup<CXX17>; + // C++17 parameter shadows capture + def err_parameter_shadow_capture : Error< + "a lambda parameter cannot shadow an explicitly captured entity">; + // C++2a [=, this] captures. def warn_cxx17_compat_equals_this_lambda_capture : Warning< "explicit capture of 'this' with a capture default of '=' is incompatible " diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index f0c024e9a1..430a851d25 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -5580,7 +5580,9 @@ public: void finishLambdaExplicitCaptures(sema::LambdaScopeInfo *LSI); /// Introduce the lambda parameters into scope. - void addLambdaParameters(CXXMethodDecl *CallOperator, Scope *CurScope); + void addLambdaParameters( + ArrayRef<LambdaIntroducer::LambdaCapture> Captures, + CXXMethodDecl *CallOperator, Scope *CurScope); /// Deduce a block or lambda's return type based on the return /// statements present in the body. diff --git a/lib/Sema/SemaLambda.cpp b/lib/Sema/SemaLambda.cpp index 803b253e45..aa60ce113d 100644 --- a/lib/Sema/SemaLambda.cpp +++ b/lib/Sema/SemaLambda.cpp @@ -493,7 +493,9 @@ void Sema::finishLambdaExplicitCaptures(LambdaScopeInfo *LSI) { LSI->finishedExplicitCaptures(); } -void Sema::addLambdaParameters(CXXMethodDecl *CallOperator, Scope *CurScope) { +void Sema::addLambdaParameters( + ArrayRef<LambdaIntroducer::LambdaCapture> Captures, + CXXMethodDecl *CallOperator, Scope *CurScope) { // Introduce our parameters into the function scope for (unsigned p = 0, NumParams = CallOperator->getNumParams(); p < NumParams; ++p) { @@ -501,7 +503,19 @@ void Sema::addLambdaParameters(CXXMethodDecl *CallOperator, Scope *CurScope) { // If this has an identifier, add it to the scope stack. if (CurScope && Param->getIdentifier()) { - CheckShadow(CurScope, Param); + bool Error = false; + // Resolution of CWG 2211 in C++17 renders shadowing ill-formed, but we + // retroactively apply it. + for (const auto &Capture : Captures) { + if (Capture.Id == Param->getIdentifier()) { + Error = true; + Diag(Param->getLocation(), diag::err_parameter_shadow_capture); + Diag(Capture.Loc, diag::note_var_explicitly_captured_here) + << Capture.Id << true; + } + } + if (!Error) + CheckShadow(CurScope, Param); PushOnScopeChains(Param, CurScope); } @@ -1142,7 +1156,7 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro, LSI->ContainsUnexpandedParameterPack = ContainsUnexpandedParameterPack; // Add lambda parameters into scope. - addLambdaParameters(Method, CurScope); + addLambdaParameters(Intro.Captures, Method, CurScope); // Enter a new evaluation context to insulate the lambda from any // cleanups from the enclosing full-expression. diff --git a/test/CXX/drs/dr22xx.cpp b/test/CXX/drs/dr22xx.cpp index 021707d876..70a26db757 100644 --- a/test/CXX/drs/dr22xx.cpp +++ b/test/CXX/drs/dr22xx.cpp @@ -15,3 +15,14 @@ struct AnonBitfieldQualifiers { const volatile unsigned i3 : 1; }; } + +#if __cplusplus >= 201103L +namespace dr2211 { // dr2211: 8 +void f() { + int a; + auto f = [a](int a) { (void)a; }; // expected-error {{a lambda parameter cannot shadow an explicitly captured entity}} + // expected-note@-1{{variable 'a' is explicitly captured here}} + auto g = [=](int a) { (void)a; }; +} +} +#endif diff --git a/test/SemaCXX/warn-shadow-in-lambdas.cpp b/test/SemaCXX/warn-shadow-in-lambdas.cpp index b0dcd122a5..a772af049a 100644 --- a/test/SemaCXX/warn-shadow-in-lambdas.cpp +++ b/test/SemaCXX/warn-shadow-in-lambdas.cpp @@ -1,6 +1,7 @@ // RUN: %clang_cc1 -std=c++14 -verify -fsyntax-only -Wshadow -D AVOID %s // RUN: %clang_cc1 -std=c++14 -verify -fsyntax-only -Wshadow -Wshadow-uncaptured-local %s // RUN: %clang_cc1 -std=c++14 -verify -fsyntax-only -Wshadow-all %s +// RUN: %clang_cc1 -std=c++17 -verify -fsyntax-only -Wshadow-all %s void foo(int param) { // expected-note 1+ {{previous declaration is here}} int var = 0; // expected-note 1+ {{previous declaration is here}} @@ -79,7 +80,7 @@ void foo(int param) { // expected-note 1+ {{previous declaration is here}} int var = 1; // expected-warning {{declaration shadows a local variable}} }; auto f2 = [param] // expected-note {{variable 'param' is explicitly captured here}} - (int param) { ; }; // expected-warning {{declaration shadows a local variable}} + (int param) { ; }; // expected-error {{a lambda parameter cannot shadow an explicitly captured entity}} } // Warn for variables defined in the capture list. @@ -135,7 +136,7 @@ void foo(int param) { // expected-note 1+ {{previous declaration is here}} auto g2 = [=](auto param) { ; }; // expected-warning {{declaration shadows a local variable}} #endif auto g3 = [param] // expected-note {{variable 'param' is explicitly captured here}} - (auto param) { ; }; // expected-warning {{declaration shadows a local variable}} + (auto param) { ; }; // expected-error {{a lambda parameter cannot shadow an explicitly captured entity}} } void avoidWarningWhenRedefining() { diff --git a/www/cxx_dr_status.html b/www/cxx_dr_status.html index 44fdf8f17f..460978260f 100755 --- a/www/cxx_dr_status.html +++ b/www/cxx_dr_status.html @@ -13081,7 +13081,7 @@ and <I>POD class</I></td> <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2211">2211</a></td> <td>C++17</td> <td>Hiding by lambda captures and parameters</td> - <td class="none" align="center">Unknown</td> + <td class="svn" align="center">SVN</td> </tr> <tr class="open" id="2212"> <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2212">2212</a></td> |