Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:36:23

0001 //===---------- ExprMutationAnalyzer.h ------------------------------------===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 #ifndef LLVM_CLANG_ANALYSIS_ANALYSES_EXPRMUTATIONANALYZER_H
0009 #define LLVM_CLANG_ANALYSIS_ANALYSES_EXPRMUTATIONANALYZER_H
0010 
0011 #include "clang/ASTMatchers/ASTMatchers.h"
0012 #include "llvm/ADT/DenseMap.h"
0013 #include <memory>
0014 
0015 namespace clang {
0016 
0017 class FunctionParmMutationAnalyzer;
0018 
0019 /// Analyzes whether any mutative operations are applied to an expression within
0020 /// a given statement.
0021 class ExprMutationAnalyzer {
0022   friend class FunctionParmMutationAnalyzer;
0023 
0024 public:
0025   struct Memoized {
0026     using ResultMap = llvm::DenseMap<const Expr *, const Stmt *>;
0027     using FunctionParaAnalyzerMap =
0028         llvm::SmallDenseMap<const FunctionDecl *,
0029                             std::unique_ptr<FunctionParmMutationAnalyzer>>;
0030 
0031     ResultMap Results;
0032     ResultMap PointeeResults;
0033     FunctionParaAnalyzerMap FuncParmAnalyzer;
0034 
0035     void clear() {
0036       Results.clear();
0037       PointeeResults.clear();
0038       FuncParmAnalyzer.clear();
0039     }
0040   };
0041   struct Analyzer {
0042     Analyzer(const Stmt &Stm, ASTContext &Context, Memoized &Memorized)
0043         : Stm(Stm), Context(Context), Memorized(Memorized) {}
0044 
0045     const Stmt *findMutation(const Expr *Exp);
0046     const Stmt *findMutation(const Decl *Dec);
0047 
0048     const Stmt *findPointeeMutation(const Expr *Exp);
0049     const Stmt *findPointeeMutation(const Decl *Dec);
0050 
0051   private:
0052     using MutationFinder = const Stmt *(Analyzer::*)(const Expr *);
0053 
0054     const Stmt *findMutationMemoized(const Expr *Exp,
0055                                      llvm::ArrayRef<MutationFinder> Finders,
0056                                      Memoized::ResultMap &MemoizedResults);
0057     const Stmt *tryEachDeclRef(const Decl *Dec, MutationFinder Finder);
0058 
0059     const Stmt *findExprMutation(ArrayRef<ast_matchers::BoundNodes> Matches);
0060     const Stmt *findDeclMutation(ArrayRef<ast_matchers::BoundNodes> Matches);
0061     const Stmt *
0062     findExprPointeeMutation(ArrayRef<ast_matchers::BoundNodes> Matches);
0063     const Stmt *
0064     findDeclPointeeMutation(ArrayRef<ast_matchers::BoundNodes> Matches);
0065 
0066     const Stmt *findDirectMutation(const Expr *Exp);
0067     const Stmt *findMemberMutation(const Expr *Exp);
0068     const Stmt *findArrayElementMutation(const Expr *Exp);
0069     const Stmt *findCastMutation(const Expr *Exp);
0070     const Stmt *findRangeLoopMutation(const Expr *Exp);
0071     const Stmt *findReferenceMutation(const Expr *Exp);
0072     const Stmt *findFunctionArgMutation(const Expr *Exp);
0073 
0074     const Stmt *findPointeeValueMutation(const Expr *Exp);
0075     const Stmt *findPointeeMemberMutation(const Expr *Exp);
0076     const Stmt *findPointeeToNonConst(const Expr *Exp);
0077 
0078     const Stmt &Stm;
0079     ASTContext &Context;
0080     Memoized &Memorized;
0081   };
0082 
0083   ExprMutationAnalyzer(const Stmt &Stm, ASTContext &Context)
0084       : Memorized(), A(Stm, Context, Memorized) {}
0085 
0086   /// check whether stmt is unevaluated. mutation analyzer will ignore the
0087   /// content in unevaluated stmt.
0088   static bool isUnevaluated(const Stmt *Stm, ASTContext &Context);
0089 
0090   bool isMutated(const Expr *Exp) { return findMutation(Exp) != nullptr; }
0091   bool isMutated(const Decl *Dec) { return findMutation(Dec) != nullptr; }
0092   const Stmt *findMutation(const Expr *Exp) { return A.findMutation(Exp); }
0093   const Stmt *findMutation(const Decl *Dec) { return A.findMutation(Dec); }
0094 
0095   bool isPointeeMutated(const Expr *Exp) {
0096     return findPointeeMutation(Exp) != nullptr;
0097   }
0098   bool isPointeeMutated(const Decl *Dec) {
0099     return findPointeeMutation(Dec) != nullptr;
0100   }
0101   const Stmt *findPointeeMutation(const Expr *Exp) {
0102     return A.findPointeeMutation(Exp);
0103   }
0104   const Stmt *findPointeeMutation(const Decl *Dec) {
0105     return A.findPointeeMutation(Dec);
0106   }
0107 
0108 private:
0109   Memoized Memorized;
0110   Analyzer A;
0111 };
0112 
0113 // A convenient wrapper around ExprMutationAnalyzer for analyzing function
0114 // params.
0115 class FunctionParmMutationAnalyzer {
0116 public:
0117   static FunctionParmMutationAnalyzer *
0118   getFunctionParmMutationAnalyzer(const FunctionDecl &Func, ASTContext &Context,
0119                                   ExprMutationAnalyzer::Memoized &Memorized) {
0120     auto it = Memorized.FuncParmAnalyzer.find(&Func);
0121     if (it == Memorized.FuncParmAnalyzer.end()) {
0122       // Creating a new instance of FunctionParmMutationAnalyzer below may add
0123       // additional elements to FuncParmAnalyzer. If we did try_emplace before
0124       // creating a new instance, the returned iterator of try_emplace could be
0125       // invalidated.
0126       it =
0127           Memorized.FuncParmAnalyzer
0128               .try_emplace(&Func, std::unique_ptr<FunctionParmMutationAnalyzer>(
0129                                       new FunctionParmMutationAnalyzer(
0130                                           Func, Context, Memorized)))
0131               .first;
0132     }
0133     return it->getSecond().get();
0134   }
0135 
0136   bool isMutated(const ParmVarDecl *Parm) {
0137     return findMutation(Parm) != nullptr;
0138   }
0139   const Stmt *findMutation(const ParmVarDecl *Parm);
0140 
0141 private:
0142   ExprMutationAnalyzer::Analyzer BodyAnalyzer;
0143   llvm::DenseMap<const ParmVarDecl *, const Stmt *> Results;
0144 
0145   FunctionParmMutationAnalyzer(const FunctionDecl &Func, ASTContext &Context,
0146                                ExprMutationAnalyzer::Memoized &Memorized);
0147 };
0148 
0149 } // namespace clang
0150 
0151 #endif // LLVM_CLANG_ANALYSIS_ANALYSES_EXPRMUTATIONANALYZER_H