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@-1{{because 'typename T::temp<int>' would be invalid: type 'int' cannot be used prior to '::' because it has no members}} -// expected-note@-2{{because 'typename T::temp<int>' would be invalid: no member named 'temp' in 'D'}} -// expected-note@-3{{because 'typename T::temp<int>' would be invalid: template name refers to non-type template 'G::template temp'}} +// expected-note@-1{{because 'typename T::template temp<int>' would be invalid: type 'int' cannot be used prior to '::' because it has no members}} +// expected-note@-2{{because 'typename T::template temp<int>' would be invalid: no member named 'temp' in 'D'}} +// expected-note@-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]}} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits