1//===--- RedundantMemberInitCheck.cpp - clang-tidy-------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "RedundantMemberInitCheck.h"
10#include "../utils/LexerUtils.h"
11#include "../utils/Matchers.h"
12#include "clang/AST/ASTContext.h"
13#include "clang/ASTMatchers/ASTMatchFinder.h"
14#include "clang/Lex/Lexer.h"
15
16using namespace clang::ast_matchers;
17using namespace clang::tidy::matchers;
18
19namespace clang::tidy::readability {
20
21static SourceRange
22getFullInitRangeInclWhitespaces(SourceRange Range, const SourceManager &SM,
23 const LangOptions &LangOpts) {
24 const Token PrevToken =
25 utils::lexer::getPreviousToken(Location: Range.getBegin(), SM, LangOpts, SkipComments: false);
26 if (PrevToken.is(K: tok::unknown))
27 return Range;
28
29 if (PrevToken.isNot(K: tok::equal))
30 return {PrevToken.getEndLoc(), Range.getEnd()};
31
32 return getFullInitRangeInclWhitespaces(
33 Range: {PrevToken.getLocation(), Range.getEnd()}, SM, LangOpts);
34}
35
36void RedundantMemberInitCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
37 Options.store(Options&: Opts, LocalName: "IgnoreBaseInCopyConstructors",
38 Value: IgnoreBaseInCopyConstructors);
39}
40
41void RedundantMemberInitCheck::registerMatchers(MatchFinder *Finder) {
42 auto ConstructorMatcher =
43 cxxConstructExpr(
44 argumentCountIs(N: 0),
45 hasDeclaration(InnerMatcher: cxxConstructorDecl(
46 ofClass(InnerMatcher: cxxRecordDecl(unless(isTriviallyDefaultConstructible()))
47 .bind(ID: "class")))))
48 .bind(ID: "construct");
49
50 auto HasUnionAsParent = hasParent(recordDecl(isUnion()));
51
52 auto HasTypeEqualToConstructorClass = hasType(InnerMatcher: qualType(
53 hasCanonicalType(InnerMatcher: qualType(hasDeclaration(InnerMatcher: equalsBoundNode(ID: "class"))))));
54
55 Finder->addMatcher(
56 NodeMatch: cxxConstructorDecl(
57 unless(isDelegatingConstructor()), ofClass(InnerMatcher: unless(isUnion())),
58 forEachConstructorInitializer(
59 InnerMatcher: cxxCtorInitializer(
60 withInitializer(InnerMatcher: ConstructorMatcher),
61 anyOf(isBaseInitializer(),
62 forField(InnerMatcher: fieldDecl(unless(hasType(InnerMatcher: isConstQualified())),
63 unless(HasUnionAsParent),
64 HasTypeEqualToConstructorClass))))
65 .bind(ID: "init")))
66 .bind(ID: "constructor"),
67 Action: this);
68
69 Finder->addMatcher(NodeMatch: fieldDecl(hasInClassInitializer(InnerMatcher: ConstructorMatcher),
70 HasTypeEqualToConstructorClass,
71 unless(HasUnionAsParent))
72 .bind(ID: "field"),
73 Action: this);
74}
75
76void RedundantMemberInitCheck::check(const MatchFinder::MatchResult &Result) {
77 const auto *Construct = Result.Nodes.getNodeAs<CXXConstructExpr>(ID: "construct");
78
79 if (const auto *Field = Result.Nodes.getNodeAs<FieldDecl>(ID: "field")) {
80 const Expr *Init = Field->getInClassInitializer();
81 diag(Construct->getExprLoc(), "initializer for member %0 is redundant")
82 << Field
83 << FixItHint::CreateRemoval(getFullInitRangeInclWhitespaces(
84 Init->getSourceRange(), *Result.SourceManager, getLangOpts()));
85 return;
86 }
87
88 const auto *Init = Result.Nodes.getNodeAs<CXXCtorInitializer>(ID: "init");
89 const auto *ConstructorDecl =
90 Result.Nodes.getNodeAs<CXXConstructorDecl>(ID: "constructor");
91
92 if (IgnoreBaseInCopyConstructors && ConstructorDecl->isCopyConstructor() &&
93 Init->isBaseInitializer())
94 return;
95
96 if (Init->isAnyMemberInitializer()) {
97 diag(Loc: Init->getSourceLocation(), Description: "initializer for member %0 is redundant")
98 << Init->getAnyMember()
99 << FixItHint::CreateRemoval(RemoveRange: Init->getSourceRange());
100 } else {
101 diag(Loc: Init->getSourceLocation(),
102 Description: "initializer for base class %0 is redundant")
103 << Construct->getType()
104 << FixItHint::CreateRemoval(RemoveRange: Init->getSourceRange());
105 }
106}
107
108} // namespace clang::tidy::readability
109

Provided by KDAB

Privacy Policy
Update your C++ knowledge – Modern C++11/14/17 Training
Find out more

source code of clang-tools-extra/clang-tidy/readability/RedundantMemberInitCheck.cpp