From 33d7d68cb694613dfa836cf506d8af012563b9c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johann=20Kl=C3=A4hn?= <johann.klaehn@kip.uni-heidelberg.de> Date: Wed, 26 Jul 2017 15:06:10 +0200 Subject: [PATCH 1/5] [Tooling] Fully qualify template parameters of nested name specifier in getFullyQualifiedName --- clang/lib/AST/QualTypeNames.cpp | 18 ++++++++++++++---- clang/unittests/Tooling/QualTypeNamesTest.cpp | 8 +++++++- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/tools/clang/lib/AST/QualTypeNames.cpp b/tools/clang/lib/AST/QualTypeNames.cpp index f28f00171cc..ecfef57566e 100644 --- a/tools/clang/lib/AST/QualTypeNames.cpp +++ b/tools/clang/lib/AST/QualTypeNames.cpp @@ -356,11 +356,21 @@ NestedNameSpecifier *createNestedNameSpecifier(const ASTContext &Ctx, const TypeDecl *TD, bool FullyQualify, bool WithGlobalNsPrefix) { + const Type *TypePtr = TD->getTypeForDecl(); + // In case of template specializations iterate over the arguments and + // fully qualify them as well. + if (isa<const TemplateSpecializationType>(TypePtr) || + isa<const RecordType>(TypePtr)) { + // We are asked to fully qualify and we have a Record Type (which + // may point to a template specialization) or Template + // Specialization Type. We need to fully qualify their arguments. + + TypePtr = getFullyQualifiedTemplateType(Ctx, TypePtr, WithGlobalNsPrefix); + } + return NestedNameSpecifier::Create( - Ctx, - createOuterNNS(Ctx, TD, FullyQualify, WithGlobalNsPrefix), - false /*No TemplateKeyword*/, - TD->getTypeForDecl()); + Ctx, createOuterNNS(Ctx, TD, FullyQualify, WithGlobalNsPrefix), + false /*No TemplateKeyword*/, TypePtr); } /// Return the fully qualified type, including fully-qualified diff --git a/tools/clang/unittests/Tooling/QualTypeNamesTest.cpp b/tools/clang/unittests/Tooling/QualTypeNamesTest.cpp index b6c30297787..e93a0475812 100644 --- a/tools/clang/unittests/Tooling/QualTypeNamesTest.cpp +++ b/tools/clang/unittests/Tooling/QualTypeNamesTest.cpp @@ -66,6 +66,10 @@ TEST(QualTypeNameTest, getFullyQualifiedName) { // Template parameter expansion. Visitor.ExpectedQualTypeNames["CheckC"] = "A::B::Template0<A::B::C::MyInt, A::B::AnotherClass>"; + // Template parameters of nested name specifier should also be fully expanded. + Visitor.ExpectedQualTypeNames["CheckNested"] = + // "typename A::B::Template0<A::B::C::MyInt, A::B::AnotherClass>::nested"; + "typename A::B::Template0<int, A::B::Class0>::nested"; // Recursive template parameter expansion. Visitor.ExpectedQualTypeNames["CheckD"] = "A::B::Template0<A::B::Template1<A::B::C::MyInt, A::B::AnotherClass>, " @@ -108,7 +112,7 @@ TEST(QualTypeNameTest, getFullyQualifiedName) { " using InnerAlias = OuterTemplateClass<T>;\n" " InnerAlias<int> AliasTypeVal;\n" " }\n" - " template<class X, class Y> class Template0;" + " template<class X, class Y> struct Template0 { typedef int nested; };" " template<class X, class Y> class Template1;" " typedef B::Class0 AnotherClass;\n" " void Function1(Template0<C::MyInt,\n" @@ -116,6 +120,8 @@ TEST(QualTypeNameTest, getFullyQualifiedName) { " void Function2(Template0<Template1<C::MyInt, AnotherClass>,\n" " Template0<int, long> > CheckD);\n" " void Function3(const B::Class0* CheckM);\n" + " void Function4(typename Template0<C::MyInt,\n" + " AnotherClass>::nested CheckNested);\n" " }\n" "template<typename... Values> class Variadic {};\n" "Variadic<int, B::Template0<int, char>, " -- 2.23.0