1343173Sdim//===---------- ExprMutationAnalyzer.h ------------------------------------===//
2343173Sdim//
3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353358Sdim// See https://llvm.org/LICENSE.txt for license information.
5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6343173Sdim//
7343173Sdim//===----------------------------------------------------------------------===//
8343173Sdim#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_EXPRMUTATIONANALYZER_H
9343173Sdim#define LLVM_CLANG_ANALYSIS_ANALYSES_EXPRMUTATIONANALYZER_H
10343173Sdim
11343173Sdim#include <type_traits>
12343173Sdim
13343173Sdim#include "clang/AST/AST.h"
14343173Sdim#include "clang/ASTMatchers/ASTMatchers.h"
15343173Sdim#include "llvm/ADT/DenseMap.h"
16343173Sdim
17343173Sdimnamespace clang {
18343173Sdim
19343173Sdimclass FunctionParmMutationAnalyzer;
20343173Sdim
21343173Sdim/// Analyzes whether any mutative operations are applied to an expression within
22343173Sdim/// a given statement.
23343173Sdimclass ExprMutationAnalyzer {
24343173Sdimpublic:
25343173Sdim  ExprMutationAnalyzer(const Stmt &Stm, ASTContext &Context)
26343173Sdim      : Stm(Stm), Context(Context) {}
27343173Sdim
28343173Sdim  bool isMutated(const Expr *Exp) { return findMutation(Exp) != nullptr; }
29343173Sdim  bool isMutated(const Decl *Dec) { return findMutation(Dec) != nullptr; }
30343173Sdim  const Stmt *findMutation(const Expr *Exp);
31343173Sdim  const Stmt *findMutation(const Decl *Dec);
32343173Sdim
33343173Sdim  bool isPointeeMutated(const Expr *Exp) {
34343173Sdim    return findPointeeMutation(Exp) != nullptr;
35343173Sdim  }
36343173Sdim  bool isPointeeMutated(const Decl *Dec) {
37343173Sdim    return findPointeeMutation(Dec) != nullptr;
38343173Sdim  }
39343173Sdim  const Stmt *findPointeeMutation(const Expr *Exp);
40343173Sdim  const Stmt *findPointeeMutation(const Decl *Dec);
41343173Sdim
42343173Sdimprivate:
43343173Sdim  using MutationFinder = const Stmt *(ExprMutationAnalyzer::*)(const Expr *);
44343173Sdim  using ResultMap = llvm::DenseMap<const Expr *, const Stmt *>;
45343173Sdim
46343173Sdim  const Stmt *findMutationMemoized(const Expr *Exp,
47343173Sdim                                   llvm::ArrayRef<MutationFinder> Finders,
48343173Sdim                                   ResultMap &MemoizedResults);
49343173Sdim  const Stmt *tryEachDeclRef(const Decl *Dec, MutationFinder Finder);
50343173Sdim
51343173Sdim  bool isUnevaluated(const Expr *Exp);
52343173Sdim
53343173Sdim  const Stmt *findExprMutation(ArrayRef<ast_matchers::BoundNodes> Matches);
54343173Sdim  const Stmt *findDeclMutation(ArrayRef<ast_matchers::BoundNodes> Matches);
55343173Sdim  const Stmt *
56343173Sdim  findExprPointeeMutation(ArrayRef<ast_matchers::BoundNodes> Matches);
57343173Sdim  const Stmt *
58343173Sdim  findDeclPointeeMutation(ArrayRef<ast_matchers::BoundNodes> Matches);
59343173Sdim
60343173Sdim  const Stmt *findDirectMutation(const Expr *Exp);
61343173Sdim  const Stmt *findMemberMutation(const Expr *Exp);
62343173Sdim  const Stmt *findArrayElementMutation(const Expr *Exp);
63343173Sdim  const Stmt *findCastMutation(const Expr *Exp);
64343173Sdim  const Stmt *findRangeLoopMutation(const Expr *Exp);
65343173Sdim  const Stmt *findReferenceMutation(const Expr *Exp);
66343173Sdim  const Stmt *findFunctionArgMutation(const Expr *Exp);
67343173Sdim
68343173Sdim  const Stmt &Stm;
69343173Sdim  ASTContext &Context;
70343173Sdim  llvm::DenseMap<const FunctionDecl *,
71343173Sdim                 std::unique_ptr<FunctionParmMutationAnalyzer>>
72343173Sdim      FuncParmAnalyzer;
73343173Sdim  ResultMap Results;
74343173Sdim  ResultMap PointeeResults;
75343173Sdim};
76343173Sdim
77343173Sdim// A convenient wrapper around ExprMutationAnalyzer for analyzing function
78343173Sdim// params.
79343173Sdimclass FunctionParmMutationAnalyzer {
80343173Sdimpublic:
81343173Sdim  FunctionParmMutationAnalyzer(const FunctionDecl &Func, ASTContext &Context);
82343173Sdim
83343173Sdim  bool isMutated(const ParmVarDecl *Parm) {
84343173Sdim    return findMutation(Parm) != nullptr;
85343173Sdim  }
86343173Sdim  const Stmt *findMutation(const ParmVarDecl *Parm);
87343173Sdim
88343173Sdimprivate:
89343173Sdim  ExprMutationAnalyzer BodyAnalyzer;
90343173Sdim  llvm::DenseMap<const ParmVarDecl *, const Stmt *> Results;
91343173Sdim};
92343173Sdim
93343173Sdim} // namespace clang
94343173Sdim
95343173Sdim#endif // LLVM_CLANG_ANALYSIS_ANALYSES_EXPRMUTATIONANALYZER_H
96