//===-- 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,
PathSensitiveBugReport &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