aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/AST/ASTContext.cpp30
-rw-r--r--test/SemaTemplate/typename-specifier-4.cpp17
2 files changed, 44 insertions, 3 deletions
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index 366fe7d28f..7ed1035c0f 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -2723,9 +2723,33 @@ ASTContext::getCanonicalNestedNameSpecifier(NestedNameSpecifier *NNS) {
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:
diff --git a/test/SemaTemplate/typename-specifier-4.cpp b/test/SemaTemplate/typename-specifier-4.cpp
index 5a313bf225..f5bc7477dd 100644
--- a/test/SemaTemplate/typename-specifier-4.cpp
+++ b/test/SemaTemplate/typename-specifier-4.cpp
@@ -117,3 +117,20 @@ namespace PR6463 {
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() { }
+}