Skip to content

Commit 04e220e

Browse files
committed
[analysis] support mutation analysis for pointee wip
1 parent 4ad4d34 commit 04e220e

File tree

3 files changed

+371
-3
lines changed

3 files changed

+371
-3
lines changed

clang/include/clang/Analysis/Analyses/ExprMutationAnalyzer.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,10 @@ class ExprMutationAnalyzer {
7171
const Stmt *findReferenceMutation(const Expr *Exp);
7272
const Stmt *findFunctionArgMutation(const Expr *Exp);
7373

74+
const Stmt *findPointeeValueMutation(const Expr *Exp);
75+
const Stmt *findPointeeMemberMutation(const Expr *Exp);
76+
const Stmt *findPointeeToNonConst(const Expr *Exp);
77+
7478
const Stmt &Stm;
7579
ASTContext &Context;
7680
Memoized &Memorized;

clang/lib/Analysis/ExprMutationAnalyzer.cpp

Lines changed: 93 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,21 +8,35 @@
88
#include "clang/Analysis/Analyses/ExprMutationAnalyzer.h"
99
#include "clang/AST/Expr.h"
1010
#include "clang/AST/OperationKinds.h"
11+
#include "clang/AST/Stmt.h"
1112
#include "clang/ASTMatchers/ASTMatchFinder.h"
1213
#include "clang/ASTMatchers/ASTMatchers.h"
14+
#include "clang/ASTMatchers/ASTMatchersMacros.h"
1315
#include "llvm/ADT/STLExtras.h"
1416

1517
namespace clang {
1618
using namespace ast_matchers;
1719

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+
1833
// Check if result of Source expression could be a Target expression.
1934
// Checks:
2035
// - Implicit Casts
2136
// - Binary Operators
2237
// - ConditionalOperator
2338
// - BinaryConditionalOperator
2439
static bool canExprResolveTo(const Expr *Source, const Expr *Target) {
25-
2640
const auto IgnoreDerivedToBase = [](const Expr *E, auto Matcher) {
2741
if (Matcher(E))
2842
return true;
@@ -92,6 +106,8 @@ static bool canExprResolveTo(const Expr *Source, const Expr *Target) {
92106

93107
namespace {
94108

109+
AST_MATCHER(Type, isDependentType) { return Node.isDependentType(); }
110+
95111
AST_MATCHER_P(LambdaExpr, hasCaptureInit, const Expr *, E) {
96112
return llvm::is_contained(Node.capture_inits(), E);
97113
}
@@ -219,7 +235,14 @@ const Stmt *ExprMutationAnalyzer::Analyzer::findMutation(const Decl *Dec) {
219235

220236
const Stmt *
221237
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);
223246
}
224247

225248
const Stmt *
@@ -388,7 +411,8 @@ ExprMutationAnalyzer::Analyzer::findDirectMutation(const Expr *Exp) {
388411
// references.
389412
const auto NonConstRefParam = forEachArgumentWithParamType(
390413
anyOf(canResolveToExpr(Exp),
391-
memberExpr(hasObjectExpression(canResolveToExpr(Exp)))),
414+
memberExpr(
415+
hasObjectExpression(ignoringImpCasts(canResolveToExpr(Exp))))),
392416
nonConstReferenceType());
393417
const auto NotInstantiated = unless(hasDeclaration(isInstantiated()));
394418

@@ -654,6 +678,72 @@ ExprMutationAnalyzer::Analyzer::findFunctionArgMutation(const Expr *Exp) {
654678
return nullptr;
655679
}
656680

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+
657747
FunctionParmMutationAnalyzer::FunctionParmMutationAnalyzer(
658748
const FunctionDecl &Func, ASTContext &Context,
659749
ExprMutationAnalyzer::Memoized &Memorized)

0 commit comments

Comments
 (0)