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
20namespace clang {
21namespace ento {
22namespace mpi {
23
24void 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
50void 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
70void 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
88PathDiagnosticPiece *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