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
27namespace clang {
28namespace ento {
29namespace mpi {
30
31class MPIChecker : public Checker<check::PreCall, check::DeadSymbols> {
32public:
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
78private:
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