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 20 namespace clang { 21 namespace ento { 22 namespace mpi { 23 24 void 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 50 void 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 70 void 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 88 std::shared_ptr<PathDiagnosticPiece> 89 MPIBugReporter::RequestNodeVisitor::VisitNode(const ExplodedNode *N, 90 BugReporterContext &BRC, 91 BugReport &BR) { 92 93 if (IsNodeFound) 94 return nullptr; 95 96 const Request *const Req = N->getState()->get<RequestMap>(RequestRegion); 97 const Request *const PrevReq = 98 N->getFirstPred()->getState()->get<RequestMap>(RequestRegion); 99 100 // Check if request was previously unused or in a different state. 101 if ((Req && !PrevReq) || (Req->CurrentState != PrevReq->CurrentState)) { 102 IsNodeFound = true; 103 104 ProgramPoint P = N->getFirstPred()->getLocation(); 105 PathDiagnosticLocation L = 106 PathDiagnosticLocation::create(P, BRC.getSourceManager()); 107 108 return std::make_shared<PathDiagnosticEventPiece>(L, ErrorText); 109 } 110 111 return nullptr; 112 } 113 114 } // end of namespace: mpi 115 } // end of namespace: ento 116 } // end of namespace: clang 117