[clang] [mutation analyzer] support mutation analysis for pointee (PR #118593)

Julian Schmidt via cfe-commits cfe-commits at lists.llvm.org
Tue Jan 21 01:03:26 PST 2025


================
@@ -654,6 +716,83 @@ ExprMutationAnalyzer::Analyzer::findFunctionArgMutation(const Expr *Exp) {
   return nullptr;
 }
 
+const Stmt *
+ExprMutationAnalyzer::Analyzer::findPointeeValueMutation(const Expr *Exp) {
+  const auto Matches = match(
+      stmt(forEachDescendant(
+          expr(anyOf(
+                   // deref by *
+                   unaryOperator(hasOperatorName("*"),
+                                 hasUnaryOperand(canResolveToExprPointee(Exp))),
+                   // deref by []
+                   arraySubscriptExpr(hasBase(canResolveToExprPointee(Exp)))))
+              .bind(NodeID<Expr>::value))),
+      Stm, Context);
+  return findExprMutation(Matches);
+}
+
+const Stmt *
+ExprMutationAnalyzer::Analyzer::findPointeeMemberMutation(const Expr *Exp) {
+  const Stmt *MemberCallExpr = selectFirst<Stmt>(
+      "stmt", match(stmt(forEachDescendant(
+                        cxxMemberCallExpr(on(canResolveToExprPointee(Exp)),
+                                          unless(isConstCallee()))
+                            .bind("stmt"))),
+                    Stm, Context));
+  if (MemberCallExpr)
+    return MemberCallExpr;
+  const auto Matches =
+      match(stmt(forEachDescendant(
+                memberExpr(hasObjectExpression(canResolveToExprPointee(Exp)))
+                    .bind(NodeID<Expr>::value))),
+            Stm, Context);
+  return findExprMutation(Matches);
+}
+
+const Stmt *
+ExprMutationAnalyzer::Analyzer::findPointeeToNonConst(const Expr *Exp) {
+  const auto NonConstPointerOrDependentType =
+      type(anyOf(nonConstPointerType(), isDependentType()));
+
+  // assign
+  const auto InitToNonConst =
+      varDecl(hasType(NonConstPointerOrDependentType),
+              hasInitializer(expr(canResolveToExprPointee(Exp)).bind("stmt")));
+  const auto AssignToNonConst =
+      binaryOperation(hasOperatorName("="),
+                      hasLHS(expr(hasType(NonConstPointerOrDependentType))),
+                      hasRHS(canResolveToExprPointee(Exp)));
+  // arguments like
+  const auto ArgOfInstantiationDependent = allOf(
+      hasAnyArgument(canResolveToExprPointee(Exp)), isInstantiationDependent());
+  const auto ArgOfNonConstParameter = forEachArgumentWithParamType(
+      canResolveToExprPointee(Exp), NonConstPointerOrDependentType);
+  const auto CallLikeMatcher =
+      anyOf(ArgOfNonConstParameter, ArgOfInstantiationDependent);
+  const auto PassAsNonConstArg =
+      expr(anyOf(cxxUnresolvedConstructExpr(ArgOfInstantiationDependent),
+                 cxxConstructExpr(CallLikeMatcher), callExpr(CallLikeMatcher),
+                 parenListExpr(has(canResolveToExprPointee(Exp))),
+                 initListExpr(hasAnyInit(canResolveToExprPointee(Exp)))));
+  // cast
+  const auto CastToNonConst =
+      explicitCastExpr(hasSourceExpression(canResolveToExprPointee(Exp)),
+                       hasDestinationType(NonConstPointerOrDependentType));
+
+  // capture
+  // FIXME: false positive if the pointee does not change in lambda
+  const auto CaptureNoConst = lambdaExpr(hasCaptureInit(Exp));
+
+  const auto Matches =
+      match(stmt(anyOf(forEachDescendant(
+                           stmt(anyOf(AssignToNonConst, PassAsNonConstArg,
+                                      CastToNonConst, CaptureNoConst))
+                               .bind("stmt")),
+                       forEachDescendant(decl(InitToNonConst)))),
----------------
5chmidti wrote:

nit: the `decl` around `InitToNonConst` is not needed

https://github.com/llvm/llvm-project/pull/118593


More information about the cfe-commits mailing list