Home | History | Annotate | Download | only in MPI-Checker
      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 PathDiagnosticPiece *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