aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2010-11-04 00:09:33 +0000
committerDouglas Gregor <dgregor@apple.com>2010-11-04 00:09:33 +0000
commit264bf66d55563dd86a3d7e06738aa427de512d2c (patch)
treeefd540c533339c3547d6e54d9441bb676bfc8ae6
parent06de2cfe0b46e525ba8618536b12aecfbd12d127 (diff)
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. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@118211 91177308-0d34-0410-b5e6-96231b3b80d8
-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() { }
+}