1 //===-- MPIBugReporter.cpp - bug reporter -----------------------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
10 /// This file defines prefabricated reports which are emitted in
11 /// case of MPI related bugs, detected by path-sensitive analysis.
13 //===----------------------------------------------------------------------===//
15 #include "MPIBugReporter.h"
16 #include "MPIChecker.h"
17 #include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
23 void MPIBugReporter::reportDoubleNonblocking(
24 const CallEvent
&MPICallEvent
, const ento::mpi::Request
&Req
,
25 const MemRegion
*const RequestRegion
,
26 const ExplodedNode
*const ExplNode
,
27 BugReporter
&BReporter
) const {
29 std::string ErrorText
;
30 ErrorText
= "Double nonblocking on request " +
31 RequestRegion
->getDescriptiveName() + ". ";
33 auto Report
= std::make_unique
<PathSensitiveBugReport
>(
34 *DoubleNonblockingBugType
, ErrorText
, ExplNode
);
36 Report
->addRange(MPICallEvent
.getSourceRange());
37 SourceRange Range
= RequestRegion
->sourceRange();
40 Report
->addRange(Range
);
42 Report
->addVisitor(std::make_unique
<RequestNodeVisitor
>(
43 RequestRegion
, "Request is previously used by nonblocking call here. "));
44 Report
->markInteresting(RequestRegion
);
46 BReporter
.emitReport(std::move(Report
));
49 void MPIBugReporter::reportMissingWait(
50 const ento::mpi::Request
&Req
, const MemRegion
*const RequestRegion
,
51 const ExplodedNode
*const ExplNode
,
52 BugReporter
&BReporter
) const {
53 std::string ErrorText
{"Request " + RequestRegion
->getDescriptiveName() +
54 " has no matching wait. "};
56 auto Report
= std::make_unique
<PathSensitiveBugReport
>(*MissingWaitBugType
,
59 SourceRange Range
= RequestRegion
->sourceRange();
61 Report
->addRange(Range
);
62 Report
->addVisitor(std::make_unique
<RequestNodeVisitor
>(
63 RequestRegion
, "Request is previously used by nonblocking call here. "));
64 Report
->markInteresting(RequestRegion
);
66 BReporter
.emitReport(std::move(Report
));
69 void MPIBugReporter::reportUnmatchedWait(
70 const CallEvent
&CE
, const clang::ento::MemRegion
*const RequestRegion
,
71 const ExplodedNode
*const ExplNode
,
72 BugReporter
&BReporter
) const {
73 std::string ErrorText
{"Request " + RequestRegion
->getDescriptiveName() +
74 " has no matching nonblocking call. "};
76 auto Report
= std::make_unique
<PathSensitiveBugReport
>(*UnmatchedWaitBugType
,
79 Report
->addRange(CE
.getSourceRange());
80 SourceRange Range
= RequestRegion
->sourceRange();
82 Report
->addRange(Range
);
84 BReporter
.emitReport(std::move(Report
));
87 PathDiagnosticPieceRef
88 MPIBugReporter::RequestNodeVisitor::VisitNode(const ExplodedNode
*N
,
89 BugReporterContext
&BRC
,
90 PathSensitiveBugReport
&BR
) {
95 const Request
*const Req
= N
->getState()->get
<RequestMap
>(RequestRegion
);
96 assert(Req
&& "The region must be tracked and alive, given that we've "
97 "just emitted a report against it");
98 const Request
*const PrevReq
=
99 N
->getFirstPred()->getState()->get
<RequestMap
>(RequestRegion
);
101 // Check if request was previously unused or in a different state.
102 if (!PrevReq
|| (Req
->CurrentState
!= PrevReq
->CurrentState
)) {
105 ProgramPoint P
= N
->getFirstPred()->getLocation();
106 PathDiagnosticLocation L
=
107 PathDiagnosticLocation::create(P
, BRC
.getSourceManager());
109 return std::make_shared
<PathDiagnosticEventPiece
>(L
, ErrorText
);
115 } // end of namespace: mpi
116 } // end of namespace: ento
117 } // end of namespace: clang