From a43ea64602a4cd4a18ed193bfc94a1f2aa4d3475 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. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@155621 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaTemplateInstantiate.cpp | 7 ++++++- test/SemaCXX/alias-template.cpp | 27 +++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp index 128dc2f7ff..793ee0e50a 100644 --- a/lib/Sema/SemaTemplateInstantiate.cpp +++ b/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/test/SemaCXX/alias-template.cpp b/test/SemaCXX/alias-template.cpp index 484dd3379e..4bf79f851e 100644 --- a/test/SemaCXX/alias-template.cpp +++ b/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.40.0