diff options
| author | Richard Smith <richard-llvm@metafoo.co.uk> | 2012-05-09 05:17:00 +0000 |
|---|---|---|
| committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2012-05-09 05:17:00 +0000 |
| commit | 6f8d2c6c9c3451effdf075a7034bbe77045bfeba (patch) | |
| tree | 9f37148d4c839abe13285781974985cee8bcf443 /clang/test | |
| parent | 9133c34a2a35c26692c8387763b517f808117c6f (diff) | |
| download | bcm5719-llvm-6f8d2c6c9c3451effdf075a7034bbe77045bfeba.tar.gz bcm5719-llvm-6f8d2c6c9c3451effdf075a7034bbe77045bfeba.zip | |
A little tweak to the SFINAE condition reporting. Don't say:
candidate template ignored: substitution failed [with T = int]: no type named 'type' in 'std::enable_if<false, void>'
Instead, just say:
candidate template ignored: disabled by 'enable_if' [with T = int]
... and point at the enable_if condition which (we assume) failed.
This is applied to all cases where the user writes 'typename enable_if<...>::type' (optionally prefixed with a nested name specifier), and 'enable_if<...>' names a complete class type which does not have a member named 'type', and this results in a candidate function being ignored in a SFINAE context. Thus it catches 'std::enable_if', 'std::__1::enable_if', 'boost::enable_if' and 'llvm::enable_if'.
llvm-svn: 156463
Diffstat (limited to 'clang/test')
| -rw-r--r-- | clang/test/SemaTemplate/overload-candidates.cpp | 22 |
1 files changed, 22 insertions, 0 deletions
diff --git a/clang/test/SemaTemplate/overload-candidates.cpp b/clang/test/SemaTemplate/overload-candidates.cpp index 23ca1d47f1a..dc6d2a51ec2 100644 --- a/clang/test/SemaTemplate/overload-candidates.cpp +++ b/clang/test/SemaTemplate/overload-candidates.cpp @@ -40,3 +40,25 @@ struct X { void test_X_min(X x) { (void)x.min(1, 2l); // expected-error{{no matching member function for call to 'min'}} } + +namespace boost { + template<bool, typename = void> struct enable_if {}; + template<typename T> struct enable_if<true, T> { typedef T type; }; +} +template<typename T> typename boost::enable_if<sizeof(T) == 4, int>::type if_size_4(); // expected-note{{candidate template ignored: disabled by 'enable_if' [with T = char]}} +int k = if_size_4<char>(); // expected-error{{no matching function}} + +namespace llvm { + template<typename Cond, typename T = void> struct enable_if : boost::enable_if<Cond::value, T> {}; +} +template<typename T> struct is_int { enum { value = false }; }; +template<> struct is_int<int> { enum { value = true }; }; +template<typename T> typename llvm::enable_if<is_int<T> >::type if_int(); // expected-note{{candidate template ignored: disabled by 'enable_if' [with T = char]}} +void test_if_int() { + if_int<char>(); // expected-error{{no matching function}} +} + +template<typename T> struct NonTemplateFunction { + typename boost::enable_if<sizeof(T) == 4, int>::type f(); // expected-error{{no type named 'type' in 'boost::enable_if<false, int>'; 'enable_if' cannot be used to disable this declaration}} +}; +NonTemplateFunction<char> NTFC; // expected-note{{here}} |

