diff options
author | Douglas Gregor <dgregor@apple.com> | 2013-04-17 08:45:07 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2013-04-17 08:45:07 +0000 |
commit | 092140a434366007a611c0a1a73fb6a4e8ff7f5e (patch) | |
tree | ab580f464020dde46addde90c583a8c414a55fb7 /test/SemaCXX | |
parent | b42f200777a66b98989160bf3987ce431540a584 (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.cpp | 83 |
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'}} + } +} |