Rakete1111 created this revision. Rakete1111 added a reviewer: rsmith. 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; }; ^ Repository: rC Clang https://reviews.llvm.org/D53595 Files: include/clang/Basic/DiagnosticSemaKinds.td include/clang/Sema/Sema.h lib/Sema/SemaLambda.cpp test/SemaCXX/warn-shadow-in-lambdas.cpp
Index: test/SemaCXX/warn-shadow-in-lambdas.cpp =================================================================== --- test/SemaCXX/warn-shadow-in-lambdas.cpp +++ 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}} @@ -78,8 +79,15 @@ auto f1 = [var] () { // expected-note {{variable 'var' is explicitly captured 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}} + auto f2 = [param] + (int param) { ; }; +#if __cplusplus < 201703L + // expected-note@-3{{variable 'param' is explicitly captured here}} + // expected-warning@-3{{declaration shadows a local variable}} +#else + // expected-error@-5{{a lambda parameter cannot shadow an explicitly captured entity}} + // expected-note@-7{{variable param is explicitly captured here}} +#endif } // Warn for variables defined in the capture list. @@ -134,8 +142,16 @@ auto g1 = [](auto param) { ; }; // expected-warning {{declaration shadows a local variable}} 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 g3 = [param] + (auto param) { ; }; +#if __cplusplus < 201703L + // expected-note@-3{{variable 'param' is explicitly captured here}} + // expected-warning@-3{{declaration shadows a local variable}} +#else + // expected-error@-5{{a lambda parameter cannot shadow an explicitly captured entity}} + // expected-note@-7{{variable param is explicitly captured here}} +#endif + } void avoidWarningWhenRedefining() { @@ -145,3 +161,20 @@ int b = 0; // expected-error {{redefinition of 'b'}} }; } + +void parameterShadowCapture() { +#if __cplusplus >= 201703L + int var = 1; // expected-note{{previous declaration is here}} + auto f1 = [var](int var) { return var; }; // expected-error{{a lambda parameter cannot shadow an explicitly captured entity}} + // expected-note@-1{{variable var is explicitly captured here}} + + auto f2 = [var = 1](int var) { return var; }; // expected-error{{a lambda parameter cannot shadow an explicitly captured entity}} + // expected-note@-1{{variable var is explicitly captured here}} + // expected-error@-2{{reference to 'var' is ambiguous}} + // expected-note@-3{{candidate found by name lookup is 'var'}} + // expected-note@-4{{candidate found by name lookup is 'var'}} + + auto f3 = [=](int var) { return var; }; + // expected-warning@-1{{declaration shadows a local variable}} +#endif +} Index: lib/Sema/SemaLambda.cpp =================================================================== --- lib/Sema/SemaLambda.cpp +++ lib/Sema/SemaLambda.cpp @@ -493,15 +493,30 @@ LSI->finishedExplicitCaptures(); } -void Sema::addLambdaParameters(CXXMethodDecl *CallOperator, Scope *CurScope) { +void Sema::addLambdaParameters( + const SmallVectorImpl<LambdaIntroducer::LambdaCapture> &Captures, + CXXMethodDecl *CallOperator, Scope *CurScope) { // Introduce our parameters into the function scope for (unsigned p = 0, NumParams = CallOperator->getNumParams(); p < NumParams; ++p) { ParmVarDecl *Param = CallOperator->getParamDecl(p); // If this has an identifier, add it to the scope stack. if (CurScope && Param->getIdentifier()) { - CheckShadow(CurScope, Param); + bool Error = false; + if (getLangOpts().CPlusPlus17) { + // Resolution of CWG 2211 in C++17 renders shadowing ill-formed. + for (const auto &Capture: Captures) { + if (Capture.Id && Capture.Id->getName() == Param->getName()) { + Error = true; + Diag(Param->getLocation(), diag::err_parameter_shadow_capture); + Diag(Capture.Loc, diag::note_var_explicitly_captured_here) + << Capture.Id->getName() << true; + } + } + } + if (!Error) + CheckShadow(CurScope, Param); PushOnScopeChains(Param, CurScope); } @@ -1142,7 +1157,7 @@ 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. Index: include/clang/Sema/Sema.h =================================================================== --- include/clang/Sema/Sema.h +++ include/clang/Sema/Sema.h @@ -5580,7 +5580,9 @@ void finishLambdaExplicitCaptures(sema::LambdaScopeInfo *LSI); /// Introduce the lambda parameters into scope. - void addLambdaParameters(CXXMethodDecl *CallOperator, Scope *CurScope); + void addLambdaParameters( + const SmallVectorImpl<LambdaIntroducer::LambdaCapture> &Captures, + CXXMethodDecl *CallOperator, Scope *CurScope); /// Deduce a block or lambda's return type based on the return /// statements present in the body. Index: include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- include/clang/Basic/DiagnosticSemaKinds.td +++ include/clang/Basic/DiagnosticSemaKinds.td @@ -6630,6 +6630,10 @@ def ext_star_this_lambda_capture_cxx17 : ExtWarn< "capture of '*this' by copy is a C++17 extension">, InGroup<CXX17>; + // C++17 shadow capture parameter + 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 "
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits