[clang] 0642e5e - [clang-tidy] modernize-use-using: Fix broken fixit with 'template' keyword

Matthias Gehre via cfe-commits cfe-commits at lists.llvm.org
Fri Apr 17 01:37:42 PDT 2020


Author: Matthias Gehre
Date: 2020-04-17T10:37:24+02:00
New Revision: 0642e5e7a7e54a11120262cfafea0193e3a75faf

URL: https://github.com/llvm/llvm-project/commit/0642e5e7a7e54a11120262cfafea0193e3a75faf
DIFF: https://github.com/llvm/llvm-project/commit/0642e5e7a7e54a11120262cfafea0193e3a75faf.diff

LOG: [clang-tidy] modernize-use-using: Fix broken fixit with 'template' keyword

Summary:
Before this PR, `modernize-use-using` would transform the typedef in
```

template <typename a> class TemplateKeyword {
  typedef typename a::template f<> e;
  typedef typename a::template f<>::d e2;
};
```
into
```
template <typename a> class TemplateKeyword {
  using d = typename a::b<>;
  using d2 = typename a::template a::b<>::c;
};
```
The first one is missing the `template` keyword,
the second one has an extra `a::` scope. Both result
in compilation errors.

Reviewers: aaron.ballman, alexfh, hokein, njames93

Subscribers: xazax.hun, cfe-commits

Tags: #clang

Differential Revision: https://reviews.llvm.org/D78139

Added: 
    

Modified: 
    clang-tools-extra/test/clang-tidy/checkers/modernize-use-using.cpp
    clang/lib/AST/NestedNameSpecifier.cpp
    clang/lib/AST/TypePrinter.cpp
    clang/test/CXX/expr/expr.prim/expr.prim.req/type-requirement.cpp

Removed: 
    


################################################################################
diff  --git a/clang-tools-extra/test/clang-tidy/checkers/modernize-use-using.cpp b/clang-tools-extra/test/clang-tidy/checkers/modernize-use-using.cpp
index 2eccc9066fa6..8d25dbb95658 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/modernize-use-using.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/modernize-use-using.cpp
@@ -249,6 +249,17 @@ typedef TwoArgTemplate<TwoArgTemplate<int, Q<T{0 < 0}.b> >, S<(0 < 0), Q<b[0 < 0
 // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
 // CHECK-FIXES: using Nested_t = TwoArgTemplate<TwoArgTemplate<int, Q<T{0 < 0}.b>>, S<(0 < 0), Q<b[0 < 0]>>>;
 
+template <typename a>
+class TemplateKeyword {
+  typedef typename a::template b<> d;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use 'using' instead of 'typedef'
+  // CHECK-FIXES: using d = typename a::template b<>;
+
+  typedef typename a::template b<>::c d2;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use 'using' instead of 'typedef'
+  // CHECK-FIXES: using d2 = typename a::template b<>::c;
+};
+
 template <typename... Args>
 class Variadic {};
 

diff  --git a/clang/lib/AST/NestedNameSpecifier.cpp b/clang/lib/AST/NestedNameSpecifier.cpp
index af53c7fd9ba4..e28463516a9f 100644
--- a/clang/lib/AST/NestedNameSpecifier.cpp
+++ b/clang/lib/AST/NestedNameSpecifier.cpp
@@ -311,6 +311,14 @@ void NestedNameSpecifier::print(raw_ostream &OS, const PrintingPolicy &Policy,
       // Print the template argument list.
       printTemplateArgumentList(OS, SpecType->template_arguments(),
                                 InnerPolicy);
+    } else if (const auto *DepSpecType =
+                   dyn_cast<DependentTemplateSpecializationType>(T)) {
+      // Print the template name without its corresponding
+      // nested-name-specifier.
+      OS << DepSpecType->getIdentifier()->getName();
+      // Print the template argument list.
+      printTemplateArgumentList(OS, DepSpecType->template_arguments(),
+                                InnerPolicy);
     } else {
       // Print the type normally
       QualType(T, 0).print(OS, InnerPolicy);

diff  --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp
index 405a760c58ce..4cc0d735ed6a 100644
--- a/clang/lib/AST/TypePrinter.cpp
+++ b/clang/lib/AST/TypePrinter.cpp
@@ -1388,7 +1388,7 @@ void TypePrinter::printDependentTemplateSpecializationBefore(
 
   if (T->getQualifier())
     T->getQualifier()->print(OS, Policy);
-  OS << T->getIdentifier()->getName();
+  OS << "template " << T->getIdentifier()->getName();
   printTemplateArgumentList(OS, T->template_arguments(), Policy);
   spaceBeforePlaceHolder(OS);
 }

diff  --git a/clang/test/CXX/expr/expr.prim/expr.prim.req/type-requirement.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.req/type-requirement.cpp
index b8903b884e0a..15cbe6637845 100644
--- a/clang/test/CXX/expr/expr.prim/expr.prim.req/type-requirement.cpp
+++ b/clang/test/CXX/expr/expr.prim/expr.prim.req/type-requirement.cpp
@@ -109,9 +109,9 @@ static_assert(!requires { typename ::F<int>; });
 struct G { template<typename T> static T temp; };
 
 template<typename T> requires requires { typename T::template temp<int>; }
-// expected-note at -1{{because 'typename T::temp<int>' would be invalid: type 'int' cannot be used prior to '::' because it has no members}}
-// expected-note at -2{{because 'typename T::temp<int>' would be invalid: no member named 'temp' in 'D'}}
-// expected-note at -3{{because 'typename T::temp<int>' would be invalid: template name refers to non-type template 'G::template temp'}}
+// expected-note at -1{{because 'typename T::template temp<int>' would be invalid: type 'int' cannot be used prior to '::' because it has no members}}
+// expected-note at -2{{because 'typename T::template temp<int>' would be invalid: no member named 'temp' in 'D'}}
+// expected-note at -3{{because 'typename T::template temp<int>' would be invalid: template name refers to non-type template 'G::template temp'}}
 struct r7 {};
 
 using r7i1 = r7<int>; // expected-error{{constraints not satisfied for class template 'r7' [with T = int]}}


        


More information about the cfe-commits mailing list