1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 #include "MustUseChecker.h"
6 #include "CustomMatchers.h"
7 #include "CustomTypeAnnotation.h"
9 CustomTypeAnnotation MustUse
=
10 CustomTypeAnnotation(moz_must_use_type
, "must-use");
12 void MustUseChecker::registerMatchers(MatchFinder
*AstMatcher
) {
13 AstMatcher
->addMatcher(switchCase().bind("switchcase"), this);
14 AstMatcher
->addMatcher(compoundStmt().bind("compound"), this);
15 AstMatcher
->addMatcher(ifStmt().bind("if"), this);
16 AstMatcher
->addMatcher(whileStmt().bind("while"), this);
17 AstMatcher
->addMatcher(doStmt().bind("do"), this);
18 AstMatcher
->addMatcher(forStmt().bind("for"), this);
19 AstMatcher
->addMatcher(binaryOperator(binaryCommaOperator()).bind("bin"),
23 void MustUseChecker::check(const MatchFinder::MatchResult
&Result
) {
24 if (auto SC
= Result
.Nodes
.getNodeAs
<SwitchCase
>("switchcase")) {
25 handleUnusedExprResult(SC
->getSubStmt());
27 if (auto C
= Result
.Nodes
.getNodeAs
<CompoundStmt
>("compound")) {
28 for (const auto &S
: C
->body()) {
29 handleUnusedExprResult(S
);
32 if (auto IF
= Result
.Nodes
.getNodeAs
<IfStmt
>("if")) {
33 handleUnusedExprResult(IF
->getThen());
34 handleUnusedExprResult(IF
->getElse());
36 if (auto W
= Result
.Nodes
.getNodeAs
<WhileStmt
>("while")) {
37 handleUnusedExprResult(W
->getBody());
39 if (auto D
= Result
.Nodes
.getNodeAs
<DoStmt
>("do")) {
40 handleUnusedExprResult(D
->getBody());
42 if (auto F
= Result
.Nodes
.getNodeAs
<ForStmt
>("for")) {
43 handleUnusedExprResult(F
->getBody());
44 handleUnusedExprResult(F
->getInit());
45 handleUnusedExprResult(F
->getInc());
47 if (auto C
= Result
.Nodes
.getNodeAs
<BinaryOperator
>("bin")) {
48 handleUnusedExprResult(C
->getLHS());
52 void MustUseChecker::handleUnusedExprResult(const Stmt
*Statement
) {
53 const Expr
*E
= dyn_cast_or_null
<Expr
>(Statement
);
55 E
= E
->IgnoreImplicit(); // Ignore ExprWithCleanup etc. implicit wrappers
56 QualType T
= E
->getType();
57 if (MustUse
.hasEffectiveAnnotation(T
) && !isIgnoredExprForMustUse(E
)) {
58 diag(E
->getBeginLoc(), "Unused value of must-use type %0",
61 MustUse
.dumpAnnotationReason(*this, T
, E
->getBeginLoc());