text: //===-- MPIBugReporter.h - bug reporter -----------------------*- C++ -*-===//
  //
  // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  // See https://llvm.org/LICENSE.txt for license information.
  // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  //
  //===----------------------------------------------------------------------===//
  ///
  /// \file
  /// This file defines prefabricated reports which are emitted in
  /// case of MPI related bugs, detected by path-sensitive analysis.
  ///
  //===----------------------------------------------------------------------===//
  
  #ifndef LLVM_CLANG_LIB_STATICANALYZER_CHECKERS_MPICHECKER_MPIBUGREPORTER_H
  #define LLVM_CLANG_LIB_STATICANALYZER_CHECKERS_MPICHECKER_MPIBUGREPORTER_H
  
  #include "MPITypes.h"
  #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
  
  namespace clang {
  namespace ento {
  namespace mpi {
  
  class MPIBugReporter {
  public:
    MPIBugReporter(const CheckerBase &CB) {
      UnmatchedWaitBugType.reset(new BugType(&CB, "Unmatched wait", MPIError));
      DoubleNonblockingBugType.reset(
          new BugType(&CB, "Double nonblocking", MPIError));
      MissingWaitBugType.reset(new BugType(&CB, "Missing wait", MPIError));
    }
  
    /// Report duplicate request use by nonblocking calls without intermediate
    /// wait.
    ///
    /// \param MPICallEvent MPI call that caused the double nonblocking
    /// \param Req request that was used by two nonblocking calls in sequence
    /// \param RequestRegion memory region of the request
    /// \param ExplNode node in the graph the bug appeared at
    /// \param BReporter bug reporter for current context
    void reportDoubleNonblocking(const CallEvent &MPICallEvent,
                                 const Request &Req,
                                 const MemRegion *const RequestRegion,
                                 const ExplodedNode *const ExplNode,
                                BugReporter &BReporter) const;
  
    /// Report a missing wait for a nonblocking call.
    ///
    /// \param Req request that is not matched by a wait
    /// \param RequestRegion memory region of the request
    /// \param ExplNode node in the graph the bug appeared at
    /// \param BReporter bug reporter for current context
    void reportMissingWait(const Request &Req,
                           const MemRegion *const RequestRegion,
                           const ExplodedNode *const ExplNode,
                           BugReporter &BReporter) const;
  
    /// Report a wait on a request that has not been used at all before.
    ///
    /// \param CE wait call that uses the request
    /// \param RequestRegion memory region of the request
    /// \param ExplNode node in the graph the bug appeared at
    /// \param BReporter bug reporter for current context
    void reportUnmatchedWait(const CallEvent &CE,
                             const MemRegion *const RequestRegion,
                             const ExplodedNode *const ExplNode,
                             BugReporter &BReporter) const;
  
  private:
    const std::string MPIError = "MPI Error";
  
    // path-sensitive bug types
    std::unique_ptr<BugType> UnmatchedWaitBugType;
    std::unique_ptr<BugType> MissingWaitBugType;
    std::unique_ptr<BugType> DoubleNonblockingBugType;
  
    /// Bug visitor class to find the node where the request region was previously
    /// used in order to include it into the BugReport path.
    class RequestNodeVisitor : public BugReporterVisitor {
    public:
      RequestNodeVisitor(const MemRegion *const MemoryRegion,
                         const std::string &ErrText)
          : RequestRegion(MemoryRegion), ErrorText(ErrText) {}
  
      void Profile(llvm::FoldingSetNodeID &ID) const override {
        static int X = 0;
        ID.AddPointer(&X);
        ID.AddPointer(RequestRegion);
      }
  
      PathDiagnosticPieceRef VisitNode(const ExplodedNode *N,
                                       BugReporterContext &BRC,
                                       BugReport &BR) override;
  
    private:
      const MemRegion *const RequestRegion;
      bool IsNodeFound = false;
      std::string ErrorText;
    };
  };
  
  } // end of namespace: mpi
  } // end of namespace: ento
  } // end of namespace: clang
  
  #endif
  