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