diff options
author | Brian Gesiak <modocache@gmail.com> | 2018-04-01 22:59:22 +0000 |
---|---|---|
committer | Brian Gesiak <modocache@gmail.com> | 2018-04-01 22:59:22 +0000 |
commit | cb024024891d25bca33d1632ea95f461471c65a6 (patch) | |
tree | 8ace1bb4f861c25ec7cd02737ccff054e3e86428 /clang/test | |
parent | 8a1787ae224de305c3227c45adbd3cc5e329249b (diff) | |
download | bcm5719-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.cpp | 26 | ||||
-rw-r--r-- | clang/test/SemaCXX/coroutines.cpp | 56 |
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(); |