[cfe-commits] r118211 - in /cfe/trunk: lib/AST/ASTContext.cpp test/SemaTemplate/typename-specifier-4.cpp

Douglas Gregor dgregor at apple.com
Wed Nov 3 17:09:33 PDT 2010


Author: dgregor
Date: Wed Nov  3 19:09:33 2010
New Revision: 118211

URL: http://llvm.org/viewvc/llvm-project?rev=118211&view=rev
Log:
When canonicalizing nested-name-specifiers involving dependent names
or dependent specializations, rip apart the dependent name/dependent
specialization to recanonicalize its pieces, because
nested-name-specifiers store "dependent-type::identifier" differently
than types do. Fixes PR7419.

Modified:
    cfe/trunk/lib/AST/ASTContext.cpp
    cfe/trunk/test/SemaTemplate/typename-specifier-4.cpp

Modified: cfe/trunk/lib/AST/ASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=118211&r1=118210&r2=118211&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTContext.cpp (original)
+++ cfe/trunk/lib/AST/ASTContext.cpp Wed Nov  3 19:09:33 2010
@@ -2723,9 +2723,33 @@
   case NestedNameSpecifier::TypeSpec:
   case NestedNameSpecifier::TypeSpecWithTemplate: {
     QualType T = getCanonicalType(QualType(NNS->getAsType(), 0));
-    return NestedNameSpecifier::Create(*this, 0,
-                 NNS->getKind() == NestedNameSpecifier::TypeSpecWithTemplate,
-                                       T.getTypePtr());
+    
+    // If we have some kind of dependent-named type (e.g., "typename T::type"),
+    // break it apart into its prefix and identifier, then reconsititute those
+    // as the canonical nested-name-specifier. This is required to canonicalize
+    // a dependent nested-name-specifier involving typedefs of dependent-name
+    // types, e.g.,
+    //   typedef typename T::type T1;
+    //   typedef typename T1::type T2;
+    if (const DependentNameType *DNT = T->getAs<DependentNameType>()) {
+      NestedNameSpecifier *Prefix
+        = getCanonicalNestedNameSpecifier(DNT->getQualifier());
+      return NestedNameSpecifier::Create(*this, Prefix, 
+                           const_cast<IdentifierInfo *>(DNT->getIdentifier()));
+    }    
+
+    if (const DependentTemplateSpecializationType *DTST
+          = T->getAs<DependentTemplateSpecializationType>()) {
+      NestedNameSpecifier *Prefix
+        = getCanonicalNestedNameSpecifier(DTST->getQualifier());
+      TemplateName Name
+        = getDependentTemplateName(Prefix, DTST->getIdentifier());
+      T = getTemplateSpecializationType(Name, 
+                                        DTST->getArgs(), DTST->getNumArgs());
+      T = getCanonicalType(T);
+    }
+    
+    return NestedNameSpecifier::Create(*this, 0, false, T.getTypePtr());
   }
 
   case NestedNameSpecifier::Global:

Modified: cfe/trunk/test/SemaTemplate/typename-specifier-4.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/typename-specifier-4.cpp?rev=118211&r1=118210&r2=118211&view=diff
==============================================================================
--- cfe/trunk/test/SemaTemplate/typename-specifier-4.cpp (original)
+++ cfe/trunk/test/SemaTemplate/typename-specifier-4.cpp Wed Nov  3 19:09:33 2010
@@ -117,3 +117,20 @@
     return x;
   }
 }
+
+namespace PR7419 {
+  template <typename T> struct S {
+    typedef typename T::Y T2;
+    typedef typename T2::Z T3;
+    typedef typename T3::W T4;
+    T4 *f();
+
+    typedef typename T::template Y<int> TT2;
+    typedef typename TT2::template Z<float> TT3;
+    typedef typename TT3::template W<double> TT4;
+    TT4 g();
+  };
+
+  template <typename T> typename T::Y::Z::W *S<T>::f() { }
+  template <typename T> typename T::template Y<int>::template Z<float>::template W<double> S<T>::g() { }
+}





More information about the cfe-commits mailing list