1*e5dd7070Spatrick //===-- MPIBugReporter.cpp - 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 #include "MPIBugReporter.h"
16*e5dd7070Spatrick #include "MPIChecker.h"
17*e5dd7070Spatrick #include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
18*e5dd7070Spatrick
19*e5dd7070Spatrick namespace clang {
20*e5dd7070Spatrick namespace ento {
21*e5dd7070Spatrick namespace mpi {
22*e5dd7070Spatrick
reportDoubleNonblocking(const CallEvent & MPICallEvent,const ento::mpi::Request & Req,const MemRegion * const RequestRegion,const ExplodedNode * const ExplNode,BugReporter & BReporter) const23*e5dd7070Spatrick void MPIBugReporter::reportDoubleNonblocking(
24*e5dd7070Spatrick const CallEvent &MPICallEvent, const ento::mpi::Request &Req,
25*e5dd7070Spatrick const MemRegion *const RequestRegion,
26*e5dd7070Spatrick const ExplodedNode *const ExplNode,
27*e5dd7070Spatrick BugReporter &BReporter) const {
28*e5dd7070Spatrick
29*e5dd7070Spatrick std::string ErrorText;
30*e5dd7070Spatrick ErrorText = "Double nonblocking on request " +
31*e5dd7070Spatrick RequestRegion->getDescriptiveName() + ". ";
32*e5dd7070Spatrick
33*e5dd7070Spatrick auto Report = std::make_unique<PathSensitiveBugReport>(
34*e5dd7070Spatrick *DoubleNonblockingBugType, ErrorText, ExplNode);
35*e5dd7070Spatrick
36*e5dd7070Spatrick Report->addRange(MPICallEvent.getSourceRange());
37*e5dd7070Spatrick SourceRange Range = RequestRegion->sourceRange();
38*e5dd7070Spatrick
39*e5dd7070Spatrick if (Range.isValid())
40*e5dd7070Spatrick Report->addRange(Range);
41*e5dd7070Spatrick
42*e5dd7070Spatrick Report->addVisitor(std::make_unique<RequestNodeVisitor>(
43*e5dd7070Spatrick RequestRegion, "Request is previously used by nonblocking call here. "));
44*e5dd7070Spatrick Report->markInteresting(RequestRegion);
45*e5dd7070Spatrick
46*e5dd7070Spatrick BReporter.emitReport(std::move(Report));
47*e5dd7070Spatrick }
48*e5dd7070Spatrick
reportMissingWait(const ento::mpi::Request & Req,const MemRegion * const RequestRegion,const ExplodedNode * const ExplNode,BugReporter & BReporter) const49*e5dd7070Spatrick void MPIBugReporter::reportMissingWait(
50*e5dd7070Spatrick const ento::mpi::Request &Req, const MemRegion *const RequestRegion,
51*e5dd7070Spatrick const ExplodedNode *const ExplNode,
52*e5dd7070Spatrick BugReporter &BReporter) const {
53*e5dd7070Spatrick std::string ErrorText{"Request " + RequestRegion->getDescriptiveName() +
54*e5dd7070Spatrick " has no matching wait. "};
55*e5dd7070Spatrick
56*e5dd7070Spatrick auto Report = std::make_unique<PathSensitiveBugReport>(*MissingWaitBugType,
57*e5dd7070Spatrick ErrorText, ExplNode);
58*e5dd7070Spatrick
59*e5dd7070Spatrick SourceRange Range = RequestRegion->sourceRange();
60*e5dd7070Spatrick if (Range.isValid())
61*e5dd7070Spatrick Report->addRange(Range);
62*e5dd7070Spatrick Report->addVisitor(std::make_unique<RequestNodeVisitor>(
63*e5dd7070Spatrick RequestRegion, "Request is previously used by nonblocking call here. "));
64*e5dd7070Spatrick Report->markInteresting(RequestRegion);
65*e5dd7070Spatrick
66*e5dd7070Spatrick BReporter.emitReport(std::move(Report));
67*e5dd7070Spatrick }
68*e5dd7070Spatrick
reportUnmatchedWait(const CallEvent & CE,const clang::ento::MemRegion * const RequestRegion,const ExplodedNode * const ExplNode,BugReporter & BReporter) const69*e5dd7070Spatrick void MPIBugReporter::reportUnmatchedWait(
70*e5dd7070Spatrick const CallEvent &CE, const clang::ento::MemRegion *const RequestRegion,
71*e5dd7070Spatrick const ExplodedNode *const ExplNode,
72*e5dd7070Spatrick BugReporter &BReporter) const {
73*e5dd7070Spatrick std::string ErrorText{"Request " + RequestRegion->getDescriptiveName() +
74*e5dd7070Spatrick " has no matching nonblocking call. "};
75*e5dd7070Spatrick
76*e5dd7070Spatrick auto Report = std::make_unique<PathSensitiveBugReport>(*UnmatchedWaitBugType,
77*e5dd7070Spatrick ErrorText, ExplNode);
78*e5dd7070Spatrick
79*e5dd7070Spatrick Report->addRange(CE.getSourceRange());
80*e5dd7070Spatrick SourceRange Range = RequestRegion->sourceRange();
81*e5dd7070Spatrick if (Range.isValid())
82*e5dd7070Spatrick Report->addRange(Range);
83*e5dd7070Spatrick
84*e5dd7070Spatrick BReporter.emitReport(std::move(Report));
85*e5dd7070Spatrick }
86*e5dd7070Spatrick
87*e5dd7070Spatrick PathDiagnosticPieceRef
VisitNode(const ExplodedNode * N,BugReporterContext & BRC,PathSensitiveBugReport & BR)88*e5dd7070Spatrick MPIBugReporter::RequestNodeVisitor::VisitNode(const ExplodedNode *N,
89*e5dd7070Spatrick BugReporterContext &BRC,
90*e5dd7070Spatrick PathSensitiveBugReport &BR) {
91*e5dd7070Spatrick
92*e5dd7070Spatrick if (IsNodeFound)
93*e5dd7070Spatrick return nullptr;
94*e5dd7070Spatrick
95*e5dd7070Spatrick const Request *const Req = N->getState()->get<RequestMap>(RequestRegion);
96*e5dd7070Spatrick assert(Req && "The region must be tracked and alive, given that we've "
97*e5dd7070Spatrick "just emitted a report against it");
98*e5dd7070Spatrick const Request *const PrevReq =
99*e5dd7070Spatrick N->getFirstPred()->getState()->get<RequestMap>(RequestRegion);
100*e5dd7070Spatrick
101*e5dd7070Spatrick // Check if request was previously unused or in a different state.
102*e5dd7070Spatrick if (!PrevReq || (Req->CurrentState != PrevReq->CurrentState)) {
103*e5dd7070Spatrick IsNodeFound = true;
104*e5dd7070Spatrick
105*e5dd7070Spatrick ProgramPoint P = N->getFirstPred()->getLocation();
106*e5dd7070Spatrick PathDiagnosticLocation L =
107*e5dd7070Spatrick PathDiagnosticLocation::create(P, BRC.getSourceManager());
108*e5dd7070Spatrick
109*e5dd7070Spatrick return std::make_shared<PathDiagnosticEventPiece>(L, ErrorText);
110*e5dd7070Spatrick }
111*e5dd7070Spatrick
112*e5dd7070Spatrick return nullptr;
113*e5dd7070Spatrick }
114*e5dd7070Spatrick
115*e5dd7070Spatrick } // end of namespace: mpi
116*e5dd7070Spatrick } // end of namespace: ento
117*e5dd7070Spatrick } // end of namespace: clang
118