415 lines · cpp
1// RUN: %clang_analyze_cc1 -std=c++11 -fblocks -analyzer-checker=core,debug.ExprInspection -verify %s -o %t.report2// RUN: %clang_analyze_cc1 -std=c++11 -fblocks -analyzer-checker=core,debug.ExprInspection -DEMULATE_LIBSTDCPP -verify %s -o %t.report3 4// We do NOT model libcxx03 implementation, but the analyzer should still5// not crash.6// RUN: %clang_analyze_cc1 -std=c++11 -fblocks -analyzer-checker=core,debug.ExprInspection -DEMULATE_LIBCXX03 -verify %s -o %t.report7// RUN: %clang_analyze_cc1 -std=c++11 -fblocks -analyzer-checker=core,debug.ExprInspection -DEMULATE_LIBCXX03 -DEMULATE_LIBSTDCPP -verify %s -o %t.report8// RUN: rm -rf %t.report9 10void clang_analyzer_eval(bool);11 12// Faking std::call_once implementation.13namespace std {14 15// Fake std::function implementation.16template <typename>17class function;18class function_base {19 public:20 long field;21};22template <typename R, typename... P>23class function<R(P...)> : function_base {24 public:25 R operator()(P...) const {26 27 // Read from a super-class necessary to reproduce a crash.28 bool a = field;29 }30};31 32#ifndef EMULATE_LIBSTDCPP33typedef struct once_flag_s {34 unsigned long __state_ = 0;35} once_flag;36#else37typedef struct once_flag_s {38 int _M_once = 0;39} once_flag;40#endif41 42#ifndef EMULATE_LIBCXX0343template <class Callable, class... Args>44void call_once(once_flag &o, Callable&& func, Args&&... args) {};45#else46template <class Callable, class... Args> // libcxx03 call_once47void call_once(once_flag &o, Callable func, Args&&... args) {};48#endif49 50} // namespace std51 52// Check with Lambdas.53void test_called_warning() {54 std::once_flag g_initialize;55 int z;56 57 std::call_once(g_initialize, [&] {58 int *x = nullptr;59#ifndef EMULATE_LIBCXX0360 int y = *x; // expected-warning{{Dereference of null pointer (loaded from variable 'x')}}61#endif62 z = 200;63 });64}65 66void test_called_on_path_inside_no_warning() {67 std::once_flag g_initialize;68 69 int *x = nullptr;70 int y = 100;71 int z;72 73 std::call_once(g_initialize, [&] {74 z = 200;75 x = &z;76 });77 78#ifndef EMULATE_LIBCXX0379 *x = 100; // no-warning80 clang_analyzer_eval(z == 100); // expected-warning{{TRUE}}81#endif82}83 84void test_called_on_path_no_warning() {85 std::once_flag g_initialize;86 87 int *x = nullptr;88 int y = 100;89 90 std::call_once(g_initialize, [&] {91 x = &y;92 });93 94#ifndef EMULATE_LIBCXX0395 *x = 100; // no-warning96#else97 *x = 100; // expected-warning{{Dereference of null pointer (loaded from variable 'x')}}98#endif99}100 101void test_called_on_path_warning() {102 std::once_flag g_initialize;103 104 int y = 100;105 int *x = &y;106 107 std::call_once(g_initialize, [&] {108 x = nullptr;109 });110 111#ifndef EMULATE_LIBCXX03112 *x = 100; // expected-warning{{Dereference of null pointer (loaded from variable 'x')}}113#endif114}115 116void test_called_once_warning() {117 std::once_flag g_initialize;118 119 int *x = nullptr;120 int y = 100;121 122 std::call_once(g_initialize, [&] {123 x = nullptr;124 });125 126 std::call_once(g_initialize, [&] {127 x = &y;128 });129 130#ifndef EMULATE_LIBCXX03131 *x = 100; // expected-warning{{Dereference of null pointer (loaded from variable 'x')}}132#endif133}134 135void test_called_once_no_warning() {136 std::once_flag g_initialize;137 138 int *x = nullptr;139 int y = 100;140 141 std::call_once(g_initialize, [&] {142 x = &y;143 });144 145 std::call_once(g_initialize, [&] {146 x = nullptr;147 });148 149#ifndef EMULATE_LIBCXX03150 *x = 100; // no-warning151#endif152}153 154static int global = 0;155void funcPointer() {156 global = 1;157}158 159void test_func_pointers() {160 static std::once_flag flag;161 std::call_once(flag, &funcPointer);162#ifndef EMULATE_LIBCXX03163 clang_analyzer_eval(global == 1); // expected-warning{{TRUE}}164#endif165}166 167template <class _Fp>168class function; // undefined169template <class _Rp, class... _ArgTypes>170struct function<_Rp(_ArgTypes...)> {171 _Rp operator()(_ArgTypes...) const {};172 template <class _Fp>173 function(_Fp) {};174};175 176// Note: currently we do not support calls to std::function,177// but the analyzer should not crash either.178void test_function_objects_warning() {179 int x = 0;180 int *y = &x;181 182 std::once_flag flag;183 184 function<void()> func = [&]() {185 y = nullptr;186 };187 188 std::call_once(flag, func);189 190 func();191 int z = *y;192}193 194void test_param_passing_lambda() {195 std::once_flag flag;196 int x = 120;197 int y = 0;198 199 std::call_once(flag, [&](int p) {200 y = p;201 },202 x);203 204#ifndef EMULATE_LIBCXX03205 clang_analyzer_eval(y == 120); // expected-warning{{TRUE}}206#endif207}208 209void test_param_passing_lambda_false() {210 std::once_flag flag;211 int x = 120;212 213 std::call_once(flag, [&](int p) {214 x = 0;215 },216 x);217 218#ifndef EMULATE_LIBCXX03219 clang_analyzer_eval(x == 120); // expected-warning{{FALSE}}220#endif221}222 223void test_param_passing_stored_lambda() {224 std::once_flag flag;225 int x = 120;226 int y = 0;227 228 auto lambda = [&](int p) {229 y = p;230 };231 232 std::call_once(flag, lambda, x);233#ifndef EMULATE_LIBCXX03234 clang_analyzer_eval(y == 120); // expected-warning{{TRUE}}235#endif236}237 238void test_multiparam_passing_lambda() {239 std::once_flag flag;240 int x = 120;241 242 std::call_once(flag, [&](int a, int b, int c) {243 x = a + b + c;244 },245 1, 2, 3);246 247#ifndef EMULATE_LIBCXX03248 clang_analyzer_eval(x == 120); // expected-warning{{FALSE}}249 clang_analyzer_eval(x == 6); // expected-warning{{TRUE}}250#endif251}252 253static int global2 = 0;254void test_param_passing_lambda_global() {255 std::once_flag flag;256 global2 = 0;257 std::call_once(flag, [&](int a, int b, int c) {258 global2 = a + b + c;259 },260 1, 2, 3);261#ifndef EMULATE_LIBCXX03262 clang_analyzer_eval(global2 == 6); // expected-warning{{TRUE}}263#endif264}265 266static int global3 = 0;267void funcptr(int a, int b, int c) {268 global3 = a + b + c;269}270 271void test_param_passing_funcptr() {272 std::once_flag flag;273 global3 = 0;274 275 std::call_once(flag, &funcptr, 1, 2, 3);276 277#ifndef EMULATE_LIBCXX03278 clang_analyzer_eval(global3 == 6); // expected-warning{{TRUE}}279#endif280}281 282void test_blocks() {283 global3 = 0;284 std::once_flag flag;285 std::call_once(flag, ^{286 global3 = 120;287 });288#ifndef EMULATE_LIBCXX03289 clang_analyzer_eval(global3 == 120); // expected-warning{{TRUE}}290#endif291}292 293int call_once() {294 return 5;295}296 297void test_non_std_call_once() {298 int x = call_once();299#ifndef EMULATE_LIBCXX03300 clang_analyzer_eval(x == 5); // expected-warning{{TRUE}}301#endif302}303 304namespace std {305template <typename d, typename e>306void call_once(d, e);307}308void g();309void test_no_segfault_on_different_impl() {310#ifndef EMULATE_LIBCXX03311 std::call_once(g, false); // no-warning312#endif313}314 315void test_lambda_refcapture() {316 static std::once_flag flag;317 int a = 6;318 std::call_once(flag, [&](int &a) { a = 42; }, a);319#ifndef EMULATE_LIBCXX03320 clang_analyzer_eval(a == 42); // expected-warning{{TRUE}}321#endif322}323 324void test_lambda_refcapture2() {325 static std::once_flag flag;326 int a = 6;327 std::call_once(flag, [=](int &a) { a = 42; }, a);328#ifndef EMULATE_LIBCXX03329 clang_analyzer_eval(a == 42); // expected-warning{{TRUE}}330#endif331}332 333void test_lambda_fail_refcapture() {334 static std::once_flag flag;335 int a = 6;336 std::call_once(flag, [=](int a) { a = 42; }, a);337#ifndef EMULATE_LIBCXX03338 clang_analyzer_eval(a == 42); // expected-warning{{FALSE}}339#endif340}341 342void mutator(int ¶m) {343 param = 42;344}345void test_reftypes_funcptr() {346 static std::once_flag flag;347 int a = 6;348 std::call_once(flag, &mutator, a);349#ifndef EMULATE_LIBCXX03350 clang_analyzer_eval(a == 42); // expected-warning{{TRUE}}351#endif352}353 354void fail_mutator(int param) {355 param = 42;356}357void test_mutator_noref() {358 static std::once_flag flag;359 int a = 6;360 std::call_once(flag, &fail_mutator, a);361#ifndef EMULATE_LIBCXX03362 clang_analyzer_eval(a == 42); // expected-warning{{FALSE}}363#endif364}365 366// Function is implicitly treated as a function pointer367// even when an ampersand is not explicitly set.368void callbackn(int ¶m) {369 param = 42;370}371void test_implicit_funcptr() {372 int x = 0;373 static std::once_flag flagn;374 375 std::call_once(flagn, callbackn, x);376#ifndef EMULATE_LIBCXX03377 clang_analyzer_eval(x == 42); // expected-warning{{TRUE}}378#endif379}380 381int param_passed(int *x) {382 return *x; // no-warning, as std::function is not working yet.383}384 385void callback_taking_func_ok(std::function<void(int*)> &innerCallback) {386 innerCallback(nullptr);387}388 389// The provided callback expects an std::function, but instead a pointer390// to a C++ function is provided.391void callback_with_implicit_cast_ok() {392 std::once_flag flag;393 call_once(flag, callback_taking_func_ok, ¶m_passed);394}395 396void callback_taking_func(std::function<void()> &innerCallback) {397 innerCallback();398}399 400// The provided callback expects an std::function, but instead a C function401// name is provided, and C++ implicitly auto-constructs a pointer from it.402void callback_with_implicit_cast() {403 std::once_flag flag;404 call_once(flag, callback_taking_func, callback_with_implicit_cast);405}406 407std::once_flag another_once_flag;408typedef void (*my_callback_t)(int *);409my_callback_t callback;410int global_int;411 412void rdar40270582() {413 call_once(another_once_flag, callback, &global_int);414}415