20#include "llvm/ADT/StringRef.h"
21#include "llvm/Support/FormatVariadic.h"
27class PointerSubChecker
28 :
public Checker< check::PreStmt<BinaryOperator> > {
29 const BugType BT{
this,
"Pointer subtraction"};
30 const llvm::StringLiteral Msg_MemRegionDifferent =
31 "Subtraction of two pointers that do not point into the same array "
32 "is undefined behavior.";
35 void checkPreStmt(
const BinaryOperator *B, CheckerContext &
C)
const;
46 SVal LV =
C.getSVal(B->
getLHS());
47 SVal RV =
C.getSVal(B->
getRHS());
67 const auto *ElemLR = dyn_cast<ElementRegion>(LR);
68 const auto *ElemRR = dyn_cast<ElementRegion>(RR);
71 if (ElemLR && ElemLR->getSuperRegion() == RR)
74 if (ElemRR && ElemRR->getSuperRegion() == LR)
77 const ValueDecl *DiffDeclL =
nullptr;
78 const ValueDecl *DiffDeclR =
nullptr;
80 if (ElemLR && ElemRR) {
81 const MemRegion *SuperLR = ElemLR->getSuperRegion();
82 const MemRegion *SuperRR = ElemRR->getSuperRegion();
83 if (SuperLR == SuperRR)
88 if (
const auto *SuperDLR = dyn_cast<DeclRegion>(SuperLR))
89 DiffDeclL = SuperDLR->getDecl();
90 if (
const auto *SuperDRR = dyn_cast<DeclRegion>(SuperRR))
91 DiffDeclR = SuperDRR->getDecl();
94 if (ExplodedNode *N =
C.generateNonFatalErrorNode()) {
96 std::make_unique<PathSensitiveBugReport>(BT, Msg_MemRegionDifferent, N);
102 if (DiffDeclL != DiffDeclR) {
103 auto AddNote = [&R, &
C](
const ValueDecl *D, StringRef SideStr) {
105 std::string Msg = llvm::formatv(
106 "{0} at the {1}-hand side of subtraction",
107 D->getType()->isArrayType() ?
"Array" :
"Object", SideStr);
108 R->addNote(Msg, {D,
C.getSourceManager()});
111 AddNote(DiffDeclL,
"left");
112 AddNote(DiffDeclR,
"right");
114 C.emitReport(std::move(R));
118void ento::registerPointerSubChecker(CheckerManager &mgr) {
122bool ento::shouldRegisterPointerSubChecker(
const CheckerManager &mgr) {
A builtin binary operation expression such as "x + y" or "x <= y".
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
bool isPointerType() const
CHECKER * registerChecker(AT &&...Args)
Register a single-part checker (derived from Checker): construct its singleton instance,...
Simple checker classes that implement one frontend (i.e.
const SymbolicRegion * getSymbolicBase() const
If this is a symbolic region, returns the region.
const MemRegion * getAsRegion() const
The JSON file list parser is used to communicate input to InstallAPI.
bool isa(CodeGen::Address addr)