blob: 6d3650059d440198ae595762cc537bca8b5aee0d [file] [log] [blame]
Malcolm Parsons5c24a112016-10-20 16:08:03 +00001//===--- RedundantMemberInitCheck.cpp - clang-tidy-------------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "RedundantMemberInitCheck.h"
Mandeep Singh Grang7c7ea7d2016-11-08 07:50:19 +000011#include "../utils/Matchers.h"
Malcolm Parsons5c24a112016-10-20 16:08:03 +000012#include "clang/AST/ASTContext.h"
13#include "clang/ASTMatchers/ASTMatchFinder.h"
14#include "clang/Lex/Lexer.h"
Malcolm Parsons5c24a112016-10-20 16:08:03 +000015#include <algorithm>
16
17using namespace clang::ast_matchers;
18using namespace clang::tidy::matchers;
19
20namespace clang {
21namespace tidy {
22namespace readability {
23
24void RedundantMemberInitCheck::registerMatchers(MatchFinder *Finder) {
Malcolm Parsons51bfe422016-12-27 22:14:40 +000025 if (!getLangOpts().CPlusPlus)
26 return;
27
Malcolm Parsons5c24a112016-10-20 16:08:03 +000028 auto Construct =
29 cxxConstructExpr(
30 hasDeclaration(cxxConstructorDecl(hasParent(
31 cxxRecordDecl(unless(isTriviallyDefaultConstructible()))))))
32 .bind("construct");
33
34 Finder->addMatcher(
35 cxxConstructorDecl(
36 unless(isDelegatingConstructor()),
37 ofClass(unless(
38 anyOf(isUnion(), ast_matchers::isTemplateInstantiation()))),
39 forEachConstructorInitializer(
40 cxxCtorInitializer(isWritten(),
41 withInitializer(ignoringImplicit(Construct)),
42 unless(forField(hasType(isConstQualified()))))
43 .bind("init"))),
44 this);
45}
46
47void RedundantMemberInitCheck::check(const MatchFinder::MatchResult &Result) {
48 const auto *Init = Result.Nodes.getNodeAs<CXXCtorInitializer>("init");
49 const auto *Construct = Result.Nodes.getNodeAs<CXXConstructExpr>("construct");
50
51 if (Construct->getNumArgs() == 0 ||
52 Construct->getArg(0)->isDefaultArgument()) {
53 if (Init->isAnyMemberInitializer()) {
54 diag(Init->getSourceLocation(), "initializer for member %0 is redundant")
55 << Init->getMember()
56 << FixItHint::CreateRemoval(Init->getSourceRange());
57 } else {
58 diag(Init->getSourceLocation(),
59 "initializer for base class %0 is redundant")
Malcolm Parsons49fe4032016-11-15 17:49:00 +000060 << Construct->getType()
Malcolm Parsons5c24a112016-10-20 16:08:03 +000061 << FixItHint::CreateRemoval(Init->getSourceRange());
62 }
63 }
64}
65
66} // namespace readability
67} // namespace tidy
68} // namespace clang