1*e5dd7070Spatrick //===-- MPIBugReporter.h - bug reporter -----------------------*- C++ -*-===// 2*e5dd7070Spatrick // 3*e5dd7070Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*e5dd7070Spatrick // See https://llvm.org/LICENSE.txt for license information. 5*e5dd7070Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*e5dd7070Spatrick // 7*e5dd7070Spatrick //===----------------------------------------------------------------------===// 8*e5dd7070Spatrick /// 9*e5dd7070Spatrick /// \file 10*e5dd7070Spatrick /// This file defines prefabricated reports which are emitted in 11*e5dd7070Spatrick /// case of MPI related bugs, detected by path-sensitive analysis. 12*e5dd7070Spatrick /// 13*e5dd7070Spatrick //===----------------------------------------------------------------------===// 14*e5dd7070Spatrick 15*e5dd7070Spatrick #ifndef LLVM_CLANG_LIB_STATICANALYZER_CHECKERS_MPICHECKER_MPIBUGREPORTER_H 16*e5dd7070Spatrick #define LLVM_CLANG_LIB_STATICANALYZER_CHECKERS_MPICHECKER_MPIBUGREPORTER_H 17*e5dd7070Spatrick 18*e5dd7070Spatrick #include "MPITypes.h" 19*e5dd7070Spatrick #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" 20*e5dd7070Spatrick 21*e5dd7070Spatrick namespace clang { 22*e5dd7070Spatrick namespace ento { 23*e5dd7070Spatrick namespace mpi { 24*e5dd7070Spatrick 25*e5dd7070Spatrick class MPIBugReporter { 26*e5dd7070Spatrick public: MPIBugReporter(const CheckerBase & CB)27*e5dd7070Spatrick MPIBugReporter(const CheckerBase &CB) { 28*e5dd7070Spatrick UnmatchedWaitBugType.reset(new BugType(&CB, "Unmatched wait", MPIError)); 29*e5dd7070Spatrick DoubleNonblockingBugType.reset( 30*e5dd7070Spatrick new BugType(&CB, "Double nonblocking", MPIError)); 31*e5dd7070Spatrick MissingWaitBugType.reset(new BugType(&CB, "Missing wait", MPIError)); 32*e5dd7070Spatrick } 33*e5dd7070Spatrick 34*e5dd7070Spatrick /// Report duplicate request use by nonblocking calls without intermediate 35*e5dd7070Spatrick /// wait. 36*e5dd7070Spatrick /// 37*e5dd7070Spatrick /// \param MPICallEvent MPI call that caused the double nonblocking 38*e5dd7070Spatrick /// \param Req request that was used by two nonblocking calls in sequence 39*e5dd7070Spatrick /// \param RequestRegion memory region of the request 40*e5dd7070Spatrick /// \param ExplNode node in the graph the bug appeared at 41*e5dd7070Spatrick /// \param BReporter bug reporter for current context 42*e5dd7070Spatrick void reportDoubleNonblocking(const CallEvent &MPICallEvent, 43*e5dd7070Spatrick const Request &Req, 44*e5dd7070Spatrick const MemRegion *const RequestRegion, 45*e5dd7070Spatrick const ExplodedNode *const ExplNode, 46*e5dd7070Spatrick BugReporter &BReporter) const; 47*e5dd7070Spatrick 48*e5dd7070Spatrick /// Report a missing wait for a nonblocking call. 49*e5dd7070Spatrick /// 50*e5dd7070Spatrick /// \param Req request that is not matched by a wait 51*e5dd7070Spatrick /// \param RequestRegion memory region of the request 52*e5dd7070Spatrick /// \param ExplNode node in the graph the bug appeared at 53*e5dd7070Spatrick /// \param BReporter bug reporter for current context 54*e5dd7070Spatrick void reportMissingWait(const Request &Req, 55*e5dd7070Spatrick const MemRegion *const RequestRegion, 56*e5dd7070Spatrick const ExplodedNode *const ExplNode, 57*e5dd7070Spatrick BugReporter &BReporter) const; 58*e5dd7070Spatrick 59*e5dd7070Spatrick /// Report a wait on a request that has not been used at all before. 60*e5dd7070Spatrick /// 61*e5dd7070Spatrick /// \param CE wait call that uses the request 62*e5dd7070Spatrick /// \param RequestRegion memory region of the request 63*e5dd7070Spatrick /// \param ExplNode node in the graph the bug appeared at 64*e5dd7070Spatrick /// \param BReporter bug reporter for current context 65*e5dd7070Spatrick void reportUnmatchedWait(const CallEvent &CE, 66*e5dd7070Spatrick const MemRegion *const RequestRegion, 67*e5dd7070Spatrick const ExplodedNode *const ExplNode, 68*e5dd7070Spatrick BugReporter &BReporter) const; 69*e5dd7070Spatrick 70*e5dd7070Spatrick private: 71*e5dd7070Spatrick const std::string MPIError = "MPI Error"; 72*e5dd7070Spatrick 73*e5dd7070Spatrick // path-sensitive bug types 74*e5dd7070Spatrick std::unique_ptr<BugType> UnmatchedWaitBugType; 75*e5dd7070Spatrick std::unique_ptr<BugType> MissingWaitBugType; 76*e5dd7070Spatrick std::unique_ptr<BugType> DoubleNonblockingBugType; 77*e5dd7070Spatrick 78*e5dd7070Spatrick /// Bug visitor class to find the node where the request region was previously 79*e5dd7070Spatrick /// used in order to include it into the BugReport path. 80*e5dd7070Spatrick class RequestNodeVisitor : public BugReporterVisitor { 81*e5dd7070Spatrick public: RequestNodeVisitor(const MemRegion * const MemoryRegion,const std::string & ErrText)82*e5dd7070Spatrick RequestNodeVisitor(const MemRegion *const MemoryRegion, 83*e5dd7070Spatrick const std::string &ErrText) 84*e5dd7070Spatrick : RequestRegion(MemoryRegion), ErrorText(ErrText) {} 85*e5dd7070Spatrick Profile(llvm::FoldingSetNodeID & ID)86*e5dd7070Spatrick void Profile(llvm::FoldingSetNodeID &ID) const override { 87*e5dd7070Spatrick static int X = 0; 88*e5dd7070Spatrick ID.AddPointer(&X); 89*e5dd7070Spatrick ID.AddPointer(RequestRegion); 90*e5dd7070Spatrick } 91*e5dd7070Spatrick 92*e5dd7070Spatrick PathDiagnosticPieceRef VisitNode(const ExplodedNode *N, 93*e5dd7070Spatrick BugReporterContext &BRC, 94*e5dd7070Spatrick PathSensitiveBugReport &BR) override; 95*e5dd7070Spatrick 96*e5dd7070Spatrick private: 97*e5dd7070Spatrick const MemRegion *const RequestRegion; 98*e5dd7070Spatrick bool IsNodeFound = false; 99*e5dd7070Spatrick std::string ErrorText; 100*e5dd7070Spatrick }; 101*e5dd7070Spatrick }; 102*e5dd7070Spatrick 103*e5dd7070Spatrick } // end of namespace: mpi 104*e5dd7070Spatrick } // end of namespace: ento 105*e5dd7070Spatrick } // end of namespace: clang 106*e5dd7070Spatrick 107*e5dd7070Spatrick #endif 108