//===-- MPIChecker.h - Verify MPI API usage- --------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// /// /// \file /// This file defines the main class of MPI-Checker which serves as an entry /// point. It is created once for each translation unit analysed. /// The checker defines path-sensitive checks, to verify correct usage of the /// MPI API. /// //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_LIB_STATICANALYZER_CHECKERS_MPICHECKER_MPICHECKER_H #define LLVM_CLANG_LIB_STATICANALYZER_CHECKERS_MPICHECKER_MPICHECKER_H #include "MPIBugReporter.h" #include "MPIFunctionClassifier.h" #include "MPITypes.h" #include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h" #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" namespace clang { namespace ento { namespace mpi { class MPIChecker : public Checker { public: MPIChecker() : BReporter(*this) { } // path-sensitive callbacks void checkPreCall(const CallEvent &CE, CheckerContext &Ctx) const { dynamicInit(Ctx); checkUnmatchedWaits(CE, Ctx); checkDoubleNonblocking(CE, Ctx); } void checkDeadSymbols(SymbolReaper &SymReaper, CheckerContext &Ctx) const { dynamicInit(Ctx); checkMissingWaits(SymReaper, Ctx); } void dynamicInit(CheckerContext &Ctx) const { if (FuncClassifier) return; const_cast &>(FuncClassifier) .reset(new MPIFunctionClassifier{Ctx.getASTContext()}); } /// Checks if a request is used by nonblocking calls multiple times /// in sequence without intermediate wait. The check contains a guard, /// in order to only inspect nonblocking functions. /// /// \param PreCallEvent MPI call to verify void checkDoubleNonblocking(const clang::ento::CallEvent &PreCallEvent, clang::ento::CheckerContext &Ctx) const; /// Checks if a request is used by a wait multiple times in sequence without /// intermediate nonblocking call or if the request used by the wait /// function was not used at all before. The check contains a guard, /// in order to only inspect wait functions. /// /// \param PreCallEvent MPI call to verify void checkUnmatchedWaits(const clang::ento::CallEvent &PreCallEvent, clang::ento::CheckerContext &Ctx) const; /// Check if a nonblocking call is not matched by a wait. /// If a memory region is not alive and the last function using the /// request was a nonblocking call, this is rated as a missing wait. void checkMissingWaits(clang::ento::SymbolReaper &SymReaper, clang::ento::CheckerContext &Ctx) const; private: /// Collects all memory regions of a request(array) used by a wait /// function. If the wait function uses a single request, this is a single /// region. For wait functions using multiple requests, multiple regions /// representing elements in the array are collected. /// /// \param ReqRegions vector the regions get pushed into /// \param MR top most region to iterate /// \param CE MPI wait call using the request(s) void allRegionsUsedByWait( llvm::SmallVector &ReqRegions, const clang::ento::MemRegion *const MR, const clang::ento::CallEvent &CE, clang::ento::CheckerContext &Ctx) const; /// Returns the memory region used by a wait function. /// Distinguishes between MPI_Wait and MPI_Waitall. /// /// \param CE MPI wait call const clang::ento::MemRegion * topRegionUsedByWait(const clang::ento::CallEvent &CE) const; const std::unique_ptr FuncClassifier; MPIBugReporter BReporter; }; } // end of namespace: mpi } // end of namespace: ento } // end of namespace: clang #endif