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 "MPIFunctionClassifier.h" 23 #include "MPITypes.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: 33 MPIChecker() : BReporter(*this) { } 34 35 // path-sensitive callbacks 36 void checkPreCall(const CallEvent &CE, CheckerContext &Ctx) const { 37 dynamicInit(Ctx); 38 checkUnmatchedWaits(CE, Ctx); 39 checkDoubleNonblocking(CE, Ctx); 40 } 41 42 void checkDeadSymbols(SymbolReaper &SymReaper, CheckerContext &Ctx) const { 43 dynamicInit(Ctx); 44 checkMissingWaits(SymReaper, Ctx); 45 } 46 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 55 /// Checks if a request is used by nonblocking calls multiple times 56 /// in sequence without intermediate wait. The check contains a guard, 57 /// in order to only inspect nonblocking functions. 58 /// 59 /// \param PreCallEvent MPI call to verify 60 void checkDoubleNonblocking(const clang::ento::CallEvent &PreCallEvent, 61 clang::ento::CheckerContext &Ctx) const; 62 63 /// Checks if a request is used by a wait multiple times in sequence without 64 /// intermediate nonblocking call or if the request used by the wait 65 /// function was not used at all before. The check contains a guard, 66 /// in order to only inspect wait functions. 67 /// 68 /// \param PreCallEvent MPI call to verify 69 void checkUnmatchedWaits(const clang::ento::CallEvent &PreCallEvent, 70 clang::ento::CheckerContext &Ctx) const; 71 72 /// Check if a nonblocking call is not matched by a wait. 73 /// If a memory region is not alive and the last function using the 74 /// request was a nonblocking call, this is rated as a missing wait. 75 void checkMissingWaits(clang::ento::SymbolReaper &SymReaper, 76 clang::ento::CheckerContext &Ctx) const; 77 78 private: 79 /// Collects all memory regions of a request(array) used by a wait 80 /// function. If the wait function uses a single request, this is a single 81 /// region. For wait functions using multiple requests, multiple regions 82 /// representing elements in the array are collected. 83 /// 84 /// \param ReqRegions vector the regions get pushed into 85 /// \param MR top most region to iterate 86 /// \param CE MPI wait call using the request(s) 87 void allRegionsUsedByWait( 88 llvm::SmallVector<const clang::ento::MemRegion *, 2> &ReqRegions, 89 const clang::ento::MemRegion *const MR, const clang::ento::CallEvent &CE, 90 clang::ento::CheckerContext &Ctx) const; 91 92 /// Returns the memory region used by a wait function. 93 /// Distinguishes between MPI_Wait and MPI_Waitall. 94 /// 95 /// \param CE MPI wait call 96 const clang::ento::MemRegion * 97 topRegionUsedByWait(const clang::ento::CallEvent &CE) const; 98 99 const std::unique_ptr<MPIFunctionClassifier> FuncClassifier; 100 MPIBugReporter BReporter; 101 }; 102 103 } // end of namespace: mpi 104 } // end of namespace: ento 105 } // end of namespace: clang 106 107 #endif 108