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