Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[analyzer] Reapply r271907 (2nd try).
Second try at reapplying "[analyzer] Add checker for correct usage of MPI API in C and C++." Special thanks to Dan Liew for helping test the fix for the template specialization compiler error with gcc. The original patch is by Alexander Droste! Differential Revision: http://reviews.llvm.org/D12761 llvm-svn: 271977
- Loading branch information
1 parent
a8c1d8b
commit cc1fb35
Showing
15 changed files
with
1,548 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
112 changes: 112 additions & 0 deletions
112
clang/lib/StaticAnalyzer/Checkers/MPI-Checker/MPIBugReporter.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
//===-- MPIBugReporter.cpp - bug reporter -----------------------*- C++ -*-===// | ||
// | ||
// The LLVM Compiler Infrastructure | ||
// | ||
// This file is distributed under the University of Illinois Open Source | ||
// License. See LICENSE.TXT for details. | ||
// | ||
//===----------------------------------------------------------------------===// | ||
/// | ||
/// \file | ||
/// This file defines prefabricated reports which are emitted in | ||
/// case of MPI related bugs, detected by path-sensitive analysis. | ||
/// | ||
//===----------------------------------------------------------------------===// | ||
|
||
#include "MPIBugReporter.h" | ||
#include "MPIChecker.h" | ||
#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h" | ||
|
||
namespace clang { | ||
namespace ento { | ||
namespace mpi { | ||
|
||
void MPIBugReporter::reportDoubleNonblocking( | ||
const CallEvent &MPICallEvent, const ento::mpi::Request &Req, | ||
const MemRegion *const RequestRegion, | ||
const ExplodedNode *const ExplNode) const { | ||
|
||
std::string ErrorText; | ||
ErrorText = "Double nonblocking on request " + | ||
RequestRegion->getDescriptiveName() + ". "; | ||
|
||
auto Report = llvm::make_unique<BugReport>(*DoubleNonblockingBugType, | ||
ErrorText, ExplNode); | ||
|
||
Report->addRange(MPICallEvent.getSourceRange()); | ||
SourceRange Range = RequestRegion->sourceRange(); | ||
|
||
if (Range.isValid()) | ||
Report->addRange(Range); | ||
|
||
Report->addVisitor(llvm::make_unique<RequestNodeVisitor>( | ||
RequestRegion, "Request is previously used by nonblocking call here. ")); | ||
Report->markInteresting(RequestRegion); | ||
|
||
BReporter.emitReport(std::move(Report)); | ||
} | ||
|
||
void MPIBugReporter::reportMissingWait( | ||
const ento::mpi::Request &Req, const MemRegion *const RequestRegion, | ||
const ExplodedNode *const ExplNode) const { | ||
std::string ErrorText{"Request " + RequestRegion->getDescriptiveName() + | ||
" has no matching wait. "}; | ||
|
||
auto Report = | ||
llvm::make_unique<BugReport>(*MissingWaitBugType, ErrorText, ExplNode); | ||
|
||
SourceRange Range = RequestRegion->sourceRange(); | ||
if (Range.isValid()) | ||
Report->addRange(Range); | ||
Report->addVisitor(llvm::make_unique<RequestNodeVisitor>( | ||
RequestRegion, "Request is previously used by nonblocking call here. ")); | ||
Report->markInteresting(RequestRegion); | ||
|
||
BReporter.emitReport(std::move(Report)); | ||
} | ||
|
||
void MPIBugReporter::reportUnmatchedWait( | ||
const CallEvent &CE, const clang::ento::MemRegion *const RequestRegion, | ||
const ExplodedNode *const ExplNode) const { | ||
std::string ErrorText{"Request " + RequestRegion->getDescriptiveName() + | ||
" has no matching nonblocking call. "}; | ||
|
||
auto Report = | ||
llvm::make_unique<BugReport>(*UnmatchedWaitBugType, ErrorText, ExplNode); | ||
|
||
Report->addRange(CE.getSourceRange()); | ||
SourceRange Range = RequestRegion->sourceRange(); | ||
if (Range.isValid()) | ||
Report->addRange(Range); | ||
|
||
BReporter.emitReport(std::move(Report)); | ||
} | ||
|
||
PathDiagnosticPiece *MPIBugReporter::RequestNodeVisitor::VisitNode( | ||
const ExplodedNode *N, const ExplodedNode *PrevN, BugReporterContext &BRC, | ||
BugReport &BR) { | ||
|
||
if (IsNodeFound) | ||
return nullptr; | ||
|
||
const Request *const Req = N->getState()->get<RequestMap>(RequestRegion); | ||
const Request *const PrevReq = | ||
PrevN->getState()->get<RequestMap>(RequestRegion); | ||
|
||
// Check if request was previously unused or in a different state. | ||
if ((Req && !PrevReq) || (Req->CurrentState != PrevReq->CurrentState)) { | ||
IsNodeFound = true; | ||
|
||
ProgramPoint P = PrevN->getLocation(); | ||
PathDiagnosticLocation L = | ||
PathDiagnosticLocation::create(P, BRC.getSourceManager()); | ||
|
||
return new PathDiagnosticEventPiece(L, ErrorText); | ||
} | ||
|
||
return nullptr; | ||
} | ||
|
||
} // end of namespace: mpi | ||
} // end of namespace: ento | ||
} // end of namespace: clang |
110 changes: 110 additions & 0 deletions
110
clang/lib/StaticAnalyzer/Checkers/MPI-Checker/MPIBugReporter.h
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
//===-- MPIBugReporter.h - bug reporter -----------------------*- C++ -*-===// | ||
// | ||
// The LLVM Compiler Infrastructure | ||
// | ||
// This file is distributed under the University of Illinois Open Source | ||
// License. See LICENSE.TXT for details. | ||
// | ||
//===----------------------------------------------------------------------===// | ||
/// | ||
/// \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 "MPIFunctionClassifier.h" | ||
#include "MPITypes.h" | ||
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" | ||
|
||
namespace clang { | ||
namespace ento { | ||
namespace mpi { | ||
|
||
class MPIBugReporter { | ||
public: | ||
MPIBugReporter(BugReporter &BR, const CheckerBase &CB, | ||
const MPIFunctionClassifier &FC) | ||
: BReporter{BR} { | ||
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 | ||
void reportDoubleNonblocking(const CallEvent &MPICallEvent, | ||
const Request &Req, | ||
const MemRegion *const RequestRegion, | ||
const ExplodedNode *const ExplNode) const; | ||
|
||
/// Report a missing wait for a nonblocking call. A missing wait report | ||
/// is emitted if a nonblocking call is not matched in the scope of a | ||
/// function. | ||
/// | ||
/// \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 | ||
void reportMissingWait(const Request &Req, | ||
const MemRegion *const RequestRegion, | ||
const ExplodedNode *const ExplNode) const; | ||
|
||
/// Report a wait on a request that has not been used at all before. | ||
/// | ||
/// \param CE wait call that uses the request | ||
/// \param ReqRegion memory region of the request | ||
/// \param ExplNode node in the graph the bug appeared at | ||
void reportUnmatchedWait(const CallEvent &CE, | ||
const MemRegion *const RequestRegion, | ||
const ExplodedNode *const ExplNode) 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; | ||
|
||
BugReporter &BReporter; | ||
|
||
/// 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 BugReporterVisitorImpl<RequestNodeVisitor> { | ||
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); | ||
} | ||
|
||
PathDiagnosticPiece *VisitNode(const ExplodedNode *N, | ||
const ExplodedNode *PrevN, | ||
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 |
Oops, something went wrong.