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