Home | History | Annotate | Line # | Download | only in MPI-Checker
      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 "MPIChecker.h"
     17 #include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
     18 
     19 namespace clang {
     20 namespace ento {
     21 namespace mpi {
     22 
     23 void MPIBugReporter::reportDoubleNonblocking(
     24     const CallEvent &MPICallEvent, const ento::mpi::Request &Req,
     25     const MemRegion *const RequestRegion,
     26     const ExplodedNode *const ExplNode,
     27     BugReporter &BReporter) const {
     28 
     29   std::string ErrorText;
     30   ErrorText = "Double nonblocking on request " +
     31               RequestRegion->getDescriptiveName() + ". ";
     32 
     33   auto Report = std::make_unique<PathSensitiveBugReport>(
     34       *DoubleNonblockingBugType, ErrorText, ExplNode);
     35 
     36   Report->addRange(MPICallEvent.getSourceRange());
     37   SourceRange Range = RequestRegion->sourceRange();
     38 
     39   if (Range.isValid())
     40     Report->addRange(Range);
     41 
     42   Report->addVisitor(std::make_unique<RequestNodeVisitor>(
     43       RequestRegion, "Request is previously used by nonblocking call here. "));
     44   Report->markInteresting(RequestRegion);
     45 
     46   BReporter.emitReport(std::move(Report));
     47 }
     48 
     49 void MPIBugReporter::reportMissingWait(
     50     const ento::mpi::Request &Req, const MemRegion *const RequestRegion,
     51     const ExplodedNode *const ExplNode,
     52     BugReporter &BReporter) const {
     53   std::string ErrorText{"Request " + RequestRegion->getDescriptiveName() +
     54                         " has no matching wait. "};
     55 
     56   auto Report = std::make_unique<PathSensitiveBugReport>(*MissingWaitBugType,
     57                                                          ErrorText, ExplNode);
     58 
     59   SourceRange Range = RequestRegion->sourceRange();
     60   if (Range.isValid())
     61     Report->addRange(Range);
     62   Report->addVisitor(std::make_unique<RequestNodeVisitor>(
     63       RequestRegion, "Request is previously used by nonblocking call here. "));
     64   Report->markInteresting(RequestRegion);
     65 
     66   BReporter.emitReport(std::move(Report));
     67 }
     68 
     69 void MPIBugReporter::reportUnmatchedWait(
     70     const CallEvent &CE, const clang::ento::MemRegion *const RequestRegion,
     71     const ExplodedNode *const ExplNode,
     72     BugReporter &BReporter) const {
     73   std::string ErrorText{"Request " + RequestRegion->getDescriptiveName() +
     74                         " has no matching nonblocking call. "};
     75 
     76   auto Report = std::make_unique<PathSensitiveBugReport>(*UnmatchedWaitBugType,
     77                                                          ErrorText, ExplNode);
     78 
     79   Report->addRange(CE.getSourceRange());
     80   SourceRange Range = RequestRegion->sourceRange();
     81   if (Range.isValid())
     82     Report->addRange(Range);
     83 
     84   BReporter.emitReport(std::move(Report));
     85 }
     86 
     87 PathDiagnosticPieceRef
     88 MPIBugReporter::RequestNodeVisitor::VisitNode(const ExplodedNode *N,
     89                                               BugReporterContext &BRC,
     90                                               PathSensitiveBugReport &BR) {
     91 
     92   if (IsNodeFound)
     93     return nullptr;
     94 
     95   const Request *const Req = N->getState()->get<RequestMap>(RequestRegion);
     96   assert(Req && "The region must be tracked and alive, given that we've "
     97                 "just emitted a report against it");
     98   const Request *const PrevReq =
     99       N->getFirstPred()->getState()->get<RequestMap>(RequestRegion);
    100 
    101   // Check if request was previously unused or in a different state.
    102   if (!PrevReq || (Req->CurrentState != PrevReq->CurrentState)) {
    103     IsNodeFound = true;
    104 
    105     ProgramPoint P = N->getFirstPred()->getLocation();
    106     PathDiagnosticLocation L =
    107         PathDiagnosticLocation::create(P, BRC.getSourceManager());
    108 
    109     return std::make_shared<PathDiagnosticEventPiece>(L, ErrorText);
    110   }
    111 
    112   return nullptr;
    113 }
    114 
    115 } // end of namespace: mpi
    116 } // end of namespace: ento
    117 } // end of namespace: clang
    118