273 lines · cpp
1// RUN: %clang_cc1 -std=c++14 -verify=expected,cxx14 -fsyntax-only -Wshadow -D AVOID %s2// RUN: %clang_cc1 -std=c++14 -verify=expected,cxx14 -fsyntax-only -Wshadow -Wshadow-uncaptured-local %s3// RUN: %clang_cc1 -std=c++14 -verify=expected,cxx14 -fsyntax-only -Wshadow-all %s4// RUN: %clang_cc1 -std=c++17 -verify -fsyntax-only -Wshadow-all %s5// RUN: %clang_cc1 -std=c++20 -verify -fsyntax-only -Wshadow-all %s6 7void foo(int param) { // expected-note 1+ {{previous declaration is here}}8 int var = 0; // expected-note 1+ {{previous declaration is here}}9 10 // Avoid warnings for variables that aren't implicitly captured.11 {12#ifdef AVOID13 auto f1 = [=] { int var = 1; }; // no warning14 auto f2 = [&] { int var = 2; }; // no warning15 auto f3 = [=] (int param) { ; }; // no warning16 auto f4 = [&] (int param) { ; }; // no warning17 auto f5 = [=] { static int var = 1; }; // no warning18 auto f6 = [&] { static int var = 2; }; // no warning19#else20 auto f1 = [=] { int var = 1; }; // expected-warning {{declaration shadows a local variable}}21 auto f2 = [&] { int var = 2; }; // expected-warning {{declaration shadows a local variable}}22 auto f3 = [=] (int param) { ; }; // expected-warning {{declaration shadows a local variable}}23 auto f4 = [&] (int param) { ; }; // expected-warning {{declaration shadows a local variable}}24 auto f5 = [=] { static int var = 1; }; // expected-warning {{declaration shadows a local variable}}25 auto f6 = [&] { static int var = 2; }; // expected-warning {{declaration shadows a local variable}}26#endif27 }28 29 // Warn for variables that are implicitly captured.30 {31 auto f1 = [=] () {32 {33 int var = 1; // expected-warning {{declaration shadows a local variable}}34 }35 int x = var; // expected-note {{variable 'var' is captured here}}36 };37 auto f2 = [&]38#ifdef AVOID39 (int param) {40#else41 (int param) { // expected-warning {{declaration shadows a local variable}}42#endif43 int x = var; // expected-note {{variable 'var' is captured here}}44 int var = param; // expected-warning {{declaration shadows a local variable}}45 };46 }47 48 // Warn for variables that are explicitly captured when a lambda has a default49 // capture specifier.50 {51 auto f1 = [=, &var] () { // expected-note {{variable 'var' is captured here}}52 int x = param; // expected-note {{variable 'param' is captured here}}53 int var = 0; // expected-warning {{declaration shadows a local variable}}54 int param = 0; // expected-warning {{declaration shadows a local variable}}55 };56 }57 58 // Warn normally inside of lambdas.59 auto l1 = [] { // expected-note {{previous declaration is here}}60 int x = 1; // expected-note {{previous declaration is here}}61 { int x = 2; } // expected-warning {{declaration shadows a local variable}}62 };63 auto l2 = [] (int x) { // expected-note {{previous declaration is here}}64 { int x = 1; } // expected-warning {{declaration shadows a local variable}}65 };66 67 // Avoid warnings for variables that aren't explicitly captured.68 {69#ifdef AVOID70 auto f1 = [] { int var = 1; }; // no warning71 auto f2 = [] (int param) { ; }; // no warning72 auto f3 = [param] () { int var = 1; }; // no warning73 auto f4 = [var] (int param) { ; }; // no warning74 auto f5 = [param] () { static int var = 1; }; // no warning75 auto f6 = [] { static int var = 1; }; // no warning76#else77 auto f1 = [] { int var = 1; }; // expected-warning {{declaration shadows a local variable}}78 auto f2 = [] (int param) { ; }; // expected-warning {{declaration shadows a local variable}}79 auto f3 = [param] () { int var = 1; }; // expected-warning {{declaration shadows a local variable}}80 auto f4 = [var] (int param) { ; }; // expected-warning {{declaration shadows a local variable}}81 auto f5 = [param] () { static int var = 1; }; // expected-warning {{declaration shadows a local variable}}82 auto f6 = [] { static int var = 1; }; // expected-warning {{declaration shadows a local variable}}83#endif84 };85 86 // Warn for variables that are explicitly captured.87 {88 auto f1 = [var] () { // expected-note {{variable 'var' is explicitly captured here}}89 int var = 1; // expected-warning {{declaration shadows a local variable}}90 };91 auto f2 = [param] // expected-note {{variable 'param' is explicitly captured here}}92 (int param) { ; }; // expected-error {{a lambda parameter cannot shadow an explicitly captured entity}}93 }94 95 // Warn for variables defined in the capture list.96 auto l3 = [z = var] { // expected-note {{previous declaration is here}}97#ifdef AVOID98 int var = 1; // no warning99#else100 int var = 1; // expected-warning {{declaration shadows a local variable}}101#endif102 { int z = 1; } // expected-warning {{declaration shadows a local variable}}103 };104#ifdef AVOID105 auto l4 = [var = param] (int param) { ; }; // no warning106#else107 auto l4 = [var = param](int param) { ; }; // expected-warning 2{{declaration shadows a local variable}}108#endif109 110 // Make sure that inner lambdas work as well.111 auto l5 = [var, l1] { // expected-note {{variable 'l1' is explicitly captured here}}112 auto l1 = [] { // expected-warning {{declaration shadows a local variable}}113#ifdef AVOID114 int var = 1; // no warning115#else116 int var = 1; // expected-warning {{declaration shadows a local variable}}117#endif118 };119#ifdef AVOID120 auto f1 = [] { int var = 1; }; // no warning121 auto f2 = [=] { int var = 1; }; // no warning122#else123 auto f1 = [] { int var = 1; }; // expected-warning {{declaration shadows a local variable}}124 auto f2 = [=] { int var = 1; }; // expected-warning {{declaration shadows a local variable}}125#endif126 auto f3 = [var] // expected-note {{variable 'var' is explicitly captured here}}127 { int var = 1; }; // expected-warning {{declaration shadows a local variable}}128 auto f4 = [&] {129 int x = var; // expected-note {{variable 'var' is captured here}}130 int var = 2; // expected-warning {{declaration shadows a local variable}}131 };132 };133 auto l6 = [&] {134 auto f1 = [param] { // expected-note {{variable 'param' is explicitly captured here}}135 int param = 0; // expected-warning {{declaration shadows a local variable}}136 };137 };138 auto l7 = [&] {139 auto f1 = [param] { // expected-note {{variable 'param' is explicitly captured here}}140 static int param = 0; // expected-warning {{declaration shadows a local variable}}141 };142 };143 144 // Generic lambda arguments should work.145#ifdef AVOID146 auto g1 = [](auto param) { ; }; // no warning147 auto g2 = [=](auto param) { ; }; // no warning148#else149 auto g1 = [](auto param) { ; }; // expected-warning {{declaration shadows a local variable}}150 auto g2 = [=](auto param) { ; }; // expected-warning {{declaration shadows a local variable}}151#endif152 auto g3 = [param] // expected-note {{variable 'param' is explicitly captured here}}153 (auto param) { ; }; // expected-error {{a lambda parameter cannot shadow an explicitly captured entity}}154}155 156void avoidWarningWhenRedefining() {157 int a = 1;158 auto l = [b = a] { // expected-note {{previous definition is here}}159 // Don't warn on redefinitions.160 int b = 0; // expected-error {{redefinition of 'b'}}161 };162}163 164namespace GH61105 {165void f() {166 int y = 0;167 int x = 0;168#if __cplusplus >= 202002L169 auto l1 = [y]<typename y>(y) { return 0; }; // expected-error {{declaration of 'y' shadows template parameter}} \170 // expected-note {{template parameter is declared here}}171 auto l2 = [=]<typename y>() { int a = y; return 0; }; // expected-error {{'y' does not refer to a value}} \172 // expected-note {{declared here}}173 auto l3 = [&, y]<typename y, typename>(y) { int a = x; return 0; }; // expected-error {{declaration of 'y' shadows template parameter}} \174 // expected-note {{template parameter is declared here}}175 auto l4 = [x, y]<typename y, int x>() { return 0; }; // expected-error {{declaration of 'y' shadows template parameter}} \176 // expected-error {{declaration of 'x' shadows template parameter}} \177 // expected-note 2{{template parameter is declared here}}178 auto l5 = []<typename y>(y) { return 0; }; // No diagnostic179#endif180}181}182 183namespace GH71976 {184#ifdef AVOID185struct A {186 int b = 5;187 int foo() {188 return [b = b]() { return b; }(); // no -Wshadow diagnostic, init-capture does not shadow b due to not capturing this189 }190};191 192struct B {193 int a;194 void foo() {195 auto b = [a = this->a] {}; // no -Wshadow diagnostic, init-capture does not shadow a due to not capturing his196 }197};198 199struct C {200 int b = 5;201 int foo() {202 return [a = b]() {203 return [=, b = a]() { // no -Wshadow diagnostic, init-capture does not shadow b due to outer lambda204 return b;205 }();206 }();207 }208};209 210#else211struct A {212 int b = 5; // expected-note {{previous}}213 int foo() {214 return [b = b]() { return b; }(); // expected-warning {{declaration shadows a field}}215 }216};217 218struct B {219 int a; // expected-note {{previous}}220 void foo() {221 auto b = [a = this->a] {}; // expected-warning {{declaration shadows a field}}222 }223};224 225struct C {226 int b = 5; // expected-note {{previous}}227 int foo() {228 return [a = b]() {229 return [=, b = a]() { // expected-warning {{declaration shadows a field}}230 return b;231 }();232 }();233 }234};235 236struct D {237 int b = 5; // expected-note {{previous}}238 int foo() {239 return [b = b, this]() { return b; }(); // expected-warning {{declaration shadows a field}}240 }241};242 243struct E {244 int b = 5;245 int foo() {246 return [a = b]() { // expected-note {{previous}}247 return [=, a = a]() { // expected-warning {{shadows a local}}248 return a;249 }();250 }();251 }252};253 254#endif255 256struct S {257 int a ;258};259 260int foo() {261#ifdef AVOID262 auto [a] = S{0}; // cxx14-warning {{structured binding declarations are a C++17 extension}}263 [a = a] () { // No warning with basic -Wshadow due to uncaptured-local classification264 }();265#else266 auto [a] = S{0}; // cxx14-warning {{structured binding declarations are a C++17 extension}} expected-note {{previous declaration is here}}267 [a = a] () { // expected-warning {{declaration shadows a structured binding}}268 }();269#endif270}271 272}273