Skip to content

Commit 145dcef

Browse files
committed
[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
1 parent f181f1b commit 145dcef

File tree

4 files changed

+26
-2
lines changed

4 files changed

+26
-2
lines changed

clang-tools-extra/clang-tidy/modernize/UseUsingCheck.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ void UseUsingCheck::check(const MatchFinder::MatchResult &Result) {
5858
printPolicy.SuppressScope = true;
5959
printPolicy.ConstantArraySizeAsWritten = true;
6060
printPolicy.UseVoidForZeroParams = false;
61+
printPolicy.PrintInjectedClassNameWithArguments = false;
6162

6263
std::string Type = MatchedDecl->getUnderlyingType().getAsString(printPolicy);
6364
std::string Name = MatchedDecl->getNameAsString();

clang-tools-extra/test/clang-tidy/checkers/modernize-use-using.cpp

+13
Original file line numberDiff line numberDiff line change
@@ -289,3 +289,16 @@ typedef enum { ea2, eb2 } EnumT2_CheckTypedefImpactFromAnotherFile;
289289
// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
290290
// CHECK-FIXES: using EnumT2_CheckTypedefImpactFromAnotherFile = enum { ea2, eb2 };
291291

292+
template <int A>
293+
struct InjectedClassName {
294+
typedef InjectedClassName b;
295+
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use 'using' instead of 'typedef'
296+
// CHECK-FIXES: using b = InjectedClassName;
297+
};
298+
299+
template <int>
300+
struct InjectedClassNameWithUnnamedArgument {
301+
typedef InjectedClassNameWithUnnamedArgument b;
302+
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use 'using' instead of 'typedef'
303+
// CHECK-FIXES: using b = InjectedClassNameWithUnnamedArgument;
304+
};

clang/include/clang/AST/PrettyPrinter.h

+6-1
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ struct PrintingPolicy {
6363
MSWChar(LO.MicrosoftExt && !LO.WChar), IncludeNewlines(true),
6464
MSVCFormatting(false), ConstantsAsWritten(false),
6565
SuppressImplicitBase(false), FullyQualifiedName(false),
66-
PrintCanonicalTypes(false) {}
66+
PrintCanonicalTypes(false), PrintInjectedClassNameWithArguments(true) {}
6767

6868
/// Adjust this printing policy for cases where it's known that we're
6969
/// printing C++ code (for instance, if AST dumping reaches a C++-only
@@ -244,6 +244,11 @@ struct PrintingPolicy {
244244
/// Whether to print types as written or canonically.
245245
unsigned PrintCanonicalTypes : 1;
246246

247+
/// Whether to print an InjectedClassNameType with template arguments or as
248+
/// written. When a template argument is unnamed, printing it results in
249+
/// invalid C++ code.
250+
unsigned PrintInjectedClassNameWithArguments : 1;
251+
247252
/// Callbacks to use to allow the behavior of printing to be customized.
248253
const PrintingCallbacks *Callbacks = nullptr;
249254
};

clang/lib/AST/TypePrinter.cpp

+6-1
Original file line numberDiff line numberDiff line change
@@ -1329,7 +1329,12 @@ void TypePrinter::printTemplateSpecializationAfter(
13291329

13301330
void TypePrinter::printInjectedClassNameBefore(const InjectedClassNameType *T,
13311331
raw_ostream &OS) {
1332-
printTemplateSpecializationBefore(T->getInjectedTST(), OS);
1332+
if (Policy.PrintInjectedClassNameWithArguments)
1333+
return printTemplateSpecializationBefore(T->getInjectedTST(), OS);
1334+
1335+
IncludeStrongLifetimeRAII Strong(Policy);
1336+
T->getTemplateName().print(OS, Policy);
1337+
spaceBeforePlaceHolder(OS);
13331338
}
13341339

13351340
void TypePrinter::printInjectedClassNameAfter(const InjectedClassNameType *T,

0 commit comments

Comments
 (0)