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