summaryrefslogtreecommitdiffstats
path: root/clang/test
diff options
context:
space:
mode:
authorBrian Gesiak <modocache@gmail.com>2018-04-01 22:59:22 +0000
committerBrian Gesiak <modocache@gmail.com>2018-04-01 22:59:22 +0000
commitcb024024891d25bca33d1632ea95f461471c65a6 (patch)
tree8ace1bb4f861c25ec7cd02737ccff054e3e86428 /clang/test
parent8a1787ae224de305c3227c45adbd3cc5e329249b (diff)
downloadbcm5719-llvm-cb024024891d25bca33d1632ea95f461471c65a6.tar.gz
bcm5719-llvm-cb024024891d25bca33d1632ea95f461471c65a6.zip
[Coroutines] Find custom allocators in class scope
Summary: https://reviews.llvm.org/rL325291 implemented Coroutines TS N4723 section [dcl.fct.def.coroutine]/7, but it performed lookup of allocator functions within both the global and class scope, whereas the specified behavior is to perform lookup for custom allocators within just the class scope. To fix, add parameters to the `Sema::FindAllocationFunctions` function such that it can be used to lookup allocators in global scope, class scope, or both (instead of just being able to look up in just global scope or in both global and class scope). Then, use those parameters from within the coroutine Sema. This incorrect behavior had the unfortunate side-effect of causing the bug https://bugs.llvm.org/show_bug.cgi?id=36578 (or at least the reports of that bug in C++ programs). That bug would occur for any C++ user with a coroutine frame that took a single pointer argument, since it would then find the global placement form `operator new`, described in the C++ standard 18.6.1.3.1. This patch prevents Clang from generating code that triggers the LLVM assert described in that bug report. Test Plan: `check-clang` Reviewers: GorNishanov, eric_niebler, lewissbaker Reviewed By: GorNishanov Subscribers: EricWF, cfe-commits Differential Revision: https://reviews.llvm.org/D44552 llvm-svn: 328949
Diffstat (limited to 'clang/test')
-rw-r--r--clang/test/CodeGenCoroutines/coro-alloc.cpp26
-rw-r--r--clang/test/SemaCXX/coroutines.cpp56
2 files changed, 26 insertions, 56 deletions
diff --git a/clang/test/CodeGenCoroutines/coro-alloc.cpp b/clang/test/CodeGenCoroutines/coro-alloc.cpp
index 1cf9b8c4a90..20b00d4fec2 100644
--- a/clang/test/CodeGenCoroutines/coro-alloc.cpp
+++ b/clang/test/CodeGenCoroutines/coro-alloc.cpp
@@ -134,6 +134,32 @@ extern "C" void f1a(promise_matching_placement_new_tag, int x, float y , double
co_return;
}
+// Declare a placement form operator new, such as the one described in
+// C++ 18.6.1.3.1, which takes a void* argument.
+void* operator new(SizeT __sz, void *__p) noexcept;
+
+struct promise_matching_global_placement_new_tag {};
+struct dummy {};
+template<>
+struct std::experimental::coroutine_traits<void, promise_matching_global_placement_new_tag, dummy*> {
+ struct promise_type {
+ void get_return_object() {}
+ suspend_always initial_suspend() { return {}; }
+ suspend_always final_suspend() { return {}; }
+ void return_void() {}
+ };
+};
+
+// A coroutine that takes a single pointer argument should not invoke this
+// placement form operator. [dcl.fct.def.coroutine]/7 dictates that lookup for
+// allocation functions matching the coroutine function's signature be done
+// within the scope of the promise type's class.
+// CHECK-LABEL: f1b(
+extern "C" void f1b(promise_matching_global_placement_new_tag, dummy *) {
+ // CHECK: call i8* @_Znwm(i64
+ co_return;
+}
+
struct promise_delete_tag {};
template<>
diff --git a/clang/test/SemaCXX/coroutines.cpp b/clang/test/SemaCXX/coroutines.cpp
index ed8fd909eb9..2c979f5b30d 100644
--- a/clang/test/SemaCXX/coroutines.cpp
+++ b/clang/test/SemaCXX/coroutines.cpp
@@ -804,62 +804,6 @@ struct good_promise_nonstatic_member_custom_new_operator {
void *operator new(SizeT, coroutine_nonstatic_member_struct &, double);
};
-struct bad_promise_nonstatic_member_mismatched_custom_new_operator {
- coro<bad_promise_nonstatic_member_mismatched_custom_new_operator> get_return_object();
- suspend_always initial_suspend();
- suspend_always final_suspend();
- void return_void();
- void unhandled_exception();
- // expected-note@+1 {{candidate function not viable: requires 2 arguments, but 1 was provided}}
- void *operator new(SizeT, double);
-};
-
-struct coroutine_nonstatic_member_struct {
- coro<good_promise_nonstatic_member_custom_new_operator>
- good_coroutine_calls_nonstatic_member_custom_new_operator(double) {
- co_return;
- }
-
- coro<bad_promise_nonstatic_member_mismatched_custom_new_operator>
- bad_coroutine_calls_nonstatic_member_mistmatched_custom_new_operator(double) {
- // expected-error@-1 {{no matching function for call to 'operator new'}}
- co_return;
- }
-};
-
-struct bad_promise_mismatched_custom_new_operator {
- coro<bad_promise_mismatched_custom_new_operator> get_return_object();
- suspend_always initial_suspend();
- suspend_always final_suspend();
- void return_void();
- void unhandled_exception();
- // expected-note@+1 {{candidate function not viable: requires 4 arguments, but 1 was provided}}
- void *operator new(SizeT, double, float, int);
-};
-
-coro<bad_promise_mismatched_custom_new_operator>
-bad_coroutine_calls_mismatched_custom_new_operator(double) {
- // expected-error@-1 {{no matching function for call to 'operator new'}}
- co_return;
-}
-
-struct bad_promise_throwing_custom_new_operator {
- static coro<bad_promise_throwing_custom_new_operator> get_return_object_on_allocation_failure();
- coro<bad_promise_throwing_custom_new_operator> get_return_object();
- suspend_always initial_suspend();
- suspend_always final_suspend();
- void return_void();
- void unhandled_exception();
- // expected-error@+1 {{'operator new' is required to have a non-throwing noexcept specification when the promise type declares 'get_return_object_on_allocation_failure()'}}
- void *operator new(SizeT, double, float, int);
-};
-
-coro<bad_promise_throwing_custom_new_operator>
-bad_coroutine_calls_throwing_custom_new_operator(double, float, int) {
- // expected-note@-1 {{call to 'operator new' implicitly required by coroutine function here}}
- co_return;
-}
-
struct good_promise_noexcept_custom_new_operator {
static coro<good_promise_noexcept_custom_new_operator> get_return_object_on_allocation_failure();
coro<good_promise_noexcept_custom_new_operator> get_return_object();
OpenPOWER on IntegriCloud