]> granicus.if.org Git - clang/commitdiff
PR12647: An alias template instantiation which occurs in a SFINAE context is
authorRichard Smith <richard-llvm@metafoo.co.uk>
Thu, 26 Apr 2012 07:24:08 +0000 (07:24 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Thu, 26 Apr 2012 07:24:08 +0000 (07:24 +0000)
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
test/SemaCXX/alias-template.cpp

index 128dc2f7ff403fa59552c7c0f8860af19e6e0fac..793ee0e50ade67ea19ef205c61016ae7eb0500cd 100644 (file)
@@ -638,8 +638,13 @@ llvm::Optional<TemplateDeductionInfo *> 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<TypeAliasTemplateDecl>(reinterpret_cast<Decl *>(Active->Entity)))
+        break;
+      // Fall through.
+    case ActiveTemplateInstantiation::DefaultFunctionArgumentInstantiation:
     case ActiveTemplateInstantiation::ExceptionSpecInstantiation:
       // This is a template instantiation, so there is no SFINAE.
       return llvm::Optional<TemplateDeductionInfo *>();
index 484dd3379ed706d744919dc729bdec5a6d6ff96e..4bf79f851e0b9e0a959a8458c500bd5853323130 100644 (file)
@@ -145,3 +145,30 @@ namespace Curried {
   template<typename T, typename U> struct S;
   template<typename T> template<typename U> using SS = S<T, U>; // expected-error {{extraneous template parameter list in alias template declaration}}
 }
+
+// PR12647
+namespace SFINAE {
+  template<bool> struct enable_if; // expected-note 2{{here}}
+  template<> struct enable_if<true> { using type = void; };
+
+  template<typename T> struct is_enum { static constexpr bool value = __is_enum(T); };
+
+  template<typename T> using EnableIf = typename enable_if<T::value>::type; // expected-error {{undefined template}}
+  template<typename T> using DisableIf = typename enable_if<!T::value>::type; // expected-error {{undefined template}}
+
+  template<typename T> EnableIf<is_enum<T>> f();
+  template<typename T> DisableIf<is_enum<T>> f();
+
+  enum E { e };
+
+  int main() {
+    f<int>();
+    f<E>();
+  }
+
+  template<typename T, typename U = EnableIf<is_enum<T>>> struct fail1 {}; // expected-note {{here}}
+  template<typename T> struct fail2 : DisableIf<is_enum<T>> {}; // expected-note {{here}}
+
+  fail1<int> f1; // expected-note {{here}}
+  fail2<E> f2; // expected-note {{here}}
+}