diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -3511,8 +3511,10 @@ } /// Determine whether this alias template is "enable_if_t". +/// libc++ >=14 uses "__enable_if_t" in C++11 mode. static bool isEnableIfAliasTemplate(TypeAliasTemplateDecl *AliasTemplate) { - return AliasTemplate->getName().equals("enable_if_t"); + return AliasTemplate->getName().equals("enable_if_t") || + AliasTemplate->getName().equals("__enable_if_t"); } /// Collect all of the separable terms in the given condition, which diff --git a/clang/test/SemaTemplate/diagnose-enable-if-t.cpp b/clang/test/SemaTemplate/diagnose-enable-if-t.cpp new file mode 100644 --- /dev/null +++ b/clang/test/SemaTemplate/diagnose-enable-if-t.cpp @@ -0,0 +1,96 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++14 %s +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++17 %s +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++20 %s + +namespace std { + inline namespace __1 { + template struct enable_if {}; + template struct enable_if { using type = T; }; + template using enable_if_t = typename enable_if::type; + } +} + +namespace similar_to_user_code { + // expected-note@+2 {{candidate template ignored: requirement 'sizeof(char) != 1' was not satisfied [with T = char]}} + template> + void f(T, short); + + // expected-note@+2 {{candidate template ignored: requirement 'sizeof(char) != 1' was not satisfied [with T = char]}} + template* = nullptr> + void f(T, int); + + // expected-note@+2 {{candidate template ignored: requirement 'sizeof(char) != 1' was not satisfied [with T = char]}} + template + std::enable_if_t f(T, long); + + void test() { + f('x', 0); // expected-error{{no matching function}} + } +} + +namespace similar_to_libcxx_version_14 { + template struct enable_if {}; + template struct enable_if { using type = T; }; + template using __enable_if_t = typename enable_if::type; + + // expected-note@+2 {{candidate template ignored: requirement 'sizeof(char) != 1' was not satisfied [with T = char]}} + template> + void f(T, short); + + // expected-note@+2 {{candidate template ignored: requirement 'sizeof(char) != 1' was not satisfied [with T = char]}} + template* = nullptr> + void f(T, int); + + // expected-note@+2 {{candidate template ignored: requirement 'sizeof(char) != 1' was not satisfied [with T = char]}} + template + __enable_if_t f(T, long); + + void test() { + f('x', 0); // expected-error{{no matching function}} + } +} + +namespace similar_to_libcxx_version_13 { + template struct _MetaBase {}; + template<> struct _MetaBase { template using _EnableIfImpl = R; }; + template using _EnableIf = typename _MetaBase::template _EnableIfImpl; + + // expected-note@+2 {{no member named '_EnableIfImpl'}} + template> + void f(T, short); + + // expected-note@+2 {{no member named '_EnableIfImpl'}} + template* = nullptr> + void f(T, int); + + // expected-note@+2 {{no member named '_EnableIfImpl'}} + template + _EnableIf f(T, long); + + void test() { + f('x', 0); // expected-error{{no matching function}} + } +} + +namespace not_all_names_are_magic { + template struct enable_if {}; + template struct enable_if { using type = T; }; + template using a_pony = typename enable_if::type; + + // expected-note@-2 {{candidate template ignored: disabled by 'enable_if' [with T = char]}} + template> + void f(T, short); + + // expected-note@-6 {{candidate template ignored: disabled by 'enable_if' [with T = char]}} + template* = nullptr> + void f(T, int); + + // expected-note@-10 {{candidate template ignored: disabled by 'enable_if' [with T = char]}} + template + a_pony f(T, long); + + void test() { + f('x', 0); // expected-error{{no matching function}} + } +}