xref: /aosp_15_r20/external/clang/lib/StaticAnalyzer/Checkers/MPI-Checker/MPIChecker.h (revision 67e74705e28f6214e480b399dd47ea732279e315)
1*67e74705SXin Li //===-- MPIChecker.h - Verify MPI API usage- --------------------*- C++ -*-===//
2*67e74705SXin Li //
3*67e74705SXin Li //                     The LLVM Compiler Infrastructure
4*67e74705SXin Li //
5*67e74705SXin Li // This file is distributed under the University of Illinois Open Source
6*67e74705SXin Li // License. See LICENSE.TXT for details.
7*67e74705SXin Li //
8*67e74705SXin Li //===----------------------------------------------------------------------===//
9*67e74705SXin Li ///
10*67e74705SXin Li /// \file
11*67e74705SXin Li /// This file defines the main class of MPI-Checker which serves as an entry
12*67e74705SXin Li /// point. It is created once for each translation unit analysed.
13*67e74705SXin Li /// The checker defines path-sensitive checks, to verify correct usage of the
14*67e74705SXin Li /// MPI API.
15*67e74705SXin Li ///
16*67e74705SXin Li //===----------------------------------------------------------------------===//
17*67e74705SXin Li 
18*67e74705SXin Li #ifndef LLVM_CLANG_LIB_STATICANALYZER_CHECKERS_MPICHECKER_MPICHECKER_H
19*67e74705SXin Li #define LLVM_CLANG_LIB_STATICANALYZER_CHECKERS_MPICHECKER_MPICHECKER_H
20*67e74705SXin Li 
21*67e74705SXin Li #include "MPIBugReporter.h"
22*67e74705SXin Li #include "MPIFunctionClassifier.h"
23*67e74705SXin Li #include "MPITypes.h"
24*67e74705SXin Li #include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
25*67e74705SXin Li #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
26*67e74705SXin Li 
27*67e74705SXin Li namespace clang {
28*67e74705SXin Li namespace ento {
29*67e74705SXin Li namespace mpi {
30*67e74705SXin Li 
31*67e74705SXin Li class MPIChecker : public Checker<check::PreCall, check::DeadSymbols> {
32*67e74705SXin Li public:
MPIChecker()33*67e74705SXin Li   MPIChecker() : BReporter(*this) { }
34*67e74705SXin Li 
35*67e74705SXin Li   // path-sensitive callbacks
checkPreCall(const CallEvent & CE,CheckerContext & Ctx)36*67e74705SXin Li   void checkPreCall(const CallEvent &CE, CheckerContext &Ctx) const {
37*67e74705SXin Li     dynamicInit(Ctx);
38*67e74705SXin Li     checkUnmatchedWaits(CE, Ctx);
39*67e74705SXin Li     checkDoubleNonblocking(CE, Ctx);
40*67e74705SXin Li   }
41*67e74705SXin Li 
checkDeadSymbols(SymbolReaper & SymReaper,CheckerContext & Ctx)42*67e74705SXin Li   void checkDeadSymbols(SymbolReaper &SymReaper, CheckerContext &Ctx) const {
43*67e74705SXin Li     dynamicInit(Ctx);
44*67e74705SXin Li     checkMissingWaits(SymReaper, Ctx);
45*67e74705SXin Li   }
46*67e74705SXin Li 
dynamicInit(CheckerContext & Ctx)47*67e74705SXin Li   void dynamicInit(CheckerContext &Ctx) const {
48*67e74705SXin Li     if (FuncClassifier)
49*67e74705SXin Li       return;
50*67e74705SXin Li     const_cast<std::unique_ptr<MPIFunctionClassifier> &>(FuncClassifier)
51*67e74705SXin Li         .reset(new MPIFunctionClassifier{Ctx.getASTContext()});
52*67e74705SXin Li 
53*67e74705SXin Li   }
54*67e74705SXin Li 
55*67e74705SXin Li   /// Checks if a request is used by nonblocking calls multiple times
56*67e74705SXin Li   /// in sequence without intermediate wait. The check contains a guard,
57*67e74705SXin Li   /// in order to only inspect nonblocking functions.
58*67e74705SXin Li   ///
59*67e74705SXin Li   /// \param PreCallEvent MPI call to verify
60*67e74705SXin Li   void checkDoubleNonblocking(const clang::ento::CallEvent &PreCallEvent,
61*67e74705SXin Li                               clang::ento::CheckerContext &Ctx) const;
62*67e74705SXin Li 
63*67e74705SXin Li   /// Checks if a request is used by a wait multiple times in sequence without
64*67e74705SXin Li   /// intermediate nonblocking call or if the request used by the wait
65*67e74705SXin Li   /// function was not used at all before. The check contains a guard,
66*67e74705SXin Li   /// in order to only inspect wait functions.
67*67e74705SXin Li   ///
68*67e74705SXin Li   /// \param PreCallEvent MPI call to verify
69*67e74705SXin Li   void checkUnmatchedWaits(const clang::ento::CallEvent &PreCallEvent,
70*67e74705SXin Li                            clang::ento::CheckerContext &Ctx) const;
71*67e74705SXin Li 
72*67e74705SXin Li   /// Check if a nonblocking call is not matched by a wait.
73*67e74705SXin Li   /// If a memory region is not alive and the last function using the
74*67e74705SXin Li   /// request was a nonblocking call, this is rated as a missing wait.
75*67e74705SXin Li   void checkMissingWaits(clang::ento::SymbolReaper &SymReaper,
76*67e74705SXin Li                          clang::ento::CheckerContext &Ctx) const;
77*67e74705SXin Li 
78*67e74705SXin Li private:
79*67e74705SXin Li   /// Collects all memory regions of a request(array) used by a wait
80*67e74705SXin Li   /// function. If the wait function uses a single request, this is a single
81*67e74705SXin Li   /// region. For wait functions using multiple requests, multiple regions
82*67e74705SXin Li   /// representing elements in the array are collected.
83*67e74705SXin Li   ///
84*67e74705SXin Li   /// \param ReqRegions vector the regions get pushed into
85*67e74705SXin Li   /// \param MR top most region to iterate
86*67e74705SXin Li   /// \param CE MPI wait call using the request(s)
87*67e74705SXin Li   void allRegionsUsedByWait(
88*67e74705SXin Li       llvm::SmallVector<const clang::ento::MemRegion *, 2> &ReqRegions,
89*67e74705SXin Li       const clang::ento::MemRegion *const MR, const clang::ento::CallEvent &CE,
90*67e74705SXin Li       clang::ento::CheckerContext &Ctx) const;
91*67e74705SXin Li 
92*67e74705SXin Li   /// Returns the memory region used by a wait function.
93*67e74705SXin Li   /// Distinguishes between MPI_Wait and MPI_Waitall.
94*67e74705SXin Li   ///
95*67e74705SXin Li   /// \param CE MPI wait call
96*67e74705SXin Li   const clang::ento::MemRegion *
97*67e74705SXin Li   topRegionUsedByWait(const clang::ento::CallEvent &CE) const;
98*67e74705SXin Li 
99*67e74705SXin Li   const std::unique_ptr<MPIFunctionClassifier> FuncClassifier;
100*67e74705SXin Li   MPIBugReporter BReporter;
101*67e74705SXin Li };
102*67e74705SXin Li 
103*67e74705SXin Li } // end of namespace: mpi
104*67e74705SXin Li } // end of namespace: ento
105*67e74705SXin Li } // end of namespace: clang
106*67e74705SXin Li 
107*67e74705SXin Li #endif
108