djtodoro created this revision. djtodoro added reviewers: shuaiwang, lebedev.ri. Herald added subscribers: Charusso, jdoerfert, dkrupp, donat.nagy, Szelethus, mikhail.ramalho, a.sidorin, szepet, baloghadamsoftware, xazax.hun.
We should track mutation of a variable within a comma operator expression. Current code in `ExprMutationAnalyzer `does not handle it. This will handle cases like: `(a, b) ++` < == `b `is modified `(a, b) = c` < == `b `is modifed https://reviews.llvm.org/D58894 Files: include/clang/AST/Expr.h lib/Analysis/ExprMutationAnalyzer.cpp unittests/Analysis/ExprMutationAnalyzerTest.cpp
Index: unittests/Analysis/ExprMutationAnalyzerTest.cpp =================================================================== --- unittests/Analysis/ExprMutationAnalyzerTest.cpp +++ unittests/Analysis/ExprMutationAnalyzerTest.cpp @@ -881,6 +881,24 @@ EXPECT_FALSE(isMutated(Results, AST.get())); } +TEST(ExprMutationAnalyzerTest, CommaExprWithAnAssigment) { + const auto AST = + buildASTFromCodeWithArgs("void f() { int x; int y; (x, y) = 5; }", + {"-Wno-unused-value"}); + const auto Results = + match(withEnclosingCompound(declRefTo("y")), AST->getASTContext()); + EXPECT_TRUE(isMutated(Results, AST.get())); +} + +TEST(ExprMutationAnalyzerTest, CommaExprWithDecOp) { + const auto AST = + buildASTFromCodeWithArgs("void f() { int x; int y; (x, y)++; }", + {"-Wno-unused-value"}); + const auto Results = + match(withEnclosingCompound(declRefTo("y")), AST->getASTContext()); + EXPECT_TRUE(isMutated(Results, AST.get())); +} + TEST(ExprMutationAnalyzerTest, LambdaDefaultCaptureByValue) { const auto AST = buildASTFromCode("void f() { int x; [=]() { x; }; }"); const auto Results = Index: lib/Analysis/ExprMutationAnalyzer.cpp =================================================================== --- lib/Analysis/ExprMutationAnalyzer.cpp +++ lib/Analysis/ExprMutationAnalyzer.cpp @@ -14,6 +14,42 @@ namespace { +// Assignment on an expression with comma operator. +// Match situations like: +// '(a, b) = c', '(c, (a, b)) = c', etc. +AST_MATCHER_P(BinaryOperator, isAssigmentWithCommma, const Expr *, E) { + if (Node.isAssignmentOp()) { + const Expr* LHSResult = Node.getLHS(); + while (const auto *BOComma = + dyn_cast_or_null<BinaryOperator>(LHSResult->IgnoreParens())) { + if (!BOComma->isCommaOp()) + break; + LHSResult = BOComma->getRHS(); + } + if (LHSResult == E) + return true; + } + return false; +} + +// Increment/Decrement on an expression with comma operator. +// Match situations like: +// '(a, b)++', '(c, (a, b))++', '(a, b)--', etc. +AST_MATCHER_P(UnaryOperator, isIncDecOperandWithComma, const Expr *, E) { + if (Node.isIncrementDecrementOp()) { + const Expr* Result = Node.getSubExpr()->IgnoreParens(); + while (const auto *BOComma = + dyn_cast_or_null<BinaryOperator>(Result->IgnoreParens())) { + if (!BOComma->isCommaOp()) + break; + Result = BOComma->getRHS(); + } + if (Result == E) + return true; + } + return false; +} + AST_MATCHER_P(LambdaExpr, hasCaptureInit, const Expr *, E) { return llvm::is_contained(Node.capture_inits(), E); } @@ -195,11 +231,20 @@ const auto AsAssignmentLhs = binaryOperator(isAssignmentOperator(), hasLHS(equalsNode(Exp))); + // LHS of assignment is an expression with comma operator. + const auto AsAssignmentCommaLhs = + binaryOperator(isAssigmentWithCommma(Exp)); + // Operand of increment/decrement operators. const auto AsIncDecOperand = unaryOperator(anyOf(hasOperatorName("++"), hasOperatorName("--")), hasUnaryOperand(equalsNode(Exp))); + // Operand of increment/decrement operators is an expression + // with comma operator. + const auto AsIncDecOperandWithComma = + unaryOperator(isIncDecOperandWithComma(Exp)); + // Invoking non-const member function. // A member function is assumed to be non-const when it is unresolved. const auto NonConstMethod = cxxMethodDecl(unless(isConst())); @@ -264,10 +309,12 @@ const auto AsNonConstRefReturn = returnStmt(hasReturnValue(equalsNode(Exp))); const auto Matches = - match(findAll(stmt(anyOf(AsAssignmentLhs, AsIncDecOperand, AsNonConstThis, - AsAmpersandOperand, AsPointerFromArrayDecay, - AsOperatorArrowThis, AsNonConstRefArg, - AsLambdaRefCaptureInit, AsNonConstRefReturn)) + match(findAll(stmt(anyOf(AsAssignmentLhs, AsAssignmentCommaLhs, + AsIncDecOperand, AsIncDecOperandWithComma, + AsNonConstThis, AsAmpersandOperand, + AsPointerFromArrayDecay, AsOperatorArrowThis, + AsNonConstRefArg, AsLambdaRefCaptureInit, + AsNonConstRefReturn)) .bind("stmt")), Stm, Context); return selectFirst<Stmt>("stmt", Matches); Index: include/clang/AST/Expr.h =================================================================== --- include/clang/AST/Expr.h +++ include/clang/AST/Expr.h @@ -3403,6 +3403,9 @@ static bool isComparisonOp(Opcode Opc) { return Opc >= BO_Cmp && Opc<=BO_NE; } bool isComparisonOp() const { return isComparisonOp(getOpcode()); } + static bool isCommaOp(Opcode Opc) { return Opc == BO_Comma; } + bool isCommaOp() const { return isCommaOp(getOpcode()); } + static Opcode negateComparisonOp(Opcode Opc) { switch (Opc) { default:
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits