xref: /openbsd-src/gnu/llvm/clang/lib/StaticAnalyzer/Checkers/MPI-Checker/MPIBugReporter.h (revision e5dd70708596ae51455a0ffa086a00c5b29f8583)
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