diff options
Diffstat (limited to 'lib/Analysis/ExprMutationAnalyzer.cpp')
-rw-r--r-- | lib/Analysis/ExprMutationAnalyzer.cpp | 53 |
1 files changed, 36 insertions, 17 deletions
diff --git a/lib/Analysis/ExprMutationAnalyzer.cpp b/lib/Analysis/ExprMutationAnalyzer.cpp index 8414cb5c72..fb5a139e82 100644 --- a/lib/Analysis/ExprMutationAnalyzer.cpp +++ b/lib/Analysis/ExprMutationAnalyzer.cpp @@ -1,9 +1,8 @@ //===---------- ExprMutationAnalyzer.cpp ----------------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #include "clang/Analysis/Analyses/ExprMutationAnalyzer.h" @@ -25,6 +24,18 @@ AST_MATCHER_P(CXXForRangeStmt, hasRangeStmt, return InnerMatcher.matches(*Range, Finder, Builder); } +AST_MATCHER_P(Expr, maybeEvalCommaExpr, + ast_matchers::internal::Matcher<Expr>, InnerMatcher) { + const Expr* Result = &Node; + while (const auto *BOComma = + dyn_cast_or_null<BinaryOperator>(Result->IgnoreParens())) { + if (!BOComma->isCommaOp()) + break; + Result = BOComma->getRHS(); + } + return InnerMatcher.matches(*Result, Finder, Builder); +} + const ast_matchers::internal::VariadicDynCastAllOfMatcher<Stmt, CXXTypeidExpr> cxxTypeidExpr; @@ -194,24 +205,28 @@ const Stmt *ExprMutationAnalyzer::findDeclPointeeMutation( const Stmt *ExprMutationAnalyzer::findDirectMutation(const Expr *Exp) { // LHS of any assignment operators. const auto AsAssignmentLhs = - binaryOperator(isAssignmentOperator(), hasLHS(equalsNode(Exp))); + binaryOperator(isAssignmentOperator(), + hasLHS(maybeEvalCommaExpr(equalsNode(Exp)))); // Operand of increment/decrement operators. const auto AsIncDecOperand = unaryOperator(anyOf(hasOperatorName("++"), hasOperatorName("--")), - hasUnaryOperand(equalsNode(Exp))); + hasUnaryOperand(maybeEvalCommaExpr(equalsNode(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())); const auto AsNonConstThis = - expr(anyOf(cxxMemberCallExpr(callee(NonConstMethod), on(equalsNode(Exp))), + expr(anyOf(cxxMemberCallExpr(callee(NonConstMethod), + on(maybeEvalCommaExpr(equalsNode(Exp)))), cxxOperatorCallExpr(callee(NonConstMethod), - hasArgument(0, equalsNode(Exp))), + hasArgument(0, + maybeEvalCommaExpr(equalsNode(Exp)))), callExpr(callee(expr(anyOf( - unresolvedMemberExpr(hasObjectExpression(equalsNode(Exp))), + unresolvedMemberExpr( + hasObjectExpression(maybeEvalCommaExpr(equalsNode(Exp)))), cxxDependentScopeMemberExpr( - hasObjectExpression(equalsNode(Exp))))))))); + hasObjectExpression(maybeEvalCommaExpr(equalsNode(Exp)))))))))); // Taking address of 'Exp'. // We're assuming 'Exp' is mutated as soon as its address is taken, though in @@ -221,10 +236,11 @@ const Stmt *ExprMutationAnalyzer::findDirectMutation(const Expr *Exp) { unaryOperator(hasOperatorName("&"), // A NoOp implicit cast is adding const. unless(hasParent(implicitCastExpr(hasCastKind(CK_NoOp)))), - hasUnaryOperand(equalsNode(Exp))); + hasUnaryOperand(maybeEvalCommaExpr(equalsNode(Exp)))); const auto AsPointerFromArrayDecay = castExpr(hasCastKind(CK_ArrayToPointerDecay), - unless(hasParent(arraySubscriptExpr())), has(equalsNode(Exp))); + unless(hasParent(arraySubscriptExpr())), + has(maybeEvalCommaExpr(equalsNode(Exp)))); // Treat calling `operator->()` of move-only classes as taking address. // These are typically smart pointers with unique ownership so we treat // mutation of pointee as mutation of the smart pointer itself. @@ -232,7 +248,8 @@ const Stmt *ExprMutationAnalyzer::findDirectMutation(const Expr *Exp) { cxxOperatorCallExpr(hasOverloadedOperatorName("->"), callee(cxxMethodDecl(ofClass(isMoveOnly()), returns(nonConstPointerType()))), - argumentCountIs(1), hasArgument(0, equalsNode(Exp))); + argumentCountIs(1), + hasArgument(0, maybeEvalCommaExpr(equalsNode(Exp)))); // Used as non-const-ref argument when calling a function. // An argument is assumed to be non-const-ref when the function is unresolved. @@ -240,7 +257,8 @@ const Stmt *ExprMutationAnalyzer::findDirectMutation(const Expr *Exp) { // findFunctionArgMutation which has additional smarts for handling forwarding // references. const auto NonConstRefParam = forEachArgumentWithParam( - equalsNode(Exp), parmVarDecl(hasType(nonConstReferenceType()))); + maybeEvalCommaExpr(equalsNode(Exp)), + parmVarDecl(hasType(nonConstReferenceType()))); const auto NotInstantiated = unless(hasDeclaration(isInstantiated())); const auto AsNonConstRefArg = anyOf( callExpr(NonConstRefParam, NotInstantiated), @@ -248,8 +266,8 @@ const Stmt *ExprMutationAnalyzer::findDirectMutation(const Expr *Exp) { callExpr(callee(expr(anyOf(unresolvedLookupExpr(), unresolvedMemberExpr(), cxxDependentScopeMemberExpr(), hasType(templateTypeParmType())))), - hasAnyArgument(equalsNode(Exp))), - cxxUnresolvedConstructExpr(hasAnyArgument(equalsNode(Exp)))); + hasAnyArgument(maybeEvalCommaExpr(equalsNode(Exp)))), + cxxUnresolvedConstructExpr(hasAnyArgument(maybeEvalCommaExpr(equalsNode(Exp))))); // Captured by a lambda by reference. // If we're initializing a capture with 'Exp' directly then we're initializing @@ -262,7 +280,8 @@ const Stmt *ExprMutationAnalyzer::findDirectMutation(const Expr *Exp) { // For returning by value there will be an ImplicitCastExpr <LValueToRValue>. // For returning by const-ref there will be an ImplicitCastExpr <NoOp> (for // adding const.) - const auto AsNonConstRefReturn = returnStmt(hasReturnValue(equalsNode(Exp))); + const auto AsNonConstRefReturn = returnStmt(hasReturnValue( + maybeEvalCommaExpr(equalsNode(Exp)))); const auto Matches = match(findAll(stmt(anyOf(AsAssignmentLhs, AsIncDecOperand, AsNonConstThis, |