105 lines
3.9 KiB
C
105 lines
3.9 KiB
C
|
//===-- MPIChecker.h - Verify MPI API usage- --------------------*- 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 the main class of MPI-Checker which serves as an entry
|
||
|
/// point. It is created once for each translation unit analysed.
|
||
|
/// The checker defines path-sensitive checks, to verify correct usage of the
|
||
|
/// MPI API.
|
||
|
///
|
||
|
//===----------------------------------------------------------------------===//
|
||
|
|
||
|
#ifndef LLVM_CLANG_LIB_STATICANALYZER_CHECKERS_MPICHECKER_MPICHECKER_H
|
||
|
#define LLVM_CLANG_LIB_STATICANALYZER_CHECKERS_MPICHECKER_MPICHECKER_H
|
||
|
|
||
|
#include "MPIBugReporter.h"
|
||
|
#include "MPITypes.h"
|
||
|
#include "clang/StaticAnalyzer/Checkers/MPIFunctionClassifier.h"
|
||
|
#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
|
||
|
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
|
||
|
|
||
|
namespace clang {
|
||
|
namespace ento {
|
||
|
namespace mpi {
|
||
|
|
||
|
class MPIChecker : public Checker<check::PreCall, check::DeadSymbols> {
|
||
|
public:
|
||
|
MPIChecker() : BReporter(*this) {}
|
||
|
|
||
|
// path-sensitive callbacks
|
||
|
void checkPreCall(const CallEvent &CE, CheckerContext &Ctx) const {
|
||
|
dynamicInit(Ctx);
|
||
|
checkUnmatchedWaits(CE, Ctx);
|
||
|
checkDoubleNonblocking(CE, Ctx);
|
||
|
}
|
||
|
|
||
|
void checkDeadSymbols(SymbolReaper &SymReaper, CheckerContext &Ctx) const {
|
||
|
dynamicInit(Ctx);
|
||
|
checkMissingWaits(SymReaper, Ctx);
|
||
|
}
|
||
|
|
||
|
void dynamicInit(CheckerContext &Ctx) const {
|
||
|
if (FuncClassifier)
|
||
|
return;
|
||
|
const_cast<std::unique_ptr<MPIFunctionClassifier> &>(FuncClassifier)
|
||
|
.reset(new MPIFunctionClassifier{Ctx.getASTContext()});
|
||
|
}
|
||
|
|
||
|
/// Checks if a request is used by nonblocking calls multiple times
|
||
|
/// in sequence without intermediate wait. The check contains a guard,
|
||
|
/// in order to only inspect nonblocking functions.
|
||
|
///
|
||
|
/// \param PreCallEvent MPI call to verify
|
||
|
void checkDoubleNonblocking(const clang::ento::CallEvent &PreCallEvent,
|
||
|
clang::ento::CheckerContext &Ctx) const;
|
||
|
|
||
|
/// Checks if the request used by the wait function was not used at all
|
||
|
/// before. The check contains a guard, in order to only inspect wait
|
||
|
/// functions.
|
||
|
///
|
||
|
/// \param PreCallEvent MPI call to verify
|
||
|
void checkUnmatchedWaits(const clang::ento::CallEvent &PreCallEvent,
|
||
|
clang::ento::CheckerContext &Ctx) const;
|
||
|
|
||
|
/// Check if a nonblocking call is not matched by a wait.
|
||
|
/// If a memory region is not alive and the last function using the
|
||
|
/// request was a nonblocking call, this is rated as a missing wait.
|
||
|
void checkMissingWaits(clang::ento::SymbolReaper &SymReaper,
|
||
|
clang::ento::CheckerContext &Ctx) const;
|
||
|
|
||
|
private:
|
||
|
/// Collects all memory regions of a request(array) used by a wait
|
||
|
/// function. If the wait function uses a single request, this is a single
|
||
|
/// region. For wait functions using multiple requests, multiple regions
|
||
|
/// representing elements in the array are collected.
|
||
|
///
|
||
|
/// \param ReqRegions vector the regions get pushed into
|
||
|
/// \param MR top most region to iterate
|
||
|
/// \param CE MPI wait call using the request(s)
|
||
|
void allRegionsUsedByWait(
|
||
|
llvm::SmallVector<const clang::ento::MemRegion *, 2> &ReqRegions,
|
||
|
const clang::ento::MemRegion *const MR, const clang::ento::CallEvent &CE,
|
||
|
clang::ento::CheckerContext &Ctx) const;
|
||
|
|
||
|
/// Returns the memory region used by a wait function.
|
||
|
/// Distinguishes between MPI_Wait and MPI_Waitall.
|
||
|
///
|
||
|
/// \param CE MPI wait call
|
||
|
const clang::ento::MemRegion *
|
||
|
topRegionUsedByWait(const clang::ento::CallEvent &CE) const;
|
||
|
|
||
|
const std::unique_ptr<MPIFunctionClassifier> FuncClassifier;
|
||
|
MPIBugReporter BReporter;
|
||
|
};
|
||
|
|
||
|
} // end of namespace: mpi
|
||
|
} // end of namespace: ento
|
||
|
} // end of namespace: clang
|
||
|
|
||
|
#endif
|