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'.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@156463 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/test/SemaTemplate/overload-candidates.cpp b/test/SemaTemplate/overload-candidates.cpp
index 23ca1d4..dc6d2a5 100644
--- a/test/SemaTemplate/overload-candidates.cpp
+++ b/test/SemaTemplate/overload-candidates.cpp
@@ -40,3 +40,25 @@
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}}