]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm-project/clang/lib/StaticAnalyzer/Checkers/MPI-Checker/MPIBugReporter.cpp
MFC r355940:
[FreeBSD/FreeBSD.git] / contrib / llvm-project / clang / lib / StaticAnalyzer / Checkers / MPI-Checker / MPIBugReporter.cpp
1 //===-- MPIBugReporter.cpp - 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 #include "MPIBugReporter.h"
16 #include "MPIChecker.h"
17 #include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
18
19 namespace clang {
20 namespace ento {
21 namespace mpi {
22
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 {
28
29   std::string ErrorText;
30   ErrorText = "Double nonblocking on request " +
31               RequestRegion->getDescriptiveName() + ". ";
32
33   auto Report = llvm::make_unique<BugReport>(*DoubleNonblockingBugType,
34                                              ErrorText, ExplNode);
35
36   Report->addRange(MPICallEvent.getSourceRange());
37   SourceRange Range = RequestRegion->sourceRange();
38
39   if (Range.isValid())
40     Report->addRange(Range);
41
42   Report->addVisitor(llvm::make_unique<RequestNodeVisitor>(
43       RequestRegion, "Request is previously used by nonblocking call here. "));
44   Report->markInteresting(RequestRegion);
45
46   BReporter.emitReport(std::move(Report));
47 }
48
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. "};
55
56   auto Report =
57       llvm::make_unique<BugReport>(*MissingWaitBugType, ErrorText, ExplNode);
58
59   SourceRange Range = RequestRegion->sourceRange();
60   if (Range.isValid())
61     Report->addRange(Range);
62   Report->addVisitor(llvm::make_unique<RequestNodeVisitor>(
63       RequestRegion, "Request is previously used by nonblocking call here. "));
64   Report->markInteresting(RequestRegion);
65
66   BReporter.emitReport(std::move(Report));
67 }
68
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. "};
75
76   auto Report =
77       llvm::make_unique<BugReport>(*UnmatchedWaitBugType, ErrorText, ExplNode);
78
79   Report->addRange(CE.getSourceRange());
80   SourceRange Range = RequestRegion->sourceRange();
81   if (Range.isValid())
82     Report->addRange(Range);
83
84   BReporter.emitReport(std::move(Report));
85 }
86
87 std::shared_ptr<PathDiagnosticPiece>
88 MPIBugReporter::RequestNodeVisitor::VisitNode(const ExplodedNode *N,
89                                               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       N->getFirstPred()->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 = N->getFirstPred()->getLocation();
104     PathDiagnosticLocation L =
105         PathDiagnosticLocation::create(P, BRC.getSourceManager());
106
107     return std::make_shared<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