1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
16 #include "config_clang.h"
21 the comma operator is best used sparingly
26 Stmt
const * lookThroughExprWithCleanups(Stmt
const * stmt
) {
27 if (auto const e
= dyn_cast_or_null
<ExprWithCleanups
>(stmt
)) {
28 return e
->getSubExpr();
34 public loplugin::FilteringPlugin
<CommaOperator
>
37 explicit CommaOperator(loplugin::InstantiationData
const & data
):
38 FilteringPlugin(data
) {}
40 virtual void run() override
42 TraverseDecl(compiler
.getASTContext().getTranslationUnitDecl());
45 bool TraverseForStmt(ForStmt
* stmt
) {
46 auto const saved1
= ignore1_
;
47 ignore1_
= lookThroughExprWithCleanups(stmt
->getInit());
48 auto const saved2
= ignore2_
;
49 ignore2_
= lookThroughExprWithCleanups(stmt
->getInc());
50 auto const ret
= RecursiveASTVisitor::TraverseForStmt(stmt
);
56 bool TraverseWhileStmt(WhileStmt
* stmt
) {
57 auto const saved1
= ignore1_
;
58 ignore1_
= lookThroughExprWithCleanups(stmt
->getCond());
59 auto const ret
= RecursiveASTVisitor::TraverseWhileStmt(stmt
);
64 bool TraverseParenExpr(ParenExpr
* expr
) {
65 auto const saved1
= ignore1_
;
66 ignore1_
= expr
->getSubExpr();
67 auto const ret
= RecursiveASTVisitor::TraverseParenExpr(expr
);
72 bool TraverseBinaryOperator(BinaryOperator
* expr
) {
73 if (expr
->getOpcode() != BO_Comma
) {
74 return RecursiveASTVisitor::TraverseBinaryOperator(expr
);
76 if (!WalkUpFromBinaryOperator(expr
)) {
79 auto const saved1
= ignore1_
;
80 ignore1_
= expr
->getLHS();
81 auto const ret
= TraverseStmt(expr
->getLHS())
82 && TraverseStmt(expr
->getRHS());
87 #if CLANG_VERSION < 110000
88 bool TraverseBinComma(BinaryOperator
* expr
) { return TraverseBinaryOperator(expr
); }
91 bool VisitBinaryOperator(const BinaryOperator
* );
94 Stmt
const * ignore1_
= nullptr;
95 Stmt
const * ignore2_
= nullptr;
98 bool CommaOperator::VisitBinaryOperator(const BinaryOperator
* binaryOp
)
100 if (binaryOp
->getOpcode() != BO_Comma
) {
103 if (binaryOp
== ignore1_
|| binaryOp
== ignore2_
) {
106 if (ignoreLocation(binaryOp
)) {
109 // Ignore FD_SET expanding to "...} while(0, 0)" in some Microsoft
110 // winsock2.h (TODO: improve heuristic of determining that the whole
111 // binaryOp is part of a single macro body expansion):
112 if (compiler
.getSourceManager().isMacroBodyExpansion(
113 compat::getBeginLoc(binaryOp
))
114 && compiler
.getSourceManager().isMacroBodyExpansion(
115 binaryOp
->getOperatorLoc())
116 && compiler
.getSourceManager().isMacroBodyExpansion(
117 compat::getEndLoc(binaryOp
))
119 compiler
.getSourceManager().getSpellingLoc(
120 binaryOp
->getOperatorLoc())))
125 DiagnosticsEngine::Warning
, "comma operator hides code",
126 binaryOp
->getOperatorLoc())
127 << binaryOp
->getSourceRange();
132 loplugin::Plugin::Registration
< CommaOperator
> X("commaoperator", true);
136 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */