1 //===---------- ExprMutationAnalyzer.h ------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 #ifndef LLVM_CLANG_ANALYSIS_ANALYSES_EXPRMUTATIONANALYZER_H
9 #define LLVM_CLANG_ANALYSIS_ANALYSES_EXPRMUTATIONANALYZER_H
10 
11 #include <type_traits>
12 
13 #include "clang/AST/AST.h"
14 #include "clang/ASTMatchers/ASTMatchers.h"
15 #include "llvm/ADT/DenseMap.h"
16 
17 namespace clang {
18 
19 class FunctionParmMutationAnalyzer;
20 
21 /// Analyzes whether any mutative operations are applied to an expression within
22 /// a given statement.
23 class ExprMutationAnalyzer {
24 public:
ExprMutationAnalyzer(const Stmt & Stm,ASTContext & Context)25   ExprMutationAnalyzer(const Stmt &Stm, ASTContext &Context)
26       : Stm(Stm), Context(Context) {}
27 
isMutated(const Expr * Exp)28   bool isMutated(const Expr *Exp) { return findMutation(Exp) != nullptr; }
isMutated(const Decl * Dec)29   bool isMutated(const Decl *Dec) { return findMutation(Dec) != nullptr; }
30   const Stmt *findMutation(const Expr *Exp);
31   const Stmt *findMutation(const Decl *Dec);
32 
isPointeeMutated(const Expr * Exp)33   bool isPointeeMutated(const Expr *Exp) {
34     return findPointeeMutation(Exp) != nullptr;
35   }
isPointeeMutated(const Decl * Dec)36   bool isPointeeMutated(const Decl *Dec) {
37     return findPointeeMutation(Dec) != nullptr;
38   }
39   const Stmt *findPointeeMutation(const Expr *Exp);
40   const Stmt *findPointeeMutation(const Decl *Dec);
41 
42 private:
43   using MutationFinder = const Stmt *(ExprMutationAnalyzer::*)(const Expr *);
44   using ResultMap = llvm::DenseMap<const Expr *, const Stmt *>;
45 
46   const Stmt *findMutationMemoized(const Expr *Exp,
47                                    llvm::ArrayRef<MutationFinder> Finders,
48                                    ResultMap &MemoizedResults);
49   const Stmt *tryEachDeclRef(const Decl *Dec, MutationFinder Finder);
50 
51   bool isUnevaluated(const Expr *Exp);
52 
53   const Stmt *findExprMutation(ArrayRef<ast_matchers::BoundNodes> Matches);
54   const Stmt *findDeclMutation(ArrayRef<ast_matchers::BoundNodes> Matches);
55   const Stmt *
56   findExprPointeeMutation(ArrayRef<ast_matchers::BoundNodes> Matches);
57   const Stmt *
58   findDeclPointeeMutation(ArrayRef<ast_matchers::BoundNodes> Matches);
59 
60   const Stmt *findDirectMutation(const Expr *Exp);
61   const Stmt *findMemberMutation(const Expr *Exp);
62   const Stmt *findArrayElementMutation(const Expr *Exp);
63   const Stmt *findCastMutation(const Expr *Exp);
64   const Stmt *findRangeLoopMutation(const Expr *Exp);
65   const Stmt *findReferenceMutation(const Expr *Exp);
66   const Stmt *findFunctionArgMutation(const Expr *Exp);
67 
68   const Stmt &Stm;
69   ASTContext &Context;
70   llvm::DenseMap<const FunctionDecl *,
71                  std::unique_ptr<FunctionParmMutationAnalyzer>>
72       FuncParmAnalyzer;
73   ResultMap Results;
74   ResultMap PointeeResults;
75 };
76 
77 // A convenient wrapper around ExprMutationAnalyzer for analyzing function
78 // params.
79 class FunctionParmMutationAnalyzer {
80 public:
81   FunctionParmMutationAnalyzer(const FunctionDecl &Func, ASTContext &Context);
82 
isMutated(const ParmVarDecl * Parm)83   bool isMutated(const ParmVarDecl *Parm) {
84     return findMutation(Parm) != nullptr;
85   }
86   const Stmt *findMutation(const ParmVarDecl *Parm);
87 
88 private:
89   ExprMutationAnalyzer BodyAnalyzer;
90   llvm::DenseMap<const ParmVarDecl *, const Stmt *> Results;
91 };
92 
93 } // namespace clang
94 
95 #endif // LLVM_CLANG_ANALYSIS_ANALYSES_EXPRMUTATIONANALYZER_H
96