diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2017-06-07 21:46:22 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2017-06-07 21:46:22 +0000 |
commit | 410ea620fd05609810e3710ba2f75e1b763b0afc (patch) | |
tree | df5e2cea69e344dc4d7233a159b0ade87c3e6423 /test/SemaTemplate | |
parent | a2380ee70ae88d4dbce307112b66eb7563f72873 (diff) |
[c++1z] Support deducing B in noexcept(B).
This is not required by the standard (yet), but there seems to be reasonable
support for this being a defect according to CWG discussion, and libstdc++ 7.1
relies on it working.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@304946 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'test/SemaTemplate')
-rw-r--r-- | test/SemaTemplate/temp_arg_type.cpp | 54 |
1 files changed, 54 insertions, 0 deletions
diff --git a/test/SemaTemplate/temp_arg_type.cpp b/test/SemaTemplate/temp_arg_type.cpp index daad61c142..9069f63e02 100644 --- a/test/SemaTemplate/temp_arg_type.cpp +++ b/test/SemaTemplate/temp_arg_type.cpp @@ -1,6 +1,7 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s // RUN: %clang_cc1 -fsyntax-only -verify -std=c++98 %s // RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++1z %s template<typename T> class A; // expected-note 2 {{template parameter is declared here}} expected-note{{template is declared here}} @@ -53,3 +54,56 @@ A1<Array<int, 17>::type> ax; // FIXME: [temp.arg.type]p3. The check doesn't really belong here (it // belongs somewhere in the template instantiation section). + +#if __cplusplus >= 201703 +// As a defect resolution, we support deducing B in noexcept(B). +namespace deduce_noexcept { + template<typename> struct function; + template<typename R, typename ...A, bool N> + struct function<R(A...) noexcept(N)> { + static constexpr bool Noexcept = N; + }; + static_assert(function<int(float, double) noexcept>::Noexcept); + static_assert(!function<int(float, double)>::Noexcept); + + void noexcept_function() noexcept; + void throwing_function(); + + template<typename T, bool B> float &deduce_function(T(*)() noexcept(B)); // expected-note {{candidate}} + template<typename T> int &deduce_function(T(*)() noexcept); // expected-note {{candidate}} + void test_function_deduction() { + // FIXME: This should probably unambiguously select the second overload. + int &r = deduce_function(noexcept_function); // expected-error {{ambiguous}} + float &s = deduce_function(throwing_function); + } + + namespace low_priority_deduction { + template<int> struct A {}; + template<auto B> void f(A<B>, void(*)() noexcept(B)) { + using T = decltype(B); + using T = int; + } + void g() { f(A<0>(), g); } // ok, deduce B as an int + } + + // FIXME: It's not clear whether this should work. We're told to deduce with + // P being the function template type and A being the declared type, which + // would accept this, but considering the exception specification in such + // cases breaks new/delete matching. + template<bool Noexcept> void dep() noexcept(Noexcept) {} // expected-note 3{{couldn't infer template argument 'Noexcept'}} + template void dep(); // expected-error {{does not refer to a function template}} + template void dep() noexcept(true); // expected-error {{does not refer to a function template}} + template void dep() noexcept(false); // expected-error {{does not refer to a function template}} + + // FIXME: It's also not clear whether this should be valid: do we substitute + // into the function type (including the exception specification) or not? + template<typename T> typename T::type1 f() noexcept(T::a); + template<typename T> typename T::type2 f() noexcept(T::b) {} + struct X { + static constexpr bool b = true; + using type1 = void; + using type2 = void; + }; + template void f<X>(); +} +#endif |