[clang] Handle __declspec() attributes in using
[llvm-project.git] / clang / test / Analysis / lambdas.mm
blobd2b8e7b3535615e7017c1e29444b9e58b04cc2c6
1 // RUN: %clang_analyze_cc1 -std=c++11 -fblocks -Wno-objc-root-class -analyzer-checker=core,deadcode,debug.ExprInspection -analyzer-config inline-lambdas=true -verify %s
3 int clang_analyzer_eval(int);
5 @interface Super
6 - (void)superMethod;
7 @end
9 @interface Sub : Super {
10   int _ivar1;
11   int _ivar2;
13 @end
15 @implementation Sub
16 - (void)callMethodOnSuperInCXXLambda; {
17   // Explicit capture.
18   [self]() {
19     [super superMethod];
20   }();
22   // Implicit capture.
23   [=]() {
24     [super superMethod];
25   }();
28 // Make sure to properly handle super-calls when a block captures
29 // a local variable named 'self'.
30 - (void)callMethodOnSuperInCXXLambdaWithRedefinedSelf; {
31   /*__weak*/ Sub *weakSelf = self;
32   // Implicit capture. (Sema outlaws explicit capture of a redefined self
33   // and a call to super [which uses the original self]).
34   [=]() {
35     Sub *self = weakSelf;
36     [=]() {
37       [super superMethod];
38     }();
39   }();
42 - (void)swapIvars {
43   int tmp = _ivar1;
44   _ivar1 = _ivar2;
45   _ivar2 = tmp;
48 - (void)callMethodOnSelfInCXXLambda; {
49   _ivar1 = 7;
50   _ivar2 = 8;
51   [self]() {
52     [self swapIvars];
53   }();
55   clang_analyzer_eval(_ivar1 == 8); // expected-warning{{TRUE}}
56   clang_analyzer_eval(_ivar2 == 7); // expected-warning{{TRUE}}
59 @end
61 int getValue();
62 void useValue(int v);
64 void castToBlockNoDeadStore() {
65   int v = getValue(); // no-warning
67   (void)(void(^)())[v]() { // This capture should count as a use, so no dead store warning above.
68   };
71 void takesBlock(void(^block)());
73 void passToFunctionTakingBlockNoDeadStore() {
74   int v = 7; // no-warning
75   int x = 8; // no-warning
76   takesBlock([&v, x]() {
77     (void)v;
78   });
81 void castToBlockAndInline() {
82   int result = ((int(^)(int))[](int p) {
83     return p;
84   })(7);
86   clang_analyzer_eval(result == 7); // expected-warning{{TRUE}}
89 void castToBlockWithCaptureAndInline() {
90   int y = 7;
92   auto lambda = [y]{ return y; };
93   int(^block)() = lambda;
95   int result = block();
96   clang_analyzer_eval(result == 7); // expected-warning{{TRUE}}
99 void castMutableLambdaToBlock() {
100   int x = 0;
102   auto lambda = [x]() mutable {
103     x = x + 1;
104     return x;
105    };
107   // The block should copy the lambda before capturing.
108   int(^block)() = lambda;
110   int r1 = block();
111   clang_analyzer_eval(r1 == 1); // expected-warning{{TRUE}}
113   int r2 = block();
114   clang_analyzer_eval(r2 == 2); // expected-warning{{TRUE}}
116   // Because block copied the lambda, r3 should be 1.
117   int r3 = lambda();
118   clang_analyzer_eval(r3 == 1); // expected-warning{{TRUE}}
120   // Aliasing the block shouldn't copy the lambda.
121   int(^blockAlias)() = block;
123   int r4 = blockAlias();
124   clang_analyzer_eval(r4 == 3); // expected-warning{{TRUE}}
126   int r5 = block();
127   clang_analyzer_eval(r5 == 4); // expected-warning{{TRUE}}
129   // Another copy of lambda
130   int(^blockSecondCopy)() = lambda;
131   int r6 = blockSecondCopy();
132   clang_analyzer_eval(r6 == 2); // expected-warning{{TRUE}}
135 void castLambdaInLocalBlock() {
136   // Make sure we don't emit a spurious diagnostic about the address of a block
137   // escaping in the implicit conversion operator method for lambda-to-block
138   // conversions.
139   auto lambda = []{ }; // no-warning
141   void(^block)() = lambda;
142   (void)block;