• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
reportDoubleNonblocking(const CallEvent & MPICallEvent,const ento::mpi::Request & Req,const MemRegion * const RequestRegion,const ExplodedNode * const ExplNode,BugReporter & BReporter) const24 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 
reportMissingWait(const ento::mpi::Request & Req,const MemRegion * const RequestRegion,const ExplodedNode * const ExplNode,BugReporter & BReporter) const50 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 
reportUnmatchedWait(const CallEvent & CE,const clang::ento::MemRegion * const RequestRegion,const ExplodedNode * const ExplNode,BugReporter & BReporter) const70 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 
VisitNode(const ExplodedNode * N,const ExplodedNode * PrevN,BugReporterContext & BRC,BugReport & BR)88 PathDiagnosticPiece *MPIBugReporter::RequestNodeVisitor::VisitNode(
89     const ExplodedNode *N, const ExplodedNode *PrevN, BugReporterContext &BRC,
90     BugReport &BR) {
91 
92   if (IsNodeFound)
93     return nullptr;
94 
95   const Request *const Req = N->getState()->get<RequestMap>(RequestRegion);
96   const Request *const PrevReq =
97       PrevN->getState()->get<RequestMap>(RequestRegion);
98 
99   // Check if request was previously unused or in a different state.
100   if ((Req && !PrevReq) || (Req->CurrentState != PrevReq->CurrentState)) {
101     IsNodeFound = true;
102 
103     ProgramPoint P = PrevN->getLocation();
104     PathDiagnosticLocation L =
105         PathDiagnosticLocation::create(P, BRC.getSourceManager());
106 
107     return new PathDiagnosticEventPiece(L, ErrorText);
108   }
109 
110   return nullptr;
111 }
112 
113 } // end of namespace: mpi
114 } // end of namespace: ento
115 } // end of namespace: clang
116