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 "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h" 17 18 namespace clang { 19 namespace ento { 20 namespace mpi { 21 22 void MPIBugReporter::reportDoubleNonblocking( 23 const CallEvent &MPICallEvent, const ento::mpi::Request &Req, 24 const MemRegion *const RequestRegion, 25 const ExplodedNode *const ExplNode, 26 BugReporter &BReporter) const { 27 28 std::string ErrorText; 29 ErrorText = "Double nonblocking on request " + 30 RequestRegion->getDescriptiveName() + ". "; 31 32 auto Report = std::make_unique<PathSensitiveBugReport>( 33 DoubleNonblockingBugType, ErrorText, ExplNode); 34 35 Report->addRange(MPICallEvent.getSourceRange()); 36 SourceRange Range = RequestRegion->sourceRange(); 37 38 if (Range.isValid()) 39 Report->addRange(Range); 40 41 Report->addVisitor(std::make_unique<RequestNodeVisitor>( 42 RequestRegion, "Request is previously used by nonblocking call here. ")); 43 Report->markInteresting(RequestRegion); 44 45 BReporter.emitReport(std::move(Report)); 46 } 47 48 void MPIBugReporter::reportMissingWait( 49 const ento::mpi::Request &Req, const MemRegion *const RequestRegion, 50 const ExplodedNode *const ExplNode, 51 BugReporter &BReporter) const { 52 std::string ErrorText{"Request " + RequestRegion->getDescriptiveName() + 53 " has no matching wait. "}; 54 55 auto Report = std::make_unique<PathSensitiveBugReport>(MissingWaitBugType, 56 ErrorText, ExplNode); 57 58 SourceRange Range = RequestRegion->sourceRange(); 59 if (Range.isValid()) 60 Report->addRange(Range); 61 Report->addVisitor(std::make_unique<RequestNodeVisitor>( 62 RequestRegion, "Request is previously used by nonblocking call here. ")); 63 Report->markInteresting(RequestRegion); 64 65 BReporter.emitReport(std::move(Report)); 66 } 67 68 void MPIBugReporter::reportUnmatchedWait( 69 const CallEvent &CE, const clang::ento::MemRegion *const RequestRegion, 70 const ExplodedNode *const ExplNode, 71 BugReporter &BReporter) const { 72 std::string ErrorText{"Request " + RequestRegion->getDescriptiveName() + 73 " has no matching nonblocking call. "}; 74 75 auto Report = std::make_unique<PathSensitiveBugReport>(UnmatchedWaitBugType, 76 ErrorText, ExplNode); 77 78 Report->addRange(CE.getSourceRange()); 79 SourceRange Range = RequestRegion->sourceRange(); 80 if (Range.isValid()) 81 Report->addRange(Range); 82 83 BReporter.emitReport(std::move(Report)); 84 } 85 86 PathDiagnosticPieceRef 87 MPIBugReporter::RequestNodeVisitor::VisitNode(const ExplodedNode *N, 88 BugReporterContext &BRC, 89 PathSensitiveBugReport &BR) { 90 91 if (IsNodeFound) 92 return nullptr; 93 94 const Request *const Req = N->getState()->get<RequestMap>(RequestRegion); 95 assert(Req && "The region must be tracked and alive, given that we've " 96 "just emitted a report against it"); 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 (!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