summaryrefslogtreecommitdiff
path: root/test/SemaTemplate
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2017-06-07 21:46:22 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2017-06-07 21:46:22 +0000
commit410ea620fd05609810e3710ba2f75e1b763b0afc (patch)
treedf5e2cea69e344dc4d7233a159b0ade87c3e6423 /test/SemaTemplate
parenta2380ee70ae88d4dbce307112b66eb7563f72873 (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.cpp54
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