From 72249ba9454f9cb1fc59aee7815ffbb412c2d871 Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Thu, 26 Apr 2012 07:24:08 +0000 Subject: [PATCH] PR12647: An alias template instantiation which occurs in a SFINAE context is itself a SFINAE context. llvm-svn: 155621 --- clang/lib/Sema/SemaTemplateInstantiate.cpp | 7 ++++++- clang/test/SemaCXX/alias-template.cpp | 27 +++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index 128dc2f..793ee0e 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -638,8 +638,13 @@ llvm::Optional Sema::isSFINAEContext() const { ++Active) { switch(Active->Kind) { - case ActiveTemplateInstantiation::DefaultFunctionArgumentInstantiation: case ActiveTemplateInstantiation::TemplateInstantiation: + // An instantiation of an alias template may or may not be a SFINAE + // context, depending on what else is on the stack. + if (isa(reinterpret_cast(Active->Entity))) + break; + // Fall through. + case ActiveTemplateInstantiation::DefaultFunctionArgumentInstantiation: case ActiveTemplateInstantiation::ExceptionSpecInstantiation: // This is a template instantiation, so there is no SFINAE. return llvm::Optional(); diff --git a/clang/test/SemaCXX/alias-template.cpp b/clang/test/SemaCXX/alias-template.cpp index 484dd33..4bf79f8 100644 --- a/clang/test/SemaCXX/alias-template.cpp +++ b/clang/test/SemaCXX/alias-template.cpp @@ -145,3 +145,30 @@ namespace Curried { template struct S; template template using SS = S; // expected-error {{extraneous template parameter list in alias template declaration}} } + +// PR12647 +namespace SFINAE { + template struct enable_if; // expected-note 2{{here}} + template<> struct enable_if { using type = void; }; + + template struct is_enum { static constexpr bool value = __is_enum(T); }; + + template using EnableIf = typename enable_if::type; // expected-error {{undefined template}} + template using DisableIf = typename enable_if::type; // expected-error {{undefined template}} + + template EnableIf> f(); + template DisableIf> f(); + + enum E { e }; + + int main() { + f(); + f(); + } + + template>> struct fail1 {}; // expected-note {{here}} + template struct fail2 : DisableIf> {}; // expected-note {{here}} + + fail1 f1; // expected-note {{here}} + fail2 f2; // expected-note {{here}} +} -- 2.7.4