]> granicus.if.org Git - clang/commitdiff
Fix the rest of PR21289: a pack expansion that we can't expand yet makes a
authorRichard Smith <richard-llvm@metafoo.co.uk>
Fri, 17 Oct 2014 20:56:14 +0000 (20:56 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Fri, 17 Oct 2014 20:56:14 +0000 (20:56 +0000)
template specialization type dependent, even if it has no dependent template
arguments. I've filed a corresponding bug against the C++ standard.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@220088 91177308-0d34-0410-b5e6-96231b3b80d8

lib/AST/TemplateBase.cpp
lib/AST/Type.cpp
test/SemaTemplate/dependent-type-identity.cpp

index 929fdfc7ceb88241a0b93528713708282ad7af78..f07b18e7c12a39927412a41efa3337532857ef30 100644 (file)
@@ -90,7 +90,8 @@ bool TemplateArgument::isDependent() const {
     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() const {
     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())
index 3c5e80e9ba552914e1a9e6edbf476c8105da430f..4bf5927f6b34f8910cc4b83e0e56a20a35b14441 100644 (file)
@@ -1980,32 +1980,14 @@ anyDependentTemplateArguments(const TemplateArgumentLoc *Args, unsigned N,
   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,
           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 T,
     // 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]);
   }
 
index a796834ce01a888fcb172c0149a17eba9683eabc..5b9da5d89258a0e7ab073e902cce1f661fb1ba13 100644 (file)
@@ -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}}
+}