aboutsummaryrefslogtreecommitdiff
path: root/test/SemaCXX
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2013-04-17 08:45:07 +0000
committerDouglas Gregor <dgregor@apple.com>2013-04-17 08:45:07 +0000
commit092140a434366007a611c0a1a73fb6a4e8ff7f5e (patch)
treeab580f464020dde46addde90c583a8c414a55fb7 /test/SemaCXX
parentb42f200777a66b98989160bf3987ce431540a584 (diff)
Fix PR15291: noreturn adjustment in overload resolution for function templates, from Alexander Zinenko!
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@179680 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'test/SemaCXX')
-rw-r--r--test/SemaCXX/attr-noreturn.cpp83
1 files changed, 83 insertions, 0 deletions
diff --git a/test/SemaCXX/attr-noreturn.cpp b/test/SemaCXX/attr-noreturn.cpp
index f3d548b793..41214c4f4b 100644
--- a/test/SemaCXX/attr-noreturn.cpp
+++ b/test/SemaCXX/attr-noreturn.cpp
@@ -80,3 +80,86 @@ namespace PR12948 {
template<typename> void wibble() __attribute__((__noreturn__));
template<typename> voidfn wibble;
}
+
+// PR15291
+// Overload resolution per over.over should allow implicit noreturn adjustment.
+namespace PR15291 {
+ __attribute__((noreturn)) void foo(int) {}
+ __attribute__((noreturn)) void foo(double) {}
+
+ template <typename T>
+ __attribute__((noreturn)) void bar(T) {}
+
+ void baz(int) {}
+ void baz(double) {}
+
+ template <typename T>
+ void qux(T) {}
+
+ // expected-note@+5 {{candidate function [with T = void (*)(int) __attribute__((noreturn))] not viable: no overload of 'baz' matching 'void (*)(int) __attribute__((noreturn))' for 1st argument}}
+ // expected-note@+4 {{candidate function [with T = void (*)(int) __attribute__((noreturn))] not viable: no overload of 'qux' matching 'void (*)(int) __attribute__((noreturn))' for 1st argument}}
+ // expected-note@+3 {{candidate function [with T = void (*)(int) __attribute__((noreturn))] not viable: no overload of 'bar' matching 'void (*)(int) __attribute__((noreturn))' for 1st argument}}
+ // expected-note@+2 {{candidate function [with T = void (*)(int)] not viable: no overload of 'bar' matching 'void (*)(int)' for 1st argument}}
+ // expected-note@+1 {{candidate function [with T = void (int)] not viable: no overload of 'bar' matching 'void (*)(int)' for 1st argument}}
+ template <typename T> void accept_T(T) {}
+
+ // expected-note@+1 {{candidate function not viable: no overload of 'bar' matching 'void (*)(int)' for 1st argument}}
+ void accept_fptr(void (*f)(int)) {
+ f(42);
+ }
+
+ // expected-note@+2 {{candidate function not viable: no overload of 'baz' matching 'void (*)(int) __attribute__((noreturn))' for 1st argument}}
+ // expected-note@+1 {{candidate function not viable: no overload of 'qux' matching 'void (*)(int) __attribute__((noreturn))' for 1st argument}}
+ void accept_noreturn_fptr(void __attribute__((noreturn)) (*f)(int)) {
+ f(42);
+ }
+
+ typedef void (*fptr_t)(int);
+ typedef void __attribute__((noreturn)) (*fptr_noreturn_t)(int);
+
+ // expected-note@+1 {{candidate function not viable: no overload of 'bar' matching 'fptr_t' (aka 'void (*)(int)') for 1st argument}}
+ void accept_fptr_t(fptr_t f) {
+ f(42);
+ }
+
+ // expected-note@+2 {{candidate function not viable: no overload of 'baz' matching 'fptr_noreturn_t' (aka 'void (*)(int) __attribute__((noreturn))') for 1st argument}}
+ // expected-note@+1 {{candidate function not viable: no overload of 'qux' matching 'fptr_noreturn_t' (aka 'void (*)(int) __attribute__((noreturn))') for 1st argument}}
+ void accept_fptr_noreturn_t(fptr_noreturn_t f) {
+ f(42);
+ }
+
+ // Stripping noreturn should work if everything else is correct.
+ void strip_noreturn() {
+ accept_fptr(foo);
+ accept_fptr(bar<int>);
+ accept_fptr(bar<double>); // expected-error {{no matching function for call to 'accept_fptr'}}
+
+ accept_fptr_t(foo);
+ accept_fptr_t(bar<int>);
+ accept_fptr_t(bar<double>); // expected-error {{no matching function for call to 'accept_fptr_t'}}
+
+ accept_T<void __attribute__((noreturn)) (*)(int)>(foo);
+ accept_T<void __attribute__((noreturn)) (*)(int)>(bar<int>);
+ accept_T<void __attribute__((noreturn)) (*)(int)>(bar<double>); // expected-error {{no matching function for call to 'accept_T'}}
+
+ accept_T<void (*)(int)>(foo);
+ accept_T<void (*)(int)>(bar<int>);
+ accept_T<void (*)(int)>(bar<double>); // expected-error {{no matching function for call to 'accept_T'}}
+
+ accept_T<void (int)>(foo);
+ accept_T<void (int)>(bar<int>);
+ accept_T<void (int)>(bar<double>); // expected-error {{no matching function for call to 'accept_T'}}
+ }
+
+ // Introducing noreturn should not work.
+ void introduce_noreturn() {
+ accept_noreturn_fptr(baz); // expected-error {{no matching function for call to 'accept_noreturn_fptr'}}
+ accept_noreturn_fptr(qux<int>); // expected-error {{no matching function for call to 'accept_noreturn_fptr'}}
+
+ accept_fptr_noreturn_t(baz); // expected-error {{no matching function for call to 'accept_fptr_noreturn_t'}}
+ accept_fptr_noreturn_t(qux<int>); // expected-error {{no matching function for call to 'accept_fptr_noreturn_t'}}
+
+ accept_T<void __attribute__((noreturn)) (*)(int)>(baz); // expected-error {{no matching function for call to 'accept_T'}}
+ accept_T<void __attribute__((noreturn)) (*)(int)>(qux<int>); // expected-error {{no matching function for call to 'accept_T'}}
+ }
+}