[clang-tidy] Handle anonymous structs/unions in member init checks.
authorMalcolm Parsons <malcolm.parsons@gmail.com>
Tue, 1 Aug 2017 09:54:05 +0000 (09:54 +0000)
committerMalcolm Parsons <malcolm.parsons@gmail.com>
Tue, 1 Aug 2017 09:54:05 +0000 (09:54 +0000)
Use getAnyMember() instead of getMember() to avoid crash on anonymous
structs/unions.
Don't warn about initializing members of an anonymous union.

Fixes PR32966.

Reviewed by alexfh.

llvm-svn: 309668

clang-tools-extra/clang-tidy/modernize/UseDefaultMemberInitCheck.cpp
clang-tools-extra/clang-tidy/readability/RedundantMemberInitCheck.cpp
clang-tools-extra/test/clang-tidy/modernize-use-default-member-init.cpp
clang-tools-extra/test/clang-tidy/readability-redundant-member-init.cpp

index 67a2c3d..b07f730 100644 (file)
@@ -166,21 +166,22 @@ void UseDefaultMemberInitCheck::registerMatchers(MatchFinder *Finder) {
       cxxConstructorDecl(
           isDefaultConstructor(), unless(isInstantiated()),
           forEachConstructorInitializer(
-              allOf(forField(unless(anyOf(isBitField(),
-                                          hasInClassInitializer(anything())))),
-                    cxxCtorInitializer(isWritten(),
-                                       withInitializer(ignoringImplicit(Init)))
-                        .bind("default")))),
+              cxxCtorInitializer(
+                  forField(unless(anyOf(isBitField(),
+                                        hasInClassInitializer(anything()),
+                                        hasParent(recordDecl(isUnion()))))),
+                  isWritten(), withInitializer(ignoringImplicit(Init)))
+                  .bind("default"))),
       this);
 
   Finder->addMatcher(
       cxxConstructorDecl(
           unless(ast_matchers::isTemplateInstantiation()),
           forEachConstructorInitializer(
-              allOf(forField(hasInClassInitializer(anything())),
-                    cxxCtorInitializer(isWritten(),
-                                       withInitializer(ignoringImplicit(Init)))
-                        .bind("existing")))),
+              cxxCtorInitializer(forField(hasInClassInitializer(anything())),
+                                 isWritten(),
+                                 withInitializer(ignoringImplicit(Init)))
+                  .bind("existing"))),
       this);
 }
 
@@ -197,7 +198,7 @@ void UseDefaultMemberInitCheck::check(const MatchFinder::MatchResult &Result) {
 
 void UseDefaultMemberInitCheck::checkDefaultInit(
     const MatchFinder::MatchResult &Result, const CXXCtorInitializer *Init) {
-  const FieldDecl *Field = Init->getMember();
+  const FieldDecl *Field = Init->getAnyMember();
 
   SourceLocation StartLoc = Field->getLocStart();
   if (StartLoc.isMacroID() && IgnoreMacros)
index 6d36500..8409f9f 100644 (file)
@@ -39,7 +39,8 @@ void RedundantMemberInitCheck::registerMatchers(MatchFinder *Finder) {
           forEachConstructorInitializer(
               cxxCtorInitializer(isWritten(),
                                  withInitializer(ignoringImplicit(Construct)),
-                                 unless(forField(hasType(isConstQualified()))))
+                                 unless(forField(hasType(isConstQualified()))),
+                                 unless(forField(hasParent(recordDecl(isUnion())))))
                   .bind("init"))),
       this);
 }
@@ -52,7 +53,7 @@ void RedundantMemberInitCheck::check(const MatchFinder::MatchResult &Result) {
       Construct->getArg(0)->isDefaultArgument()) {
     if (Init->isAnyMemberInitializer()) {
       diag(Init->getSourceLocation(), "initializer for member %0 is redundant")
-          << Init->getMember()
+          << Init->getAnyMember()
           << FixItHint::CreateRemoval(Init->getSourceRange());
     } else {
       diag(Init->getSourceLocation(),
index 5b9b93c..0ed65df 100644 (file)
@@ -173,6 +173,16 @@ struct PositiveString {
   // CHECK-FIXES: const char *s{"foo"};
 };
 
+struct PositiveStruct {
+  PositiveStruct() : s(7) {}
+  // CHECK-FIXES: PositiveStruct()  {}
+  struct {
+    int s;
+    // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use default member initializer for 's'
+    // CHECK-FIXES: int s{7};
+  };
+};
+
 template <typename T>
 struct NegativeTemplate {
     NegativeTemplate() : t() {}
index f15cb1b..90b52fd 100644 (file)
@@ -105,6 +105,17 @@ struct F8 : Foo::Template<N_THINGS> {
   // CHECK-FIXES: F8()  {}
 };
 
+// Anonymous struct
+struct F9 {
+  F9() : s1() {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: initializer for member 's1' is redundant
+  // CHECK-FIXES: F9()  {}
+  struct {
+    S s1;
+    S s2;
+  };
+};
+
 // Initializer not written
 struct NF1 {
   NF1() {}
@@ -197,3 +208,12 @@ struct NF14 {
   NF14() : f() {}
   V f;
 };
+
+// Anonymous union member
+struct NF15 {
+  NF15() : s1() {}
+  union {
+    S s1;
+    S s2;
+  };
+};