[clang] 145dcef - [clang-tidy] modernize-use-using: Fix broken fixit with InjectedClassName

Matthias Gehre via cfe-commits cfe-commits at lists.llvm.org
Mon Apr 27 05:23:33 PDT 2020


Author: Matthias Gehre
Date: 2020-04-27T14:23:23+02:00
New Revision: 145dcef8bdf9da9684c9c4e34a8e6c45baafab74

URL: https://github.com/llvm/llvm-project/commit/145dcef8bdf9da9684c9c4e34a8e6c45baafab74
DIFF: https://github.com/llvm/llvm-project/commit/145dcef8bdf9da9684c9c4e34a8e6c45baafab74.diff

LOG: [clang-tidy] modernize-use-using: Fix broken fixit with InjectedClassName

Summary:
Before this PR, `modernize-use-using` would transform the typedef in
```
template <int A>
struct InjectedClassName {
  typedef InjectedClassName b;
};
```
into `using b = InjectedClassName<A>;` and
```
template <int>
struct InjectedClassNameWithUnnamedArgument {
  typedef InjectedClassNameWithUnnamedArgument b;
};
```
into `using b = InjectedClassNameWithUnnamedArgument<>;`.
The first fixit is surprising because its different than the code
before, but the second fixit doesn't even compile.

This PR adds an option to the TypePrinter to print InjectedClassNameType without
template parameters (i.e. as written).

Reviewers: aaron.ballman, alexfh, hokein, njames93

Subscribers: xazax.hun, cfe-commits

Tags: #clang

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

Added: 
    

Modified: 
    clang-tools-extra/clang-tidy/modernize/UseUsingCheck.cpp
    clang-tools-extra/test/clang-tidy/checkers/modernize-use-using.cpp
    clang/include/clang/AST/PrettyPrinter.h
    clang/lib/AST/TypePrinter.cpp

Removed: 
    


################################################################################
diff  --git a/clang-tools-extra/clang-tidy/modernize/UseUsingCheck.cpp b/clang-tools-extra/clang-tidy/modernize/UseUsingCheck.cpp
index f352374d4b91..f6dc5c044a7a 100644
--- a/clang-tools-extra/clang-tidy/modernize/UseUsingCheck.cpp
+++ b/clang-tools-extra/clang-tidy/modernize/UseUsingCheck.cpp
@@ -58,6 +58,7 @@ void UseUsingCheck::check(const MatchFinder::MatchResult &Result) {
   printPolicy.SuppressScope = true;
   printPolicy.ConstantArraySizeAsWritten = true;
   printPolicy.UseVoidForZeroParams = false;
+  printPolicy.PrintInjectedClassNameWithArguments = false;
 
   std::string Type = MatchedDecl->getUnderlyingType().getAsString(printPolicy);
   std::string Name = MatchedDecl->getNameAsString();

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 8d25dbb95658..b74e67a17f86 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
@@ -289,3 +289,16 @@ typedef enum { ea2, eb2 } EnumT2_CheckTypedefImpactFromAnotherFile;
 // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
 // CHECK-FIXES: using EnumT2_CheckTypedefImpactFromAnotherFile = enum { ea2, eb2 };
 
+template <int A>
+struct InjectedClassName {
+  typedef InjectedClassName b;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use 'using' instead of 'typedef'
+  // CHECK-FIXES: using b = InjectedClassName;
+};
+
+template <int>
+struct InjectedClassNameWithUnnamedArgument {
+  typedef InjectedClassNameWithUnnamedArgument b;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use 'using' instead of 'typedef'
+  // CHECK-FIXES: using b = InjectedClassNameWithUnnamedArgument;
+};

diff  --git a/clang/include/clang/AST/PrettyPrinter.h b/clang/include/clang/AST/PrettyPrinter.h
index 21e5ca94f6c4..65c7e2385677 100644
--- a/clang/include/clang/AST/PrettyPrinter.h
+++ b/clang/include/clang/AST/PrettyPrinter.h
@@ -63,7 +63,7 @@ struct PrintingPolicy {
         MSWChar(LO.MicrosoftExt && !LO.WChar), IncludeNewlines(true),
         MSVCFormatting(false), ConstantsAsWritten(false),
         SuppressImplicitBase(false), FullyQualifiedName(false),
-        PrintCanonicalTypes(false) {}
+        PrintCanonicalTypes(false), PrintInjectedClassNameWithArguments(true) {}
 
   /// Adjust this printing policy for cases where it's known that we're
   /// printing C++ code (for instance, if AST dumping reaches a C++-only
@@ -244,6 +244,11 @@ struct PrintingPolicy {
   /// Whether to print types as written or canonically.
   unsigned PrintCanonicalTypes : 1;
 
+  /// Whether to print an InjectedClassNameType with template arguments or as
+  /// written. When a template argument is unnamed, printing it results in
+  /// invalid C++ code.
+  unsigned PrintInjectedClassNameWithArguments : 1;
+
   /// Callbacks to use to allow the behavior of printing to be customized.
   const PrintingCallbacks *Callbacks = nullptr;
 };

diff  --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp
index f000e1f6c932..cf82d1a26156 100644
--- a/clang/lib/AST/TypePrinter.cpp
+++ b/clang/lib/AST/TypePrinter.cpp
@@ -1329,7 +1329,12 @@ void TypePrinter::printTemplateSpecializationAfter(
 
 void TypePrinter::printInjectedClassNameBefore(const InjectedClassNameType *T,
                                                raw_ostream &OS) {
-  printTemplateSpecializationBefore(T->getInjectedTST(), OS);
+  if (Policy.PrintInjectedClassNameWithArguments)
+    return printTemplateSpecializationBefore(T->getInjectedTST(), OS);
+
+  IncludeStrongLifetimeRAII Strong(Policy);
+  T->getTemplateName().print(OS, Policy);
+  spaceBeforePlaceHolder(OS);
 }
 
 void TypePrinter::printInjectedClassNameAfter(const InjectedClassNameType *T,


        


More information about the cfe-commits mailing list