Skip to content
Snippets Groups Projects
llvm5-0005-Tooling-Fully-qualify-template-parameters-of-nested-.patch 3.79 KiB
From 4427624b30117c6db67b9ea7c3f16e396edc3748 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 05/12] [Tooling] Fully qualify template parameters of nested
 name specifier in getFullyQualifiedName

---
 lib/Tooling/Core/QualTypeNames.cpp      | 18 ++++++++++++++----
 unittests/Tooling/QualTypeNamesTest.cpp |  8 +++++++-
 2 files changed, 21 insertions(+), 5 deletions(-)

diff --git a/tools/clang/lib/Tooling/Core/QualTypeNames.cpp b/tools/clang/lib/Tooling/Core/QualTypeNames.cpp
index 721c2c92fc..934624dd14 100644
--- a/tools/clang/lib/Tooling/Core/QualTypeNames.cpp
+++ b/tools/clang/lib/Tooling/Core/QualTypeNames.cpp
@@ -370,11 +370,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);
 }
 
 /// \brief 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 532fae6f5a..e27089b986 100644
--- a/tools/clang/unittests/Tooling/QualTypeNamesTest.cpp
+++ b/tools/clang/unittests/Tooling/QualTypeNamesTest.cpp
@@ -63,6 +63,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>, "
@@ -105,7 +109,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"
@@ -113,6 +117,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.13.0