blob: 8409f9f40d265d375aa13fd72b8ea7aa29bb30b2 [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)),
Malcolm Parsons2f9684332017-08-01 09:54:05 +000042 unless(forField(hasType(isConstQualified()))),
43 unless(forField(hasParent(recordDecl(isUnion())))))
Malcolm Parsons5c24a112016-10-20 16:08:03 +000044 .bind("init"))),
45 this);
46}
47
48void RedundantMemberInitCheck::check(const MatchFinder::MatchResult &Result) {
49 const auto *Init = Result.Nodes.getNodeAs<CXXCtorInitializer>("init");
50 const auto *Construct = Result.Nodes.getNodeAs<CXXConstructExpr>("construct");
51
52 if (Construct->getNumArgs() == 0 ||
53 Construct->getArg(0)->isDefaultArgument()) {
54 if (Init->isAnyMemberInitializer()) {
55 diag(Init->getSourceLocation(), "initializer for member %0 is redundant")
Malcolm Parsons2f9684332017-08-01 09:54:05 +000056 << Init->getAnyMember()
Malcolm Parsons5c24a112016-10-20 16:08:03 +000057 << FixItHint::CreateRemoval(Init->getSourceRange());
58 } else {
59 diag(Init->getSourceLocation(),
60 "initializer for base class %0 is redundant")
Malcolm Parsons49fe4032016-11-15 17:49:00 +000061 << Construct->getType()
Malcolm Parsons5c24a112016-10-20 16:08:03 +000062 << FixItHint::CreateRemoval(Init->getSourceRange());
63 }
64 }
65}
66
67} // namespace readability
68} // namespace tidy
69} // namespace clang