Home | History | Annotate | Download | only in MPI-Checker
      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