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