1 // RUN: %clang_analyze_cc1 -std=c++11 -fblocks -analyzer-checker=core,debug.ExprInspection -verify %s 2 // RUN: %clang_analyze_cc1 -std=c++11 -fblocks -analyzer-checker=core,debug.ExprInspection -DEMULATE_LIBSTDCPP -verify %s 3 4 void clang_analyzer_eval(bool); 5 6 // Faking std::std::call_once implementation. 7 namespace std { 8 9 #ifndef EMULATE_LIBSTDCPP 10 typedef struct once_flag_s { 11 unsigned long __state_ = 0; 12 } once_flag; 13 #else 14 typedef struct once_flag_s { 15 int _M_once = 0; 16 } once_flag; 17 #endif 18 19 template <class Callable, class... Args> 20 void call_once(once_flag &o, Callable&& func, Args&&... args) {}; 21 22 } // namespace std 23 24 // Check with Lambdas. 25 void test_called_warning() { 26 std::once_flag g_initialize; 27 int z; 28 29 std::call_once(g_initialize, [&] { 30 int *x = nullptr; 31 int y = *x; // expected-warning{{Dereference of null pointer (loaded from variable 'x')}} 32 z = 200; 33 }); 34 } 35 36 void test_called_on_path_inside_no_warning() { 37 std::once_flag g_initialize; 38 39 int *x = nullptr; 40 int y = 100; 41 int z; 42 43 std::call_once(g_initialize, [&] { 44 z = 200; 45 x = &z; 46 }); 47 48 *x = 100; // no-warning 49 clang_analyzer_eval(z == 100); // expected-warning{{TRUE}} 50 } 51 52 void test_called_on_path_no_warning() { 53 std::once_flag g_initialize; 54 55 int *x = nullptr; 56 int y = 100; 57 58 std::call_once(g_initialize, [&] { 59 x = &y; 60 }); 61 62 *x = 100; // no-warning 63 } 64 65 void test_called_on_path_warning() { 66 std::once_flag g_initialize; 67 68 int y = 100; 69 int *x = &y; 70 71 std::call_once(g_initialize, [&] { 72 x = nullptr; 73 }); 74 75 *x = 100; // expected-warning{{Dereference of null pointer (loaded from variable 'x')}} 76 } 77 78 void test_called_once_warning() { 79 std::once_flag g_initialize; 80 81 int *x = nullptr; 82 int y = 100; 83 84 std::call_once(g_initialize, [&] { 85 x = nullptr; 86 }); 87 88 std::call_once(g_initialize, [&] { 89 x = &y; 90 }); 91 92 *x = 100; // expected-warning{{Dereference of null pointer (loaded from variable 'x')}} 93 } 94 95 void test_called_once_no_warning() { 96 std::once_flag g_initialize; 97 98 int *x = nullptr; 99 int y = 100; 100 101 std::call_once(g_initialize, [&] { 102 x = &y; 103 }); 104 105 std::call_once(g_initialize, [&] { 106 x = nullptr; 107 }); 108 109 *x = 100; // no-warning 110 } 111 112 static int global = 0; 113 void funcPointer() { 114 global = 1; 115 } 116 117 void test_func_pointers() { 118 static std::once_flag flag; 119 std::call_once(flag, &funcPointer); 120 clang_analyzer_eval(global == 1); // expected-warning{{TRUE}} 121 } 122 123 template <class _Fp> 124 class function; // undefined 125 template <class _Rp, class... _ArgTypes> 126 struct function<_Rp(_ArgTypes...)> { 127 _Rp operator()(_ArgTypes...) const {}; 128 template <class _Fp> 129 function(_Fp) {}; 130 }; 131 132 // Note: currently we do not support calls to std::function, 133 // but the analyzer should not crash either. 134 void test_function_objects_warning() { 135 int x = 0; 136 int *y = &x; 137 138 std::once_flag flag; 139 140 function<void()> func = [&]() { 141 y = nullptr; 142 }; 143 144 std::call_once(flag, func); 145 146 func(); 147 int z = *y; 148 } 149 150 void test_param_passing_lambda() { 151 std::once_flag flag; 152 int x = 120; 153 int y = 0; 154 155 std::call_once(flag, [&](int p) { 156 y = p; 157 }, 158 x); 159 160 clang_analyzer_eval(y == 120); // expected-warning{{TRUE}} 161 } 162 163 void test_param_passing_lambda_false() { 164 std::once_flag flag; 165 int x = 120; 166 167 std::call_once(flag, [&](int p) { 168 x = 0; 169 }, 170 x); 171 172 clang_analyzer_eval(x == 120); // expected-warning{{FALSE}} 173 } 174 175 void test_param_passing_stored_lambda() { 176 std::once_flag flag; 177 int x = 120; 178 int y = 0; 179 180 auto lambda = [&](int p) { 181 y = p; 182 }; 183 184 std::call_once(flag, lambda, x); 185 clang_analyzer_eval(y == 120); // expected-warning{{TRUE}} 186 } 187 188 void test_multiparam_passing_lambda() { 189 std::once_flag flag; 190 int x = 120; 191 192 std::call_once(flag, [&](int a, int b, int c) { 193 x = a + b + c; 194 }, 195 1, 2, 3); 196 197 clang_analyzer_eval(x == 120); // expected-warning{{FALSE}} 198 clang_analyzer_eval(x == 6); // expected-warning{{TRUE}} 199 } 200 201 static int global2 = 0; 202 void test_param_passing_lambda_global() { 203 std::once_flag flag; 204 global2 = 0; 205 std::call_once(flag, [&](int a, int b, int c) { 206 global2 = a + b + c; 207 }, 208 1, 2, 3); 209 clang_analyzer_eval(global2 == 6); // expected-warning{{TRUE}} 210 } 211 212 static int global3 = 0; 213 void funcptr(int a, int b, int c) { 214 global3 = a + b + c; 215 } 216 217 void test_param_passing_funcptr() { 218 std::once_flag flag; 219 global3 = 0; 220 221 std::call_once(flag, &funcptr, 1, 2, 3); 222 223 clang_analyzer_eval(global3 == 6); // expected-warning{{TRUE}} 224 } 225 226 void test_blocks() { 227 global3 = 0; 228 std::once_flag flag; 229 std::call_once(flag, ^{ 230 global3 = 120; 231 }); 232 clang_analyzer_eval(global3 == 120); // expected-warning{{TRUE}} 233 } 234 235 int call_once() { 236 return 5; 237 } 238 239 void test_non_std_call_once() { 240 int x = call_once(); 241 clang_analyzer_eval(x == 5); // expected-warning{{TRUE}} 242 } 243 244 namespace std { 245 template <typename d, typename e> 246 void call_once(d, e); 247 } 248 void g(); 249 void test_no_segfault_on_different_impl() { 250 std::call_once(g, false); // no-warning 251 } 252 253 void test_lambda_refcapture() { 254 static std::once_flag flag; 255 int a = 6; 256 std::call_once(flag, [&](int &a) { a = 42; }, a); 257 clang_analyzer_eval(a == 42); // expected-warning{{TRUE}} 258 } 259 260 void test_lambda_refcapture2() { 261 static std::once_flag flag; 262 int a = 6; 263 std::call_once(flag, [=](int &a) { a = 42; }, a); 264 clang_analyzer_eval(a == 42); // expected-warning{{TRUE}} 265 } 266 267 void test_lambda_fail_refcapture() { 268 static std::once_flag flag; 269 int a = 6; 270 std::call_once(flag, [=](int a) { a = 42; }, a); 271 clang_analyzer_eval(a == 42); // expected-warning{{FALSE}} 272 } 273 274 void mutator(int ¶m) { 275 param = 42; 276 } 277 void test_reftypes_funcptr() { 278 static std::once_flag flag; 279 int a = 6; 280 std::call_once(flag, &mutator, a); 281 clang_analyzer_eval(a == 42); // expected-warning{{TRUE}} 282 } 283 284 void fail_mutator(int param) { 285 param = 42; 286 } 287 void test_mutator_noref() { 288 static std::once_flag flag; 289 int a = 6; 290 std::call_once(flag, &fail_mutator, a); 291 clang_analyzer_eval(a == 42); // expected-warning{{FALSE}} 292 } 293 294 // Function is implicitly treated as a function pointer 295 // even when an ampersand is not explicitly set. 296 void callbackn(int ¶m) { 297 param = 42; 298 }; 299 void test_implicit_funcptr() { 300 int x = 0; 301 static std::once_flag flagn; 302 303 std::call_once(flagn, callbackn, x); 304 clang_analyzer_eval(x == 42); // expected-warning{{TRUE}} 305 } 306