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