From: Douglas Gregor Date: Thu, 4 Nov 2010 00:09:33 +0000 (+0000) Subject: When canonicalizing nested-name-specifiers involving dependent names X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=264bf66d55563dd86a3d7e06738aa427de512d2c;p=clang 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 --- 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()) { + NestedNameSpecifier *Prefix + = getCanonicalNestedNameSpecifier(DNT->getQualifier()); + return NestedNameSpecifier::Create(*this, Prefix, + const_cast(DNT->getIdentifier())); + } + + if (const DependentTemplateSpecializationType *DTST + = T->getAs()) { + 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 struct S { + typedef typename T::Y T2; + typedef typename T2::Z T3; + typedef typename T3::W T4; + T4 *f(); + + typedef typename T::template Y TT2; + typedef typename TT2::template Z TT3; + typedef typename TT3::template W TT4; + TT4 g(); + }; + + template typename T::Y::Z::W *S::f() { } + template typename T::template Y::template Z::template W S::g() { } +}