jdemeule created this revision.
jdemeule added a reviewer: alexfh.
Herald added subscribers: cfe-commits, mgorny.
'modernize-user-default-member-init' does not automatically ask to remove comma
and colon when replacements are produced.
It seems, when they are apply directly from clang-tidy, the RefactoringTool
engine is smart enough to remove trailing tokens.
However, when fixes are exported, clang-apply-replacements cannot do the same
trick and will lead trailing commas and colon as reported on
https://bugs.llvm.org/show_bug.cgi?id=35051.
This patch made “modernize-use-default-member-init” generate explicitly the
removal of these locations to made it work correctly in both case (-fix and
-export-fixes).
Repository:
rCTE Clang Tools Extra
https://reviews.llvm.org/D43500
Files:
clang-tidy/modernize/UseDefaultMemberInitCheck.cpp
clang-tidy/modernize/UseDefaultMemberInitCheck.h
unittests/clang-tidy/CMakeLists.txt
unittests/clang-tidy/ModernizerModuleTest.cpp
Index: unittests/clang-tidy/ModernizerModuleTest.cpp
===
--- /dev/null
+++ unittests/clang-tidy/ModernizerModuleTest.cpp
@@ -0,0 +1,64 @@
+#include "ClangTidyTest.h"
+#include "modernize/UseDefaultMemberInitCheck.h"
+#include "gtest/gtest.h"
+
+using namespace clang::tidy::modernize;
+
+namespace clang {
+namespace tidy {
+namespace test {
+
+TEST(UseDefaultMemberInitCheckTest, NoChanges) {
+ EXPECT_NO_CHANGES(
+ UseDefaultMemberInitCheck,
+ "struct S { S() = default; bool a_ = false; bool b_ = false; };");
+ EXPECT_NO_CHANGES(UseDefaultMemberInitCheck, "struct S { S() : a_(true), "
+ "b_(true) {} bool a_{false}; "
+ "bool b_{false}; };");
+}
+
+TEST(UseDefaultMemberInitCheckTest, Basic) {
+ EXPECT_EQ("struct S { S() {} bool a_{false}; };",
+runCheckOnCode(
+"struct S { S() : a_(false) {} bool a_; };"));
+}
+
+TEST(UseDefaultMemberInitCheckTest, SeveralInitializers) {
+ EXPECT_EQ(
+ "struct S { S() {} bool a_{false}; bool b_{true}; };",
+ runCheckOnCode(
+ "struct S { S() : a_(false), b_(true) {} bool a_; bool b_; };"));
+}
+
+TEST(UseDefaultMemberInitCheckTest, ExceptSpec) {
+ EXPECT_EQ(
+ "struct S { S() noexcept(true) {} bool a_{false}; bool b_{true}; };",
+ runCheckOnCode(
+ "struct S { S() noexcept(true) : a_(false), b_(true) {} bool a_; "
+ "bool b_; };"));
+ EXPECT_EQ(
+ "#define NOEXCEPT_(X) noexcept(X)\n"
+ "struct S { S() NOEXCEPT_(true) {} bool a_{false}; bool b_{true}; };",
+ runCheckOnCode(
+ "#define NOEXCEPT_(X) noexcept(X)\n"
+ "struct S { S() NOEXCEPT_(true) : a_(false), b_(true) {} bool a_; "
+ "bool b_; };"));
+}
+
+TEST(UseDefaultMemberInitCheckTest, OnExisting) {
+ EXPECT_EQ("struct S { S() {} bool a_{false}; bool b_{true}; };",
+runCheckOnCode(
+"struct S { S() : a_(false), b_(true) {} bool a_{false}; bool "
+"b_{true}; };"));
+ EXPECT_EQ("struct S { S() : a_(true) {} bool a_{false}; bool b_{true}; };",
+runCheckOnCode(
+"struct S { S() : a_(true), b_(true) {} bool a_{false}; bool "
+"b_{true}; };"));
+ EXPECT_EQ("struct S { S() : b_(false) {} bool a_{false}; bool b_{true}; };",
+runCheckOnCode(
+"struct S { S() : a_(false), b_(false) {} bool a_{false}; bool "
+"b_{true}; };"));
+}
+} // namespace test
+} // namespace tidy
+} // namespace clang
Index: unittests/clang-tidy/CMakeLists.txt
===
--- unittests/clang-tidy/CMakeLists.txt
+++ unittests/clang-tidy/CMakeLists.txt
@@ -12,6 +12,7 @@
IncludeInserterTest.cpp
GoogleModuleTest.cpp
LLVMModuleTest.cpp
+ ModernizerModuleTest.cpp
NamespaceAliaserTest.cpp
ObjCModuleTest.cpp
OverlappingReplacementsTest.cpp
@@ -29,6 +30,7 @@
clangTidyAndroidModule
clangTidyGoogleModule
clangTidyLLVMModule
+ clangTidyModernizeModule
clangTidyObjCModule
clangTidyReadabilityModule
clangTidyUtils
Index: clang-tidy/modernize/UseDefaultMemberInitCheck.h
===
--- clang-tidy/modernize/UseDefaultMemberInitCheck.h
+++ clang-tidy/modernize/UseDefaultMemberInitCheck.h
@@ -31,12 +31,18 @@
private:
void checkDefaultInit(const ast_matchers::MatchFinder::MatchResult ,
-const CXXCtorInitializer *Init);
+const CXXCtorInitializer *Init,
+const CXXConstructorDecl *Ctor);
void checkExistingInit(const ast_matchers::MatchFinder::MatchResult ,
- const CXXCtorInitializer *Init);
+ const CXXCtorInitializer *Init,
+ const CXXConstructorDecl *Ctor);
+
+ void