24#include "llvm/ADT/StringSwitch.h"
25#include "llvm/Support/raw_ostream.h"
31class MacOSXAPIChecker :
public Checker< check::PreStmt<CallExpr> > {
32 const BugType BT_dispatchOnce{
this,
"Improper use of 'dispatch_once'",
35 static const ObjCIvarRegion *getParentIvarRegion(
const MemRegion *R);
38 void checkPreStmt(
const CallExpr *CE, CheckerContext &
C)
const;
40 void CheckDispatchOnce(CheckerContext &
C,
const CallExpr *CE,
41 StringRef FName)
const;
43 typedef void (MacOSXAPIChecker::*SubChecker)(CheckerContext &,
45 StringRef FName)
const;
54MacOSXAPIChecker::getParentIvarRegion(
const MemRegion *R) {
55 const SubRegion *SR = dyn_cast<SubRegion>(R);
57 if (
const ObjCIvarRegion *IR = dyn_cast<ObjCIvarRegion>(SR))
64void MacOSXAPIChecker::CheckDispatchOnce(CheckerContext &
C,
const CallExpr *CE,
65 StringRef FName)
const {
71 const MemRegion *R =
C.getSVal(CE->
getArg(0)).getAsRegion();
85 StringRef TrimmedFName = FName.ltrim(
'_');
86 if (TrimmedFName != FName)
91 llvm::raw_svector_ostream os(S);
92 bool SuggestStatic =
false;
93 os <<
"Call to '" << FName <<
"' uses";
94 if (
const VarRegion *VR = dyn_cast<VarRegion>(R->
getBaseRegion())) {
95 const VarDecl *VD = VR->getDecl();
105 os <<
" memory within";
107 os <<
" the block variable '";
109 os <<
" the local variable '";
110 os << VR->getDecl()->getName() <<
'\'';
111 SuggestStatic =
true;
112 }
else if (
const ObjCIvarRegion *IVR = getParentIvarRegion(R)) {
114 os <<
" memory within";
115 os <<
" the instance variable '" << IVR->getDecl()->getName() <<
'\'';
117 os <<
" heap-allocated memory";
126 os <<
" stack allocated memory";
128 os <<
" for the predicate value. Using such transient memory for "
129 "the predicate is potentially dangerous.";
131 os <<
" Perhaps you intended to declare the variable as 'static'?";
133 ExplodedNode *N =
C.generateErrorNode();
138 std::make_unique<PathSensitiveBugReport>(BT_dispatchOnce, os.str(), N);
140 C.emitReport(std::move(report));
147void MacOSXAPIChecker::checkPreStmt(
const CallExpr *CE,
148 CheckerContext &
C)
const {
149 StringRef Name =
C.getCalleeName(CE);
154 llvm::StringSwitch<SubChecker>(Name)
155 .Cases(
"dispatch_once",
158 &MacOSXAPIChecker::CheckDispatchOnce)
162 (this->*SC)(
C, CE, Name);
169void ento::registerMacOSXAPIChecker(CheckerManager &mgr) {
173bool ento::shouldRegisterMacOSXAPIChecker(
const CheckerManager &mgr) {
Expr * getArg(unsigned Arg)
getArg - Return the specified argument.
SourceLocation getBeginLoc() const
unsigned getNumArgs() const
getNumArgs - Return the number of actual arguments to this call.
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
bool isStaticLocal() const
Returns true if a variable with function scope is a static local variable.
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.
MemRegion - The root abstract class for all memory regions.
LLVM_ATTRIBUTE_RETURNS_NONNULL const MemSpaceRegion * getMemorySpace(ProgramStateRef State) const
Returns the most specific memory space for this memory region in the given ProgramStateRef.
LLVM_ATTRIBUTE_RETURNS_NONNULL const MemRegion * getBaseRegion() const
LLVM_ATTRIBUTE_RETURNS_NONNULL const MemRegion * getSuperRegion() const
const char *const AppleAPIMisuse
The JSON file list parser is used to communicate input to InstallAPI.
bool isa(CodeGen::Address addr)