summaryrefslogtreecommitdiff
path: root/test/Analysis/call_once.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'test/Analysis/call_once.cpp')
-rw-r--r--test/Analysis/call_once.cpp63
1 files changed, 58 insertions, 5 deletions
diff --git a/test/Analysis/call_once.cpp b/test/Analysis/call_once.cpp
index db9e5cc7ca164..344de80907875 100644
--- a/test/Analysis/call_once.cpp
+++ b/test/Analysis/call_once.cpp
@@ -1,16 +1,34 @@
-// RUN: %clang_analyze_cc1 -std=c++11 -fblocks -analyzer-checker=core,debug.ExprInspection -verify %s
-// RUN: %clang_analyze_cc1 -std=c++11 -fblocks -analyzer-checker=core,debug.ExprInspection -DEMULATE_LIBSTDCPP -verify %s
+// RUN: %clang_analyze_cc1 -std=c++11 -fblocks -analyzer-checker=core,debug.ExprInspection -verify %s -o %t.report
+// RUN: %clang_analyze_cc1 -std=c++11 -fblocks -analyzer-checker=core,debug.ExprInspection -DEMULATE_LIBSTDCPP -verify %s -o %t.report
// We do NOT model libcxx03 implementation, but the analyzer should still
// not crash.
-// RUN: %clang_analyze_cc1 -std=c++11 -fblocks -analyzer-checker=core,debug.ExprInspection -DEMULATE_LIBCXX03 -verify %s
-// RUN: %clang_analyze_cc1 -std=c++11 -fblocks -analyzer-checker=core,debug.ExprInspection -DEMULATE_LIBCXX03 -DEMULATE_LIBSTDCPP -verify %s
+// RUN: %clang_analyze_cc1 -std=c++11 -fblocks -analyzer-checker=core,debug.ExprInspection -DEMULATE_LIBCXX03 -verify %s -o %t.report
+// RUN: %clang_analyze_cc1 -std=c++11 -fblocks -analyzer-checker=core,debug.ExprInspection -DEMULATE_LIBCXX03 -DEMULATE_LIBSTDCPP -verify %s -o %t.report
+// RUN: rm -rf %t.report
void clang_analyzer_eval(bool);
-// Faking std::std::call_once implementation.
+// Faking std::call_once implementation.
namespace std {
+// Fake std::function implementation.
+template <typename>
+class function;
+class function_base {
+ public:
+ long field;
+};
+template <typename R, typename... P>
+class function<R(P...)> : function_base {
+ public:
+ R operator()(P...) const {
+
+ // Read from a super-class necessary to reproduce a crash.
+ bool a = field;
+ }
+};
+
#ifndef EMULATE_LIBSTDCPP
typedef struct once_flag_s {
unsigned long __state_ = 0;
@@ -359,3 +377,38 @@ void test_implicit_funcptr() {
clang_analyzer_eval(x == 42); // expected-warning{{TRUE}}
#endif
}
+
+int param_passed(int *x) {
+ return *x; // no-warning, as std::function is not working yet.
+}
+
+void callback_taking_func_ok(std::function<void(int*)> &innerCallback) {
+ innerCallback(nullptr);
+}
+
+// The provided callback expects an std::function, but instead a pointer
+// to a C++ function is provided.
+void callback_with_implicit_cast_ok() {
+ std::once_flag flag;
+ call_once(flag, callback_taking_func_ok, &param_passed);
+}
+
+void callback_taking_func(std::function<void()> &innerCallback) {
+ innerCallback();
+}
+
+// The provided callback expects an std::function, but instead a C function
+// name is provided, and C++ implicitly auto-constructs a pointer from it.
+void callback_with_implicit_cast() {
+ std::once_flag flag;
+ call_once(flag, callback_taking_func, callback_with_implicit_cast);
+}
+
+std::once_flag another_once_flag;
+typedef void (*my_callback_t)(int *);
+my_callback_t callback;
+int global_int;
+
+void rdar40270582() {
+ call_once(another_once_flag, callback, &global_int);
+}