r220088 - Fix the rest of PR21289: a pack expansion that we can't expand yet makes a

Richard Smith richard-llvm at metafoo.co.uk
Fri Oct 17 13:56:14 PDT 2014


Author: rsmith
Date: Fri Oct 17 15:56:14 2014
New Revision: 220088

URL: http://llvm.org/viewvc/llvm-project?rev=220088&view=rev
Log:
Fix the rest of PR21289: a pack expansion that we can't expand yet makes a
template specialization type dependent, even if it has no dependent template
arguments. I've filed a corresponding bug against the C++ standard.

Modified:
    cfe/trunk/lib/AST/TemplateBase.cpp
    cfe/trunk/lib/AST/Type.cpp
    cfe/trunk/test/SemaTemplate/dependent-type-identity.cpp

Modified: cfe/trunk/lib/AST/TemplateBase.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/TemplateBase.cpp?rev=220088&r1=220087&r2=220088&view=diff
==============================================================================
--- cfe/trunk/lib/AST/TemplateBase.cpp (original)
+++ cfe/trunk/lib/AST/TemplateBase.cpp Fri Oct 17 15:56:14 2014
@@ -90,7 +90,8 @@ bool TemplateArgument::isDependent() con
     llvm_unreachable("Should not have a NULL template argument");
 
   case Type:
-    return getAsType()->isDependentType();
+    return getAsType()->isDependentType() ||
+           isa<PackExpansionType>(getAsType());
 
   case Template:
     return getAsTemplate().isDependent();
@@ -111,7 +112,8 @@ bool TemplateArgument::isDependent() con
     return false;
 
   case Expression:
-    return (getAsExpr()->isTypeDependent() || getAsExpr()->isValueDependent());
+    return (getAsExpr()->isTypeDependent() || getAsExpr()->isValueDependent() ||
+            isa<PackExpansionExpr>(getAsExpr()));
 
   case Pack:
     for (const auto &P : pack_elements())

Modified: cfe/trunk/lib/AST/Type.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Type.cpp?rev=220088&r1=220087&r2=220088&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Type.cpp (original)
+++ cfe/trunk/lib/AST/Type.cpp Fri Oct 17 15:56:14 2014
@@ -1980,32 +1980,14 @@ anyDependentTemplateArguments(const Temp
   return false;
 }
 
-#ifndef NDEBUG
-static bool 
-anyDependentTemplateArguments(const TemplateArgument *Args, unsigned N,
-                              bool &InstantiationDependent) {
-  for (unsigned i = 0; i != N; ++i) {
-    if (Args[i].isDependent()) {
-      InstantiationDependent = true;
-      return true;
-    }
-    
-    if (Args[i].isInstantiationDependent())
-      InstantiationDependent = true;
-  }
-  return false;
-}
-#endif
-
 TemplateSpecializationType::
 TemplateSpecializationType(TemplateName T,
                            const TemplateArgument *Args, unsigned NumArgs,
                            QualType Canon, QualType AliasedType)
   : Type(TemplateSpecialization,
          Canon.isNull()? QualType(this, 0) : Canon,
-         Canon.isNull()? T.isDependent() : Canon->isDependentType(),
-         Canon.isNull()? T.isDependent() 
-                       : Canon->isInstantiationDependentType(),
+         Canon.isNull()? true : Canon->isDependentType(),
+         Canon.isNull()? true : Canon->isInstantiationDependentType(),
          false,
          T.containsUnexpandedParameterPack()),
     Template(T), NumArgs(NumArgs), TypeAlias(!AliasedType.isNull()) {
@@ -2015,18 +1997,11 @@ TemplateSpecializationType(TemplateName
           T.getKind() == TemplateName::SubstTemplateTemplateParm ||
           T.getKind() == TemplateName::SubstTemplateTemplateParmPack) &&
          "Unexpected template name for TemplateSpecializationType");
-  bool InstantiationDependent;
-  (void)InstantiationDependent;
-  assert((!Canon.isNull() ||
-          T.isDependent() || 
-          ::anyDependentTemplateArguments(Args, NumArgs, 
-                                          InstantiationDependent)) &&
-         "No canonical type for non-dependent class template specialization");
 
   TemplateArgument *TemplateArgs
     = reinterpret_cast<TemplateArgument *>(this + 1);
   for (unsigned Arg = 0; Arg < NumArgs; ++Arg) {
-    // Update dependent and variably-modified bits.
+    // Update instantiation-dependent and variably-modified bits.
     // If the canonical type exists and is non-dependent, the template
     // specialization type can be non-dependent even if one of the type
     // arguments is. Given:
@@ -2034,17 +2009,13 @@ TemplateSpecializationType(TemplateName
     // U<T> is always non-dependent, irrespective of the type T.
     // However, U<Ts> contains an unexpanded parameter pack, even though
     // its expansion (and thus its desugared type) doesn't.
-    if (Canon.isNull() && Args[Arg].isDependent())
-      setDependent();
-    else if (Args[Arg].isInstantiationDependent())
+    if (Args[Arg].isInstantiationDependent())
       setInstantiationDependent();
-    
     if (Args[Arg].getKind() == TemplateArgument::Type &&
         Args[Arg].getAsType()->isVariablyModifiedType())
       setVariablyModified();
     if (Args[Arg].containsUnexpandedParameterPack())
       setContainsUnexpandedParameterPack();
-
     new (&TemplateArgs[Arg]) TemplateArgument(Args[Arg]);
   }
 

Modified: cfe/trunk/test/SemaTemplate/dependent-type-identity.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/dependent-type-identity.cpp?rev=220088&r1=220087&r2=220088&view=diff
==============================================================================
--- cfe/trunk/test/SemaTemplate/dependent-type-identity.cpp (original)
+++ cfe/trunk/test/SemaTemplate/dependent-type-identity.cpp Fri Oct 17 15:56:14 2014
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s
 
 // This test concerns the identity of dependent types within the
 // canonical type system. This corresponds to C++ [temp.type], which
@@ -122,3 +122,24 @@ namespace PR18275 {
   template struct A<int>;
   template struct A<int[1]>;
 }
+
+namespace PR21289 {
+  template<typename T> using X = int;
+  template<typename T, decltype(sizeof(0))> using Y = int;
+  template<typename ...Ts> struct S {};
+  template<typename ...Ts> void f() {
+    // This is a dependent type. It is *not* S<int>, even though it canonically
+    // contains no template parameters.
+    using Type = S<X<Ts>...>;
+    Type s;
+    using Type = S<int, int, int>;
+  }
+  void g() { f<void, void, void>(); }
+
+  template<typename ...Ts> void h(S<int>) {}
+  // Pending a core issue, it's not clear if these are redeclarations, but they
+  // are probably intended to be... even though substitution can succeed for one
+  // of them but fail for the other!
+  template<typename ...Ts> void h(S<X<Ts>...>) {} // expected-note {{previous}}
+  template<typename ...Ts> void h(S<Y<Ts, sizeof(Ts)>...>) {} // expected-error {{redefinition}}
+}





More information about the cfe-commits mailing list