47 #include "llvm/Support/raw_ostream.h"
49 using namespace clang;
58 class ObjCSelfInitChecker :
public Checker< check::PostObjCMessage,
59 check::PostStmt<ObjCIvarRefExpr>,
60 check::PreStmt<ReturnStmt>,
65 mutable std::unique_ptr<BugType> BT;
68 const char *errorStr)
const;
71 ObjCSelfInitChecker() {}
75 void checkLocation(
SVal location,
bool isLoad,
const Stmt *
S,
83 const char *NL,
const char *Sep)
const override;
94 SelfFlag_InitRes = 0x2
109 if (
const unsigned *attachedFlags = state->get<SelfFlag>(sym))
111 return SelfFlag_None;
122 state = state->set<SelfFlag>(sym,
getSelfFlags(val, state) | flag);
145 const char *errorStr)
const {
149 if (!C.
getState()->get<CalledInit>())
161 BT.reset(
new BugType(
this,
"Missing \"self = [(super or self) init...]\"",
163 C.
emitReport(llvm::make_unique<BugReport>(*BT, errorStr, N));
166 void ObjCSelfInitChecker::checkPostObjCMessage(
const ObjCMethodCall &Msg,
184 state = state->set<CalledInit>(
true);
206 "Instance variable used while 'self' is not set to the result of "
207 "'[(super or self) init...]'");
210 void ObjCSelfInitChecker::checkPreStmt(
const ReturnStmt *
S,
218 "Returning 'self' while it is not set to the result of "
219 "'[(super or self) init...]'");
238 void ObjCSelfInitChecker::checkPreCall(
const CallEvent &CE,
252 for (
unsigned i = 0; i <
NumArgs; ++i) {
266 void ObjCSelfInitChecker::checkPostCall(
const CallEvent &CE,
277 state = state->remove<PreCallSelfFlags>();
280 for (
unsigned i = 0; i <
NumArgs; ++i) {
301 void ObjCSelfInitChecker::checkLocation(
SVal location,
bool isLoad,
317 void ObjCSelfInitChecker::checkBind(
SVal loc,
SVal val,
const Stmt *S,
331 State = State->remove<CalledInit>();
333 State = State->remove<SelfFlag>(sym);
338 void ObjCSelfInitChecker::printState(raw_ostream &Out,
ProgramStateRef State,
339 const char *NL,
const char *Sep)
const {
340 SelfFlagTy FlagMap = State->get<SelfFlag>();
341 bool DidCallInit = State->get<CalledInit>();
344 if (FlagMap.isEmpty() && !DidCallInit && !PreCallFlags)
347 Out << Sep << NL << *
this <<
" :" << NL;
350 Out <<
" An init method has been called." << NL;
352 if (PreCallFlags != SelfFlag_None) {
353 if (PreCallFlags & SelfFlag_Self) {
354 Out <<
" An argument of the current call came from the 'self' variable."
357 if (PreCallFlags & SelfFlag_InitRes) {
358 Out <<
" An argument of the current call came from an init method."
366 Out <<
I->first <<
" : ";
368 if (
I->second == SelfFlag_None)
371 if (
I->second & SelfFlag_Self)
372 Out <<
"self variable";
374 if (
I->second & SelfFlag_InitRes) {
375 if (
I->second != SelfFlag_InitRes)
377 Out <<
"result of init method";
404 if (II == NSObjectII)
407 return ID !=
nullptr;
virtual SVal getArgSVal(unsigned Index) const
Returns the value of a given argument at the time of the call.
const Expr * getBase() const
const char *const CoreFoundationObjectiveC
ExplodedNode * generateErrorNode(ProgramStateRef State=nullptr, const ProgramPointTag *Tag=nullptr)
Generate a transition to a node that will be used to report an error.
ObjCInterfaceDecl * getClassInterface()
const MemRegion * stripCasts(bool StripBaseCasts=true) const
Get the underlining region and strip casts.
IdentifierInfo * getIdentifier() const
getIdentifier - Get the identifier that names this declaration, if there is one.
ExplodedNode * addTransition(ProgramStateRef State=nullptr, const ProgramPointTag *Tag=nullptr)
Generates a new transition in the program state graph (ExplodedGraph).
ObjCMethodDecl - Represents an instance or class method declaration.
const ImplicitParamDecl * getSelfDecl() const
Return the ImplicitParamDecl* associated with 'self' if this AnalysisDeclContext wraps an ObjCMethodD...
One of these records is kept for each identifier that is lexed.
static bool isInvalidSelf(const Expr *E, CheckerContext &C)
Returns true of the value of the expression is the object that 'self' points to and is an object that...
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
AnalysisDeclContext contains the context data for the function or method under analysis.
i32 captured_struct **param SharedsTy A type which contains references the shared variables *param Shareds Context with the list of shared variables from the p *TaskFunction *param Data Additional data for task generation like final * state
static bool isInitMessage(const ObjCMethodCall &Msg)
static bool isInitializationMethod(const ObjCMethodDecl *MD)
Represents any expression that calls an Objective-C method.
ObjCMethodFamily getMethodFamily() const
Determines the family of this method.
static void addSelfFlag(ProgramStateRef state, SVal val, SelfFlagEnum flag, CheckerContext &C)
static SelfFlagEnum getSelfFlags(SVal val, ProgramStateRef state)
A call receiving a reference to 'self' invalidates the object that 'self' contains.
const Decl * getDecl() const
Represents an ObjC class declaration.
detail::InMemoryDirectory::const_iterator I
#define REGISTER_MAP_WITH_PROGRAMSTATE(Name, Key, Value)
Declares an immutable map of type NameTy, suitable for placement into the ProgramState.
Expr - This represents one expression.
const ProgramStateRef & getState() const
static bool shouldRunOnFunctionOrMethod(const NamedDecl *ND)
Optional< T > getAs() const
Convert to the specified SVal type, returning None if this SVal is not of the desired type...
ReturnStmt - This represents a return, optionally of an expression: return; return 4;...
class LLVM_ALIGNAS(8) TemplateSpecializationType unsigned NumArgs
Represents a type template specialization; the template must be a class template, a type alias templa...
ObjCMethodFamily getMethodFamily() const
void emitReport(std::unique_ptr< BugReport > R)
Emit the diagnostics report.
static bool hasSelfFlag(SVal val, SelfFlagEnum flag, CheckerContext &C)
#define REGISTER_TRAIT_WITH_PROGRAMSTATE(Name, Type)
Declares a program state trait for type Type called Name, and introduce a typedef named NameTy...
CHECKER * registerChecker()
Used to register checkers.
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
const TemplateArgument * iterator
SVal - This represents a symbolic expression, which can be either an L-value or an R-value...
static bool isSelfVar(SVal location, CheckerContext &C)
Returns true if the location is 'self'.
detail::InMemoryDirectory::const_iterator E
const Expr * getRetValue() const
Represents an abstract call to a function or method along a particular path.
ObjCIvarRefExpr - A reference to an ObjC instance variable.
AnalysisDeclContext * getCurrentAnalysisDeclContext() const
virtual unsigned getNumArgs() const =0
Returns the number of arguments (explicit and implicit).
SymbolRef getAsSymbol(bool IncludeBaseRegions=false) const
If this SVal wraps a symbol return that SymbolRef.
ObjCInterfaceDecl * getSuperClass() const
NamedDecl - This represents a decl with a name.
virtual const ObjCMessageExpr * getOriginExpr() const
SVal getReturnValue() const
Returns the return value of the call.
T castAs() const
Convert to the specified SVal type, asserting that this SVal is of the desired type.
const LocationContext * getLocationContext() const