]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MPI-Checker/MPIBugReporter.cpp
MFV r329766: 8962 zdb should work on non-idle pools
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / clang / lib / StaticAnalyzer / Checkers / MPI-Checker / MPIBugReporter.cpp
1 //===-- MPIBugReporter.cpp - bug reporter -----------------------*- 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 prefabricated reports which are emitted in
12 /// case of MPI related bugs, detected by path-sensitive analysis.
13 ///
14 //===----------------------------------------------------------------------===//
15
16 #include "MPIBugReporter.h"
17 #include "MPIChecker.h"
18 #include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
19
20 namespace clang {
21 namespace ento {
22 namespace mpi {
23
24 void MPIBugReporter::reportDoubleNonblocking(
25     const CallEvent &MPICallEvent, const ento::mpi::Request &Req,
26     const MemRegion *const RequestRegion,
27     const ExplodedNode *const ExplNode,
28     BugReporter &BReporter) const {
29
30   std::string ErrorText;
31   ErrorText = "Double nonblocking on request " +
32               RequestRegion->getDescriptiveName() + ". ";
33
34   auto Report = llvm::make_unique<BugReport>(*DoubleNonblockingBugType,
35                                              ErrorText, ExplNode);
36
37   Report->addRange(MPICallEvent.getSourceRange());
38   SourceRange Range = RequestRegion->sourceRange();
39
40   if (Range.isValid())
41     Report->addRange(Range);
42
43   Report->addVisitor(llvm::make_unique<RequestNodeVisitor>(
44       RequestRegion, "Request is previously used by nonblocking call here. "));
45   Report->markInteresting(RequestRegion);
46
47   BReporter.emitReport(std::move(Report));
48 }
49
50 void MPIBugReporter::reportMissingWait(
51     const ento::mpi::Request &Req, const MemRegion *const RequestRegion,
52     const ExplodedNode *const ExplNode,
53     BugReporter &BReporter) const {
54   std::string ErrorText{"Request " + RequestRegion->getDescriptiveName() +
55                         " has no matching wait. "};
56
57   auto Report =
58       llvm::make_unique<BugReport>(*MissingWaitBugType, ErrorText, ExplNode);
59
60   SourceRange Range = RequestRegion->sourceRange();
61   if (Range.isValid())
62     Report->addRange(Range);
63   Report->addVisitor(llvm::make_unique<RequestNodeVisitor>(
64       RequestRegion, "Request is previously used by nonblocking call here. "));
65   Report->markInteresting(RequestRegion);
66
67   BReporter.emitReport(std::move(Report));
68 }
69
70 void MPIBugReporter::reportUnmatchedWait(
71     const CallEvent &CE, const clang::ento::MemRegion *const RequestRegion,
72     const ExplodedNode *const ExplNode,
73     BugReporter &BReporter) const {
74   std::string ErrorText{"Request " + RequestRegion->getDescriptiveName() +
75                         " has no matching nonblocking call. "};
76
77   auto Report =
78       llvm::make_unique<BugReport>(*UnmatchedWaitBugType, ErrorText, ExplNode);
79
80   Report->addRange(CE.getSourceRange());
81   SourceRange Range = RequestRegion->sourceRange();
82   if (Range.isValid())
83     Report->addRange(Range);
84
85   BReporter.emitReport(std::move(Report));
86 }
87
88 std::shared_ptr<PathDiagnosticPiece>
89 MPIBugReporter::RequestNodeVisitor::VisitNode(const ExplodedNode *N,
90                                               const ExplodedNode *PrevN,
91                                               BugReporterContext &BRC,
92                                               BugReport &BR) {
93
94   if (IsNodeFound)
95     return nullptr;
96
97   const Request *const Req = N->getState()->get<RequestMap>(RequestRegion);
98   const Request *const PrevReq =
99       PrevN->getState()->get<RequestMap>(RequestRegion);
100
101   // Check if request was previously unused or in a different state.
102   if ((Req && !PrevReq) || (Req->CurrentState != PrevReq->CurrentState)) {
103     IsNodeFound = true;
104
105     ProgramPoint P = PrevN->getLocation();
106     PathDiagnosticLocation L =
107         PathDiagnosticLocation::create(P, BRC.getSourceManager());
108
109     return std::make_shared<PathDiagnosticEventPiece>(L, ErrorText);
110   }
111
112   return nullptr;
113 }
114
115 } // end of namespace: mpi
116 } // end of namespace: ento
117 } // end of namespace: clang