summaryrefslogtreecommitdiffstats
path: root/clang
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
commit3ade5704fe9ba52a5345e423a31d0f04f7919608 (patch)
tree194875d6f3b02f8fb59223bf1582b3d98dc25bd2 /clang
parent2eed7a13108be8b2806319d34dd5493dc071caff (diff)
downloadbcm5719-llvm-3ade5704fe9ba52a5345e423a31d0f04f7919608.tar.gz
bcm5719-llvm-3ade5704fe9ba52a5345e423a31d0f04f7919608.zip
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. llvm-svn: 118211
Diffstat (limited to 'clang')
-rw-r--r--clang/lib/AST/ASTContext.cpp30
-rw-r--r--clang/test/SemaTemplate/typename-specifier-4.cpp17
2 files changed, 44 insertions, 3 deletions
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index 366fe7d28f1..7ed1035c0f1 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/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/clang/test/SemaTemplate/typename-specifier-4.cpp b/clang/test/SemaTemplate/typename-specifier-4.cpp
index 5a313bf2256..f5bc7477dd4 100644
--- a/clang/test/SemaTemplate/typename-specifier-4.cpp
+++ b/clang/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() { }
+}
OpenPOWER on IntegriCloud