mgehre created this revision. mgehre added reviewers: aaron.ballman, alexfh, hokein, njames93. Herald added a subscriber: xazax.hun. Herald added a project: clang.
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. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D78139 Files: 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 Index: clang/test/CXX/expr/expr.prim/expr.prim.req/type-requirement.cpp =================================================================== --- clang/test/CXX/expr/expr.prim/expr.prim.req/type-requirement.cpp +++ clang/test/CXX/expr/expr.prim/expr.prim.req/type-requirement.cpp @@ -109,9 +109,9 @@ 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]}} Index: clang/lib/AST/TypePrinter.cpp =================================================================== --- clang/lib/AST/TypePrinter.cpp +++ clang/lib/AST/TypePrinter.cpp @@ -1388,6 +1388,7 @@ if (T->getQualifier()) T->getQualifier()->print(OS, Policy); + OS << "template "; OS << T->getIdentifier()->getName(); printTemplateArgumentList(OS, T->template_arguments(), Policy); spaceBeforePlaceHolder(OS); Index: clang/lib/AST/NestedNameSpecifier.cpp =================================================================== --- clang/lib/AST/NestedNameSpecifier.cpp +++ clang/lib/AST/NestedNameSpecifier.cpp @@ -308,6 +308,14 @@ // nested-name-specifier. SpecType->getTemplateName().print(OS, InnerPolicy, true); + // Print the template argument list. + printTemplateArgumentList(OS, SpecType->template_arguments(), + InnerPolicy); + } else if (const auto *SpecType = + dyn_cast<DependentTemplateSpecializationType>(T)) { + // Print the template name without its corresponding + // nested-name-specifier. + OS << SpecType->getIdentifier()->getName(); // Print the template argument list. printTemplateArgumentList(OS, SpecType->template_arguments(), InnerPolicy); Index: clang-tools-extra/test/clang-tidy/checkers/modernize-use-using.cpp =================================================================== --- clang-tools-extra/test/clang-tidy/checkers/modernize-use-using.cpp +++ clang-tools-extra/test/clang-tidy/checkers/modernize-use-using.cpp @@ -249,6 +249,17 @@ // 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 {};
Index: clang/test/CXX/expr/expr.prim/expr.prim.req/type-requirement.cpp =================================================================== --- clang/test/CXX/expr/expr.prim/expr.prim.req/type-requirement.cpp +++ clang/test/CXX/expr/expr.prim/expr.prim.req/type-requirement.cpp @@ -109,9 +109,9 @@ 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]}} Index: clang/lib/AST/TypePrinter.cpp =================================================================== --- clang/lib/AST/TypePrinter.cpp +++ clang/lib/AST/TypePrinter.cpp @@ -1388,6 +1388,7 @@ if (T->getQualifier()) T->getQualifier()->print(OS, Policy); + OS << "template "; OS << T->getIdentifier()->getName(); printTemplateArgumentList(OS, T->template_arguments(), Policy); spaceBeforePlaceHolder(OS); Index: clang/lib/AST/NestedNameSpecifier.cpp =================================================================== --- clang/lib/AST/NestedNameSpecifier.cpp +++ clang/lib/AST/NestedNameSpecifier.cpp @@ -308,6 +308,14 @@ // nested-name-specifier. SpecType->getTemplateName().print(OS, InnerPolicy, true); + // Print the template argument list. + printTemplateArgumentList(OS, SpecType->template_arguments(), + InnerPolicy); + } else if (const auto *SpecType = + dyn_cast<DependentTemplateSpecializationType>(T)) { + // Print the template name without its corresponding + // nested-name-specifier. + OS << SpecType->getIdentifier()->getName(); // Print the template argument list. printTemplateArgumentList(OS, SpecType->template_arguments(), InnerPolicy); Index: clang-tools-extra/test/clang-tidy/checkers/modernize-use-using.cpp =================================================================== --- clang-tools-extra/test/clang-tidy/checkers/modernize-use-using.cpp +++ clang-tools-extra/test/clang-tidy/checkers/modernize-use-using.cpp @@ -249,6 +249,17 @@ // 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 {};
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits