Clang Project

clang_source_code/test/SemaCXX/warn-shadow-in-lambdas.cpp
1// RUN: %clang_cc1 -std=c++14 -verify -fsyntax-only -Wshadow -D AVOID %s
2// RUN: %clang_cc1 -std=c++14 -verify -fsyntax-only -Wshadow -Wshadow-uncaptured-local %s
3// RUN: %clang_cc1 -std=c++14 -verify -fsyntax-only -Wshadow-all %s
4// RUN: %clang_cc1 -std=c++17 -verify -fsyntax-only -Wshadow-all %s
5
6void foo(int param) { // expected-note 1+ {{previous declaration is here}}
7  int var = 0; // expected-note 1+ {{previous declaration is here}}
8
9  // Avoid warnings for variables that aren't implicitly captured.
10  {
11#ifdef AVOID
12    auto f1 = [=] { int var = 1; };  // no warning
13    auto f2 = [&] { int var = 2; };  // no warning
14    auto f3 = [=] (int param) { ; }; // no warning
15    auto f4 = [&] (int param) { ; }; // no warning
16#else
17    auto f1 = [=] { int var = 1; };  // expected-warning {{declaration shadows a local variable}}
18    auto f2 = [&] { int var = 2; };  // expected-warning {{declaration shadows a local variable}}
19    auto f3 = [=] (int param) { ; }; // expected-warning {{declaration shadows a local variable}}
20    auto f4 = [&] (int param) { ; }; // expected-warning {{declaration shadows a local variable}}
21#endif
22  }
23
24  // Warn for variables that are implicitly captured.
25  {
26    auto f1 = [=] () {
27      {
28        int var = 1; // expected-warning {{declaration shadows a local variable}}
29      }
30      int x = var; // expected-note {{variable 'var' is captured here}}
31    };
32    auto f2 = [&]
33#ifdef AVOID
34      (int param) {
35#else
36      (int param) { // expected-warning {{declaration shadows a local variable}}
37#endif
38      int x = var; // expected-note {{variable 'var' is captured here}}
39      int var = param; // expected-warning {{declaration shadows a local variable}}
40    };
41  }
42
43  // Warn for variables that are explicitly captured when a lambda has a default
44  // capture specifier.
45  {
46    auto f1 = [=, &var] () { // expected-note {{variable 'var' is captured here}}
47      int x = param; // expected-note {{variable 'param' is captured here}}
48      int var = 0; // expected-warning {{declaration shadows a local variable}}
49      int param = 0; // expected-warning {{declaration shadows a local variable}}
50    };
51  }
52
53  // Warn normally inside of lambdas.
54  auto l1 = [] { // expected-note {{previous declaration is here}}
55      int x = 1; // expected-note {{previous declaration is here}}
56      { int x = 2; } // expected-warning {{declaration shadows a local variable}}
57  };
58  auto l2 = [] (int x) { // expected-note {{previous declaration is here}}
59    { int x = 1; } // expected-warning {{declaration shadows a local variable}}
60  };
61
62  // Avoid warnings for variables that aren't explicitly captured.
63  {
64#ifdef AVOID
65    auto f1 = [] { int var = 1; }; // no warning
66    auto f2 = [] (int param) { ; }; // no warning
67    auto f3 = [param] () { int var = 1; }; // no warning
68    auto f4 = [var] (int param) { ; }; // no warning
69#else
70    auto f1 = [] { int var = 1; }; // expected-warning {{declaration shadows a local variable}}
71    auto f2 = [] (int param) { ; }; // expected-warning {{declaration shadows a local variable}}
72    auto f3 = [param] () { int var = 1; }; // expected-warning {{declaration shadows a local variable}}
73    auto f4 = [var] (int param) { ; }; // expected-warning {{declaration shadows a local variable}}
74#endif
75  };
76
77  // Warn for variables that are explicitly captured.
78  {
79    auto f1 = [var] () { // expected-note {{variable 'var' is explicitly captured here}}
80      int var = 1; // expected-warning {{declaration shadows a local variable}}
81    };
82    auto f2 = [param]   // expected-note {{variable 'param' is explicitly captured here}}
83     (int param) { ; }; // expected-error {{a lambda parameter cannot shadow an explicitly captured entity}}
84  }
85
86  // Warn for variables defined in the capture list.
87  auto l3 = [z = var] { // expected-note {{previous declaration is here}}
88#ifdef AVOID
89    int var = 1; // no warning
90#else
91    int var = 1; // expected-warning {{declaration shadows a local variable}}
92#endif
93    { int z = 1; } // expected-warning {{declaration shadows a local variable}}
94  };
95#ifdef AVOID
96  auto l4 = [var = param] (int param) { ; }; // no warning
97#else
98  auto l4 = [var = param] (int param) { ; }; // expected-warning {{declaration shadows a local variable}}
99#endif
100
101  // Make sure that inner lambdas work as well.
102  auto l5 = [var, l1] { // expected-note {{variable 'l1' is explicitly captured here}}
103    auto l1 = [] { // expected-warning {{declaration shadows a local variable}}
104#ifdef AVOID
105      int var = 1; // no warning
106#else
107      int var = 1; // expected-warning {{declaration shadows a local variable}}
108#endif
109    };
110#ifdef AVOID
111    auto f1 = [] { int var = 1; }; // no warning
112    auto f2 = [=] { int var = 1; }; // no warning
113#else
114    auto f1 = [] { int var = 1; }; // expected-warning {{declaration shadows a local variable}}
115    auto f2 = [=] { int var = 1; }; // expected-warning {{declaration shadows a local variable}}
116#endif
117    auto f3 = [var] // expected-note {{variable 'var' is explicitly captured here}}
118      { int var = 1; }; // expected-warning {{declaration shadows a local variable}}
119    auto f4 = [&] {
120      int x = var; // expected-note {{variable 'var' is captured here}}
121      int var = 2; // expected-warning {{declaration shadows a local variable}}
122    };
123  };
124  auto l6 = [&] {
125    auto f1 = [param] { // expected-note {{variable 'param' is explicitly captured here}}
126      int param = 0; // expected-warning {{declaration shadows a local variable}}
127    };
128  };
129
130  // Generic lambda arguments should work.
131#ifdef AVOID
132  auto g1 = [](auto param) { ; }; // no warning
133  auto g2 = [=](auto param) { ; }; // no warning
134#else
135  auto g1 = [](auto param) { ; }; // expected-warning {{declaration shadows a local variable}}
136  auto g2 = [=](auto param) { ; }; // expected-warning {{declaration shadows a local variable}}
137#endif
138  auto g3 = [param] // expected-note {{variable 'param' is explicitly captured here}}
139   (auto param) { ; }; // expected-error {{a lambda parameter cannot shadow an explicitly captured entity}}
140}
141
142void avoidWarningWhenRedefining() {
143  int a = 1;
144  auto l = [b = a] { // expected-note {{previous definition is here}}
145    // Don't warn on redefinitions.
146    int b = 0; // expected-error {{redefinition of 'b'}}
147  };
148}
149