llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang-tidy Author: Piotr Zegar (PiotrZSL) <details> <summary>Changes</summary> Support detecting redundant in-class initializers. Moved from https://reviews.llvm.org/D157262 Fixes: #<!-- -->62525 --- Full diff: https://github.com/llvm/llvm-project/pull/77206.diff 4 Files Affected: - (modified) clang-tools-extra/clang-tidy/readability/RedundantMemberInitCheck.cpp (+51-22) - (modified) clang-tools-extra/docs/ReleaseNotes.rst (+5-1) - (modified) clang-tools-extra/docs/clang-tidy/checks/readability/redundant-member-init.rst (+2-1) - (modified) clang-tools-extra/test/clang-tidy/checkers/readability/redundant-member-init.cpp (+52) ``````````diff diff --git a/clang-tools-extra/clang-tidy/readability/RedundantMemberInitCheck.cpp b/clang-tools-extra/clang-tidy/readability/RedundantMemberInitCheck.cpp index b5d407773bb732..015347ee9294ce 100644 --- a/clang-tools-extra/clang-tidy/readability/RedundantMemberInitCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/RedundantMemberInitCheck.cpp @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// #include "RedundantMemberInitCheck.h" +#include "../utils/LexerUtils.h" #include "../utils/Matchers.h" #include "clang/AST/ASTContext.h" #include "clang/ASTMatchers/ASTMatchFinder.h" @@ -18,33 +19,64 @@ using namespace clang::tidy::matchers; namespace clang::tidy::readability { +static SourceRange +getFullInitRangeInclWhitespaces(SourceRange Range, const SourceManager &SM, + const LangOptions &LangOpts) { + const Token PrevToken = + utils::lexer::getPreviousToken(Range.getBegin(), SM, LangOpts, false); + if (PrevToken.is(tok::unknown)) + return Range; + + if (PrevToken.isNot(tok::equal)) + return {PrevToken.getEndLoc(), Range.getEnd()}; + + return getFullInitRangeInclWhitespaces( + {PrevToken.getLocation(), Range.getEnd()}, SM, LangOpts); +} + void RedundantMemberInitCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) { Options.store(Opts, "IgnoreBaseInCopyConstructors", IgnoreBaseInCopyConstructors); } void RedundantMemberInitCheck::registerMatchers(MatchFinder *Finder) { + auto ConstructorMatcher = + cxxConstructExpr(argumentCountIs(0), + hasDeclaration(cxxConstructorDecl(ofClass(cxxRecordDecl( + unless(isTriviallyDefaultConstructible())))))) + .bind("construct"); + Finder->addMatcher( cxxConstructorDecl( unless(isDelegatingConstructor()), ofClass(unless(isUnion())), forEachConstructorInitializer( - cxxCtorInitializer( - withInitializer( - cxxConstructExpr( - hasDeclaration( - cxxConstructorDecl(ofClass(cxxRecordDecl( - unless(isTriviallyDefaultConstructible())))))) - .bind("construct")), - unless(forField(hasType(isConstQualified()))), - unless(forField(hasParent(recordDecl(isUnion()))))) + cxxCtorInitializer(withInitializer(ConstructorMatcher), + unless(forField(fieldDecl( + anyOf(hasType(isConstQualified()), + hasParent(recordDecl(isUnion()))))))) .bind("init"))) .bind("constructor"), this); + + Finder->addMatcher(fieldDecl(hasInClassInitializer(ConstructorMatcher), + unless(hasParent(recordDecl(isUnion())))) + .bind("field"), + this); } void RedundantMemberInitCheck::check(const MatchFinder::MatchResult &Result) { - const auto *Init = Result.Nodes.getNodeAs<CXXCtorInitializer>("init"); const auto *Construct = Result.Nodes.getNodeAs<CXXConstructExpr>("construct"); + + if (const auto *Field = Result.Nodes.getNodeAs<FieldDecl>("field")) { + const Expr *Init = Field->getInClassInitializer(); + diag(Construct->getExprLoc(), "initializer for member %0 is redundant") + << Field + << FixItHint::CreateRemoval(getFullInitRangeInclWhitespaces( + Init->getSourceRange(), *Result.SourceManager, getLangOpts())); + return; + } + + const auto *Init = Result.Nodes.getNodeAs<CXXCtorInitializer>("init"); const auto *ConstructorDecl = Result.Nodes.getNodeAs<CXXConstructorDecl>("constructor"); @@ -52,18 +84,15 @@ void RedundantMemberInitCheck::check(const MatchFinder::MatchResult &Result) { Init->isBaseInitializer()) return; - if (Construct->getNumArgs() == 0 || - Construct->getArg(0)->isDefaultArgument()) { - if (Init->isAnyMemberInitializer()) { - diag(Init->getSourceLocation(), "initializer for member %0 is redundant") - << Init->getAnyMember() - << FixItHint::CreateRemoval(Init->getSourceRange()); - } else { - diag(Init->getSourceLocation(), - "initializer for base class %0 is redundant") - << Construct->getType() - << FixItHint::CreateRemoval(Init->getSourceRange()); - } + if (Init->isAnyMemberInitializer()) { + diag(Init->getSourceLocation(), "initializer for member %0 is redundant") + << Init->getAnyMember() + << FixItHint::CreateRemoval(Init->getSourceRange()); + } else { + diag(Init->getSourceLocation(), + "initializer for base class %0 is redundant") + << Construct->getType() + << FixItHint::CreateRemoval(Init->getSourceRange()); } } diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index 1bd5a72126c10b..8ec3dcadc6ebe7 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -119,7 +119,7 @@ Improvements to clang-tidy - Improved `--dump-config` to print check options in alphabetical order. -- Improved :program:`clang-tidy-diff.py` script. +- Improved :program:`clang-tidy-diff.py` script. * Return exit code `1` if any :program:`clang-tidy` subprocess exits with a non-zero code or if exporting fixes fails. @@ -487,6 +487,10 @@ Changes in existing checks <clang-tidy/checks/readability/non-const-parameter>` check to ignore false-positives in initializer list of record. +- Improved :doc:`readability-redundant-member-init + <clang-tidy/checks/readability/redundant-member-init>` check to support + in-class initializers. + - Improved :doc:`readability-simplify-subscript-expr <clang-tidy/checks/readability/simplify-subscript-expr>` check by extending the default value of the `Types` option to include ``std::span``. diff --git a/clang-tools-extra/docs/clang-tidy/checks/readability/redundant-member-init.rst b/clang-tools-extra/docs/clang-tidy/checks/readability/redundant-member-init.rst index b2f86c4429cc51..c26aaf73b16f85 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/readability/redundant-member-init.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/readability/redundant-member-init.rst @@ -11,13 +11,14 @@ Example .. code-block:: c++ - // Explicitly initializing the member s is unnecessary. + // Explicitly initializing the member s and v is unnecessary. class Foo { public: Foo() : s() {} private: std::string s; + std::vector<int> v {}; }; Options diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-member-init.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-member-init.cpp index d8ca406581a385..17b2714abca07b 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-member-init.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-member-init.cpp @@ -250,3 +250,55 @@ struct NF15 { S s2; }; }; + +// Direct in-class initialization with default constructor +struct D1 { + S f1 {}; + // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: initializer for member 'f1' is redundant + // CHECK-FIXES: S f1; +}; + +// Direct in-class initialization with constructor with default argument +struct D2 { + T f2 {}; + // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: initializer for member 'f2' is redundant + // CHECK-FIXES: T f2; +}; + +// Direct in-class initialization with default constructor (assign) +struct D3 { + S f3 = {}; + // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: initializer for member 'f3' is redundant + // CHECK-FIXES: S f3; +}; + +// Direct in-class initialization with constructor with default argument (assign) +struct D4 { + T f4 = {}; + // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: initializer for member 'f4' is redundant + // CHECK-FIXES: T f4; +}; + +// Templated class independent type +template <class V> +struct D5 { + S f5 /*comment*/ = S(); + // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: initializer for member 'f5' is redundant + // CHECK-FIXES: S f5 /*comment*/; +}; +D5<int> d5i; +D5<S> d5s; + +struct D6 { + UsesCleanup uc2{}; + // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: initializer for member 'uc2' is redundant + // CHECK-FIXES: UsesCleanup uc2; +}; + +template<typename V> +struct D7 { + V f7; +}; + +D7<int> d7i; +D7<S> d7s; `````````` </details> https://github.com/llvm/llvm-project/pull/77206 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits