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