|
8 | 8 | #include "clang/Analysis/Analyses/ExprMutationAnalyzer.h"
|
9 | 9 | #include "clang/AST/Expr.h"
|
10 | 10 | #include "clang/AST/OperationKinds.h"
|
| 11 | +#include "clang/AST/Stmt.h" |
11 | 12 | #include "clang/ASTMatchers/ASTMatchFinder.h"
|
12 | 13 | #include "clang/ASTMatchers/ASTMatchers.h"
|
| 14 | +#include "clang/ASTMatchers/ASTMatchersMacros.h" |
13 | 15 | #include "llvm/ADT/STLExtras.h"
|
14 | 16 |
|
15 | 17 | namespace clang {
|
16 | 18 | using namespace ast_matchers;
|
17 | 19 |
|
| 20 | +namespace { |
| 21 | + |
| 22 | +AST_MATCHER(Stmt, dumpStmt) { |
| 23 | + Node.dumpColor(); |
| 24 | + return true; |
| 25 | +} |
| 26 | +AST_MATCHER(Decl, dumpDecl) { |
| 27 | + Node.dumpColor(); |
| 28 | + return true; |
| 29 | +} |
| 30 | + |
| 31 | +} // namespace |
| 32 | + |
18 | 33 | // Check if result of Source expression could be a Target expression.
|
19 | 34 | // Checks:
|
20 | 35 | // - Implicit Casts
|
21 | 36 | // - Binary Operators
|
22 | 37 | // - ConditionalOperator
|
23 | 38 | // - BinaryConditionalOperator
|
24 | 39 | static bool canExprResolveTo(const Expr *Source, const Expr *Target) {
|
25 |
| - |
26 | 40 | const auto IgnoreDerivedToBase = [](const Expr *E, auto Matcher) {
|
27 | 41 | if (Matcher(E))
|
28 | 42 | return true;
|
@@ -92,6 +106,8 @@ static bool canExprResolveTo(const Expr *Source, const Expr *Target) {
|
92 | 106 |
|
93 | 107 | namespace {
|
94 | 108 |
|
| 109 | +AST_MATCHER(Type, isDependentType) { return Node.isDependentType(); } |
| 110 | + |
95 | 111 | AST_MATCHER_P(LambdaExpr, hasCaptureInit, const Expr *, E) {
|
96 | 112 | return llvm::is_contained(Node.capture_inits(), E);
|
97 | 113 | }
|
@@ -219,7 +235,14 @@ const Stmt *ExprMutationAnalyzer::Analyzer::findMutation(const Decl *Dec) {
|
219 | 235 |
|
220 | 236 | const Stmt *
|
221 | 237 | ExprMutationAnalyzer::Analyzer::findPointeeMutation(const Expr *Exp) {
|
222 |
| - return findMutationMemoized(Exp, {/*TODO*/}, Memorized.PointeeResults); |
| 238 | + return findMutationMemoized( |
| 239 | + Exp, |
| 240 | + { |
| 241 | + &ExprMutationAnalyzer::Analyzer::findPointeeValueMutation, |
| 242 | + &ExprMutationAnalyzer::Analyzer::findPointeeMemberMutation, |
| 243 | + &ExprMutationAnalyzer::Analyzer::findPointeeToNonConst, |
| 244 | + }, |
| 245 | + Memorized.PointeeResults); |
223 | 246 | }
|
224 | 247 |
|
225 | 248 | const Stmt *
|
@@ -388,7 +411,8 @@ ExprMutationAnalyzer::Analyzer::findDirectMutation(const Expr *Exp) {
|
388 | 411 | // references.
|
389 | 412 | const auto NonConstRefParam = forEachArgumentWithParamType(
|
390 | 413 | anyOf(canResolveToExpr(Exp),
|
391 |
| - memberExpr(hasObjectExpression(canResolveToExpr(Exp)))), |
| 414 | + memberExpr( |
| 415 | + hasObjectExpression(ignoringImpCasts(canResolveToExpr(Exp))))), |
392 | 416 | nonConstReferenceType());
|
393 | 417 | const auto NotInstantiated = unless(hasDeclaration(isInstantiated()));
|
394 | 418 |
|
@@ -654,6 +678,72 @@ ExprMutationAnalyzer::Analyzer::findFunctionArgMutation(const Expr *Exp) {
|
654 | 678 | return nullptr;
|
655 | 679 | }
|
656 | 680 |
|
| 681 | +const Stmt * |
| 682 | +ExprMutationAnalyzer::Analyzer::findPointeeValueMutation(const Expr *Exp) { |
| 683 | + const auto Matches = match( |
| 684 | + stmt(forEachDescendant( |
| 685 | + unaryOperator(hasOperatorName("*"), hasUnaryOperand(ignoringImpCasts( |
| 686 | + canResolveToExpr(Exp)))) |
| 687 | + .bind(NodeID<Expr>::value))), |
| 688 | + Stm, Context); |
| 689 | + return findExprMutation(Matches); |
| 690 | +} |
| 691 | + |
| 692 | +const Stmt * |
| 693 | +ExprMutationAnalyzer::Analyzer::findPointeeMemberMutation(const Expr *Exp) { |
| 694 | + const auto Matches = match( |
| 695 | + stmt(forEachDescendant(memberExpr(hasObjectExpression(ignoringImpCasts( |
| 696 | + canResolveToExpr(Exp)))) |
| 697 | + .bind(NodeID<Expr>::value))), |
| 698 | + Stm, Context); |
| 699 | + return findExprMutation(Matches); |
| 700 | +} |
| 701 | + |
| 702 | +const Stmt * |
| 703 | +ExprMutationAnalyzer::Analyzer::findPointeeToNonConst(const Expr *Exp) { |
| 704 | + const auto NonConstPointerOrDependentType = |
| 705 | + type(anyOf(nonConstPointerType(), isDependentType())); |
| 706 | + const auto CanResolveToExprWithImpCast = |
| 707 | + ignoringImpCasts(canResolveToExpr(Exp)); |
| 708 | + |
| 709 | + const auto InitToNonConst = |
| 710 | + varDecl(hasType(NonConstPointerOrDependentType), |
| 711 | + hasInitializer(expr(CanResolveToExprWithImpCast).bind("stmt"))); |
| 712 | + |
| 713 | + const auto AssignToNonConst = binaryOperation( |
| 714 | + hasOperatorName("="), hasLHS(expr(hasType(NonConstPointerOrDependentType))), |
| 715 | + hasRHS(CanResolveToExprWithImpCast)); |
| 716 | + |
| 717 | + const auto ArgOfInstantiationDependent = allOf( |
| 718 | + hasAnyArgument(CanResolveToExprWithImpCast), isInstantiationDependent()); |
| 719 | + const auto ArgOfNonConstParameter = forEachArgumentWithParamType( |
| 720 | + CanResolveToExprWithImpCast, NonConstPointerOrDependentType); |
| 721 | + const auto CallLikeMatcher = |
| 722 | + anyOf(ArgOfNonConstParameter, ArgOfInstantiationDependent); |
| 723 | + const auto PassAsNonConstArg = |
| 724 | + expr(anyOf(cxxUnresolvedConstructExpr(ArgOfInstantiationDependent), |
| 725 | + cxxConstructExpr(CallLikeMatcher), callExpr(CallLikeMatcher), |
| 726 | + parenListExpr(has(CanResolveToExprWithImpCast)), |
| 727 | + initListExpr(hasAnyInit(CanResolveToExprWithImpCast)))); |
| 728 | + const auto CallNonConstMethod = |
| 729 | + cxxMemberCallExpr(on(ignoringImpCasts(expr(canResolveToExpr(Exp)))), |
| 730 | + unless(isConstCallee())); |
| 731 | + const auto CastToNonConst = |
| 732 | + explicitCastExpr(hasSourceExpression(CanResolveToExprWithImpCast), |
| 733 | + hasDestinationType(NonConstPointerOrDependentType)); |
| 734 | + |
| 735 | + // TODO: lambda, BinaryOperator/ArraySubscriptExpr |
| 736 | + |
| 737 | + const auto Matches = |
| 738 | + match(stmt(anyOf(forEachDescendant( |
| 739 | + stmt(anyOf(AssignToNonConst, PassAsNonConstArg, |
| 740 | + CallNonConstMethod, CastToNonConst)) |
| 741 | + .bind("stmt")), |
| 742 | + forEachDescendant(decl(InitToNonConst)))), |
| 743 | + Stm, Context); |
| 744 | + return selectFirst<Stmt>("stmt", Matches); |
| 745 | +} |
| 746 | + |
657 | 747 | FunctionParmMutationAnalyzer::FunctionParmMutationAnalyzer(
|
658 | 748 | const FunctionDecl &Func, ASTContext &Context,
|
659 | 749 | ExprMutationAnalyzer::Memoized &Memorized)
|
|
0 commit comments