forked from OSchip/llvm-project
[clang-tidy] Add check 'readability-redundant-member-init'
Summary: The check emits a warning if a member-initializer calls the member's default constructor with no arguments. Reviewers: sbenza, alexfh, aaron.ballman Subscribers: modocache, mgorny, Eugene.Zelenko, etienneb, Prazek, hokein, cfe-commits, beanz Differential Revision: https://reviews.llvm.org/D24339 llvm-svn: 284742
This commit is contained in:
parent
039983b915
commit
5c24a1148d
|
@ -16,6 +16,7 @@ add_clang_library(clangTidyReadabilityModule
|
|||
NonConstParameterCheck.cpp
|
||||
ReadabilityTidyModule.cpp
|
||||
RedundantControlFlowCheck.cpp
|
||||
RedundantMemberInitCheck.cpp
|
||||
RedundantStringCStrCheck.cpp
|
||||
RedundantSmartptrGetCheck.cpp
|
||||
RedundantStringInitCheck.cpp
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include "NamedParameterCheck.h"
|
||||
#include "NonConstParameterCheck.h"
|
||||
#include "RedundantControlFlowCheck.h"
|
||||
#include "RedundantMemberInitCheck.h"
|
||||
#include "RedundantSmartptrGetCheck.h"
|
||||
#include "RedundantStringCStrCheck.h"
|
||||
#include "RedundantStringInitCheck.h"
|
||||
|
@ -57,6 +58,8 @@ public:
|
|||
"readability-inconsistent-declaration-parameter-name");
|
||||
CheckFactories.registerCheck<MisplacedArrayIndexCheck>(
|
||||
"readability-misplaced-array-index");
|
||||
CheckFactories.registerCheck<RedundantMemberInitCheck>(
|
||||
"readability-redundant-member-init");
|
||||
CheckFactories.registerCheck<StaticDefinitionInAnonymousNamespaceCheck>(
|
||||
"readability-static-definition-in-anonymous-namespace");
|
||||
CheckFactories.registerCheck<readability::NamedParameterCheck>(
|
||||
|
|
|
@ -0,0 +1,65 @@
|
|||
//===--- RedundantMemberInitCheck.cpp - clang-tidy-------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "RedundantMemberInitCheck.h"
|
||||
#include "clang/AST/ASTContext.h"
|
||||
#include "clang/ASTMatchers/ASTMatchFinder.h"
|
||||
#include "clang/Lex/Lexer.h"
|
||||
#include "../utils/Matchers.h"
|
||||
#include <algorithm>
|
||||
|
||||
using namespace clang::ast_matchers;
|
||||
using namespace clang::tidy::matchers;
|
||||
|
||||
namespace clang {
|
||||
namespace tidy {
|
||||
namespace readability {
|
||||
|
||||
void RedundantMemberInitCheck::registerMatchers(MatchFinder *Finder) {
|
||||
auto Construct =
|
||||
cxxConstructExpr(
|
||||
hasDeclaration(cxxConstructorDecl(hasParent(
|
||||
cxxRecordDecl(unless(isTriviallyDefaultConstructible()))))))
|
||||
.bind("construct");
|
||||
|
||||
Finder->addMatcher(
|
||||
cxxConstructorDecl(
|
||||
unless(isDelegatingConstructor()),
|
||||
ofClass(unless(
|
||||
anyOf(isUnion(), ast_matchers::isTemplateInstantiation()))),
|
||||
forEachConstructorInitializer(
|
||||
cxxCtorInitializer(isWritten(),
|
||||
withInitializer(ignoringImplicit(Construct)),
|
||||
unless(forField(hasType(isConstQualified()))))
|
||||
.bind("init"))),
|
||||
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 (Construct->getNumArgs() == 0 ||
|
||||
Construct->getArg(0)->isDefaultArgument()) {
|
||||
if (Init->isAnyMemberInitializer()) {
|
||||
diag(Init->getSourceLocation(), "initializer for member %0 is redundant")
|
||||
<< Init->getMember()
|
||||
<< FixItHint::CreateRemoval(Init->getSourceRange());
|
||||
} else {
|
||||
diag(Init->getSourceLocation(),
|
||||
"initializer for base class %0 is redundant")
|
||||
<< Init->getTypeSourceInfo()->getType()
|
||||
<< FixItHint::CreateRemoval(Init->getSourceRange());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace readability
|
||||
} // namespace tidy
|
||||
} // namespace clang
|
|
@ -0,0 +1,36 @@
|
|||
//===--- RedundantMemberInitCheck.h - clang-tidy----------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_REDUNDANT_MEMBER_INIT_H
|
||||
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_REDUNDANT_MEMBER_INIT_H
|
||||
|
||||
#include "../ClangTidy.h"
|
||||
|
||||
namespace clang {
|
||||
namespace tidy {
|
||||
namespace readability {
|
||||
|
||||
/// Finds member initializations that are unnecessary because the same default
|
||||
/// constructor would be called if they were not present.
|
||||
///
|
||||
/// For the user-facing documentation see:
|
||||
/// http://clang.llvm.org/extra/clang-tidy/checks/readability-redundant-member-init.html
|
||||
class RedundantMemberInitCheck : public ClangTidyCheck {
|
||||
public:
|
||||
RedundantMemberInitCheck(StringRef Name, ClangTidyContext *Context)
|
||||
: ClangTidyCheck(Name, Context) {}
|
||||
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
|
||||
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
|
||||
};
|
||||
|
||||
} // namespace readability
|
||||
} // namespace tidy
|
||||
} // namespace clang
|
||||
|
||||
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_REDUNDANT_MEMBER_INIT_H
|
|
@ -111,6 +111,12 @@ Improvements to clang-tidy
|
|||
Flags function parameters of a pointer type that could be changed to point to
|
||||
a constant type instead.
|
||||
|
||||
- New `readability-redundant-member-init
|
||||
<http://clang.llvm.org/extra/clang-tidy/checks/readability-redundant-member-init.html>`_ check
|
||||
|
||||
Flags member initializations that are unnecessary because the same default
|
||||
constructor would be called if they were not present.
|
||||
|
||||
Fixed bugs:
|
||||
|
||||
- `modernize-make-unique
|
||||
|
|
|
@ -134,6 +134,7 @@ Clang-Tidy Checks
|
|||
readability-named-parameter
|
||||
readability-non-const-parameter
|
||||
readability-redundant-control-flow
|
||||
readability-redundant-member-init
|
||||
readability-redundant-smartptr-get
|
||||
readability-redundant-string-cstr
|
||||
readability-redundant-string-init
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
.. title:: clang-tidy - readability-redundant-member-init
|
||||
|
||||
readability-redundant-member-init
|
||||
=================================
|
||||
|
||||
Finds member initializations that are unnecessary because the same default
|
||||
constructor would be called if they were not present.
|
||||
|
||||
Example:
|
||||
|
||||
.. code-block:: c++
|
||||
|
||||
// Explicitly initializing the member s is unnecessary.
|
||||
class Foo {
|
||||
public:
|
||||
Foo() : s() {}
|
||||
|
||||
private:
|
||||
std::string s;
|
||||
};
|
|
@ -0,0 +1,181 @@
|
|||
// RUN: %check_clang_tidy %s readability-redundant-member-init %t
|
||||
|
||||
struct S {
|
||||
S() = default;
|
||||
S(int i) : i(i) {}
|
||||
int i = 1;
|
||||
};
|
||||
|
||||
struct T {
|
||||
T(int i = 1) : i(i) {}
|
||||
int i;
|
||||
};
|
||||
|
||||
struct U {
|
||||
int i;
|
||||
};
|
||||
|
||||
union V {
|
||||
int i;
|
||||
double f;
|
||||
};
|
||||
|
||||
// Initializer calls default constructor
|
||||
struct F1 {
|
||||
F1() : f() {}
|
||||
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: initializer for member 'f' is redundant
|
||||
// CHECK-FIXES: F1() {}
|
||||
S f;
|
||||
};
|
||||
|
||||
// Initializer calls default constructor with default argument
|
||||
struct F2 {
|
||||
F2() : f() {}
|
||||
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: initializer for member 'f' is redundant
|
||||
// CHECK-FIXES: F2() {}
|
||||
T f;
|
||||
};
|
||||
|
||||
// Multiple redundant initializers for same constructor
|
||||
struct F3 {
|
||||
F3() : f(), g(1), h() {}
|
||||
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: initializer for member 'f' is redundant
|
||||
// CHECK-MESSAGES: :[[@LINE-2]]:21: warning: initializer for member 'h' is redundant
|
||||
// CHECK-FIXES: F3() : g(1) {}
|
||||
S f, g, h;
|
||||
};
|
||||
|
||||
// Templated class independent type
|
||||
template <class V>
|
||||
struct F4 {
|
||||
F4() : f() {}
|
||||
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: initializer for member 'f' is redundant
|
||||
// CHECK-FIXES: F4() {}
|
||||
S f;
|
||||
};
|
||||
F4<int> f4i;
|
||||
F4<S> f4s;
|
||||
|
||||
// Base class
|
||||
struct F5 : S {
|
||||
F5() : S() {}
|
||||
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: initializer for base class 'S' is redundant
|
||||
// CHECK-FIXES: F5() {}
|
||||
};
|
||||
|
||||
// Constructor call requires cleanup
|
||||
struct Cleanup {
|
||||
~Cleanup() {}
|
||||
};
|
||||
|
||||
struct UsesCleanup {
|
||||
UsesCleanup(const Cleanup &c = Cleanup()) {}
|
||||
};
|
||||
|
||||
struct F6 {
|
||||
F6() : uc() {}
|
||||
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: initializer for member 'uc' is redundant
|
||||
// CHECK-FIXES: F6() {}
|
||||
UsesCleanup uc;
|
||||
};
|
||||
|
||||
// Multiple inheritance
|
||||
struct F7 : S, T {
|
||||
F7() : S(), T() {}
|
||||
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: initializer for base class 'S' is redundant
|
||||
// CHECK-MESSAGES: :[[@LINE-2]]:15: warning: initializer for base class 'T' is redundant
|
||||
// CHECK-FIXES: F7() {}
|
||||
};
|
||||
|
||||
// Initializer not written
|
||||
struct NF1 {
|
||||
NF1() {}
|
||||
S f;
|
||||
};
|
||||
|
||||
// Initializer doesn't call default constructor
|
||||
struct NF2 {
|
||||
NF2() : f(1) {}
|
||||
S f;
|
||||
};
|
||||
|
||||
// Initializer calls default constructor without using default argument
|
||||
struct NF3 {
|
||||
NF3() : f(1) {}
|
||||
T f;
|
||||
};
|
||||
|
||||
// Initializer calls default constructor without using default argument
|
||||
struct NF4 {
|
||||
NF4() : f(2) {}
|
||||
T f;
|
||||
};
|
||||
|
||||
// Initializer is zero-initialization
|
||||
struct NF5 {
|
||||
NF5() : i() {}
|
||||
int i;
|
||||
};
|
||||
|
||||
// Initializer is direct-initialization
|
||||
struct NF6 {
|
||||
NF6() : i(1) {}
|
||||
int i;
|
||||
};
|
||||
|
||||
// Initializer is aggregate initialization of struct
|
||||
struct NF7 {
|
||||
NF7() : f{} {}
|
||||
U f;
|
||||
};
|
||||
|
||||
// Initializer is zero-initialization of struct
|
||||
struct NF7b {
|
||||
NF7b() : f() {}
|
||||
U f;
|
||||
};
|
||||
|
||||
// Initializer is aggregate initialization of array
|
||||
struct NF8 {
|
||||
NF8() : f{} {}
|
||||
int f[2];
|
||||
};
|
||||
|
||||
struct NF9 {
|
||||
NF9() : f{} {}
|
||||
S f[2];
|
||||
};
|
||||
|
||||
// Initializing member of union
|
||||
union NF10 {
|
||||
NF10() : s() {}
|
||||
int i;
|
||||
S s;
|
||||
};
|
||||
|
||||
// Templated class dependent type
|
||||
template <class V>
|
||||
struct NF11 {
|
||||
NF11() : f() {}
|
||||
V f;
|
||||
};
|
||||
NF11<int> nf11i;
|
||||
NF11<S> nf11s;
|
||||
|
||||
// Delegating constructor
|
||||
class NF12 {
|
||||
NF12() = default;
|
||||
NF12(int) : NF12() {}
|
||||
};
|
||||
|
||||
// Const member
|
||||
struct NF13 {
|
||||
NF13() : f() {}
|
||||
const S f;
|
||||
};
|
||||
|
||||
// Union member
|
||||
struct NF14 {
|
||||
NF14() : f() {}
|
||||
V f;
|
||||
};
|
Loading…
Reference in New Issue