33 #include "llvm/ADT/SmallString.h"
34 #include "llvm/ADT/StringMap.h"
35 #include "llvm/Support/raw_ostream.h"
37 using namespace clang;
41 class APIMisuse :
public BugType {
43 APIMisuse(
const CheckerBase *checker,
const char *name)
44 :
BugType(checker, name,
"API Misuse (Apple)") {}
54 return ID->getIdentifier()->getName();
70 bool IncludeSuperclasses =
true) {
71 static llvm::StringMap<FoundationClass> Classes;
72 if (Classes.empty()) {
84 if (result ==
FC_None && IncludeSuperclasses)
96 class NilArgChecker :
public Checker<check::PreObjCMessage,
97 check::PostStmt<ObjCDictionaryLiteral>,
98 check::PostStmt<ObjCArrayLiteral> > {
99 mutable std::unique_ptr<APIMisuse> BT;
101 mutable llvm::SmallDenseMap<Selector, unsigned, 16> StringSelectors;
102 mutable Selector ArrayWithObjectSel;
104 mutable Selector InsertObjectAtIndexSel;
105 mutable Selector ReplaceObjectAtIndexWithObjectSel;
106 mutable Selector SetObjectAtIndexedSubscriptSel;
107 mutable Selector ArrayByAddingObjectSel;
108 mutable Selector DictionaryWithObjectForKeySel;
109 mutable Selector SetObjectForKeySel;
110 mutable Selector SetObjectForKeyedSubscriptSel;
111 mutable Selector RemoveObjectForKeySel;
113 void warnIfNilExpr(
const Expr *
E,
120 bool CanBeSubscript =
false)
const;
137 void NilArgChecker::warnIfNilExpr(
const Expr *
E,
141 if (State->isNull(C.
getSVal(E)).isConstrainedTrue()) {
153 bool CanBeSubscript)
const {
156 if (!State->isNull(msg.getArgSVal(Arg)).isConstrainedTrue())
161 llvm::raw_svector_ostream os(sbuf);
166 os <<
"Array element cannot be nil";
169 os <<
"Value stored into '";
176 llvm_unreachable(
"Missing foundation class for the subscript expr");
181 os <<
"Value argument ";
184 os <<
"Key argument ";
188 os <<
"' cannot be nil";
192 os <<
"' cannot be nil";
196 generateBugReport(N, os.str(), msg.getArgSourceRange(Arg),
207 BT.reset(
new APIMisuse(
this,
"nil argument"));
209 auto R = llvm::make_unique<BugReport>(*BT, Msg, N);
215 void NilArgChecker::checkPreObjCMessage(
const ObjCMethodCall &msg,
223 static const unsigned InvalidArgIndex =
UINT_MAX;
224 unsigned Arg = InvalidArgIndex;
225 bool CanBeSubscript =
false;
233 if (StringSelectors.empty()) {
248 StringSelectors[KnownSel] = 0;
250 auto I = StringSelectors.find(S);
251 if (
I == StringSelectors.end())
260 if (ArrayWithObjectSel.isNull()) {
264 InsertObjectAtIndexSel =
266 ReplaceObjectAtIndexWithObjectSel =
268 SetObjectAtIndexedSubscriptSel =
273 if (S == ArrayWithObjectSel || S == AddObjectSel ||
274 S == InsertObjectAtIndexSel || S == ArrayByAddingObjectSel) {
276 }
else if (S == SetObjectAtIndexedSubscriptSel) {
278 CanBeSubscript =
true;
279 }
else if (S == ReplaceObjectAtIndexWithObjectSel) {
288 if (DictionaryWithObjectForKeySel.isNull()) {
290 DictionaryWithObjectForKeySel =
293 SetObjectForKeyedSubscriptSel =
298 if (S == DictionaryWithObjectForKeySel || S == SetObjectForKeySel) {
300 warnIfNilArg(C, msg, 1, Class);
301 }
else if (S == SetObjectForKeyedSubscriptSel) {
302 CanBeSubscript =
true;
304 }
else if (S == RemoveObjectForKeySel) {
310 if ((Arg != InvalidArgIndex))
311 warnIfNilArg(C, msg, Arg, Class, CanBeSubscript);
317 for (
unsigned i = 0; i < NumOfElements; ++i) {
318 warnIfNilExpr(AL->
getElement(i),
"Array element cannot be nil", C);
325 for (
unsigned i = 0; i < NumOfElements; ++i) {
327 warnIfNilExpr(Element.
Key,
"Dictionary key cannot be nil", C);
328 warnIfNilExpr(Element.
Value,
"Dictionary value cannot be nil", C);
337 class CFNumberChecker :
public Checker< check::PreStmt<CallExpr> > {
338 mutable std::unique_ptr<APIMisuse> BT;
341 CFNumberChecker() : ICreate(nullptr), IGetValue(nullptr) {}
347 uint64_t SourceSize, uint64_t TargetSize, uint64_t NumberKind);
371 static const unsigned char FixedSize[] = { 8, 16, 32, 64, 32, 64 };
374 return FixedSize[i-1];
398 static const char* GetCFNumberTypeStr(uint64_t i) {
399 static const char*
Names[] = {
400 "kCFNumberSInt8Type",
401 "kCFNumberSInt16Type",
402 "kCFNumberSInt32Type",
403 "kCFNumberSInt64Type",
404 "kCFNumberFloat32Type",
405 "kCFNumberFloat64Type",
407 "kCFNumberShortType",
410 "kCFNumberLongLongType",
411 "kCFNumberFloatType",
412 "kCFNumberDoubleType",
413 "kCFNumberCFIndexType",
414 "kCFNumberNSIntegerType",
415 "kCFNumberCGFloatType"
422 void CFNumberChecker::checkPreStmt(
const CallExpr *CE,
431 ICreate = &Ctx.
Idents.
get(
"CFNumberCreate");
432 IGetValue = &Ctx.
Idents.
get(
"CFNumberGetValue");
440 SVal TheTypeVal = state->getSVal(CE->
getArg(1), LCtx);
448 uint64_t NumberKind = V->
getValue().getLimitedValue();
452 if (!OptCFNumberSize)
455 uint64_t CFNumberSize = *OptCFNumberSize;
460 SVal TheValueExpr = state->getSVal(CE->
getArg(2), LCtx);
482 if (PrimitiveTypeSize == CFNumberSize)
490 llvm::raw_svector_ostream os(sbuf);
494 os << (PrimitiveTypeSize == 8 ?
"An " :
"A ")
495 << PrimitiveTypeSize <<
"-bit integer is used to initialize a "
496 <<
"CFNumber object that represents "
497 << (CFNumberSize == 8 ?
"an " :
"a ")
498 << CFNumberSize <<
"-bit integer; ";
500 os <<
"A CFNumber object that represents "
501 << (CFNumberSize == 8 ?
"an " :
"a ")
502 << CFNumberSize <<
"-bit integer is used to initialize "
503 << (PrimitiveTypeSize == 8 ?
"an " :
"a ")
504 << PrimitiveTypeSize <<
"-bit integer; ";
507 if (PrimitiveTypeSize < CFNumberSize)
508 os << (CFNumberSize - PrimitiveTypeSize)
509 <<
" bits of the CFNumber value will "
510 << (isCreate ?
"be garbage." :
"overwrite adjacent storage.");
512 os << (PrimitiveTypeSize - CFNumberSize)
513 <<
" bits of the integer value will be "
514 << (isCreate ?
"lost." :
"garbage.");
517 BT.reset(
new APIMisuse(
this,
"Bad use of CFNumber APIs"));
519 auto report = llvm::make_unique<BugReport>(*BT, os.str(), N);
530 class CFRetainReleaseChecker :
public Checker< check::PreStmt<CallExpr> > {
531 mutable std::unique_ptr<APIMisuse> BT;
535 CFRetainReleaseChecker()
542 void CFRetainReleaseChecker::checkPreStmt(
const CallExpr *CE,
559 BT.reset(
new APIMisuse(
560 this,
"null passed to CF memory management function"));
565 if (!(FuncII == Retain || FuncII == Release || FuncII ==
MakeCollectable ||
589 std::tie(stateTrue, stateFalse) = state->assume(ArgIsNull);
591 if (stateTrue && !stateFalse) {
596 const char *description;
597 if (FuncII == Retain)
598 description =
"Null pointer argument in call to CFRetain";
599 else if (FuncII == Release)
600 description =
"Null pointer argument in call to CFRelease";
602 description =
"Null pointer argument in call to CFMakeCollectable";
604 description =
"Null pointer argument in call to CFAutorelease";
606 llvm_unreachable(
"impossible case");
608 auto report = llvm::make_unique<BugReport>(*BT, description, N);
624 class ClassReleaseChecker :
public Checker<check::PreObjCMessage> {
629 mutable std::unique_ptr<BugType> BT;
636 void ClassReleaseChecker::checkPreObjCMessage(
const ObjCMethodCall &msg,
639 BT.reset(
new APIMisuse(
640 this,
"message incorrectly sent to class instead of class instance"));
655 if (!(S == releaseS || S == retainS || S == autoreleaseS || S == drainS))
660 llvm::raw_svector_ostream os(buf);
664 os <<
"' message should be sent to instances "
665 "of class '" << Class->
getName()
666 <<
"' and not the class directly";
668 auto report = llvm::make_unique<BugReport>(*BT, os.str(), N);
680 class VariadicMethodTypeChecker :
public Checker<check::PreObjCMessage> {
682 mutable Selector dictionaryWithObjectsAndKeysS;
684 mutable Selector orderedSetWithObjectsS;
686 mutable Selector initWithObjectsAndKeysS;
687 mutable std::unique_ptr<BugType> BT;
699 VariadicMethodTypeChecker::isVariadicMessage(
const ObjCMethodCall &msg)
const {
720 return S == initWithObjectsS;
722 return S == initWithObjectsAndKeysS;
731 return S == arrayWithObjectsS;
733 return S == orderedSetWithObjectsS;
735 return S == setWithObjectsS;
737 return S == dictionaryWithObjectsAndKeysS;
744 void VariadicMethodTypeChecker::checkPreObjCMessage(
const ObjCMethodCall &msg,
747 BT.reset(
new APIMisuse(
this,
748 "Arguments passed to variadic method aren't all "
749 "Objective-C pointer types"));
753 dictionaryWithObjectsAndKeysS =
762 if (!isVariadicMessage(msg))
771 unsigned variadicArgsEnd = msg.
getNumArgs() - 1;
773 if (variadicArgsEnd <= variadicArgsBegin)
777 Optional<ExplodedNode*> errorNode;
779 for (
unsigned I = variadicArgsBegin;
I != variadicArgsEnd; ++
I) {
801 if (!errorNode.hasValue())
804 if (!errorNode.getValue())
808 llvm::raw_svector_ostream os(sbuf);
811 if (!TypeName.empty())
812 os <<
"Argument to '" << TypeName <<
"' method '";
814 os <<
"Argument to method '";
817 os <<
"' should be an Objective-C pointer type, not '";
821 auto R = llvm::make_unique<BugReport>(*BT, os.str(), errorNode.getValue());
822 R->addRange(msg.getArgSourceRange(
I));
837 class ObjCLoopChecker
838 :
public Checker<check::PostStmt<ObjCForCollectionStmt>,
839 check::PostObjCMessage,
841 check::PointerEscape > {
848 ObjCLoopChecker() : CountSelectorII(nullptr) {}
892 if (!KnownCollection)
896 std::tie(StNonNil, StNil) = State->assume(*KnownCollection);
897 if (StNil && !StNonNil) {
923 Optional<Loc> ElementLoc;
924 if (
const DeclStmt *DS = dyn_cast<DeclStmt>(Element)) {
925 const VarDecl *ElemDecl = cast<VarDecl>(DS->getSingleDecl());
926 assert(ElemDecl->
getInit() ==
nullptr);
927 ElementLoc = State->getLValue(ElemDecl, LCtx);
929 ElementLoc = State->getSVal(Element, LCtx).getAs<
Loc>();
936 SVal Val = State->getSVal(*ElementLoc);
944 SymbolRef CollectionS,
bool Assumption) {
945 if (!State || !CollectionS)
948 const SymbolRef *CountS = State->get<ContainerCountMap>(CollectionS);
950 const bool *KnownNonEmpty = State->get<ContainerNonEmptyMap>(CollectionS);
952 return State->set<ContainerNonEmptyMap>(CollectionS, Assumption);
953 return (Assumption == *KnownNonEmpty) ? State :
nullptr;
957 SVal CountGreaterThanZeroVal =
960 SvalBuilder.
makeIntVal(0, (*CountS)->getType()),
962 Optional<DefinedSVal> CountGreaterThanZero =
964 if (!CountGreaterThanZero) {
970 return State->assume(*CountGreaterThanZero, Assumption);
993 return BE->getSrc()->getLoopTarget() == FCS;
1029 bool ObjCLoopChecker::isCollectionCountMethod(
const ObjCMethodCall &M,
1033 if (!CountSelectorII)
1041 void ObjCLoopChecker::checkPostObjCMessage(
const ObjCMethodCall &M,
1063 if (!isCollectionCountMethod(M, C))
1072 State = State->set<ContainerCountMap>(ContainerS, CountS);
1074 if (
const bool *NonEmpty = State->get<ContainerNonEmptyMap>(ContainerS)) {
1075 State = State->remove<ContainerNonEmptyMap>(ContainerS);
1084 const ObjCMethodCall *Message = dyn_cast_or_null<ObjCMethodCall>(Call);
1129 for (InvalidatedSymbols::const_iterator
I = Escaped.begin(),
1138 if (Sym == ImmutableReceiver)
1143 State = State->remove<ContainerCountMap>(Sym);
1144 State = State->remove<ContainerNonEmptyMap>(Sym);
1149 void ObjCLoopChecker::checkDeadSymbols(
SymbolReaper &SymReaper,
1154 ContainerCountMapTy Tracked = State->get<ContainerCountMap>();
1155 for (ContainerCountMapTy::iterator
I = Tracked.begin(),
1156 E = Tracked.end();
I !=
E; ++
I) {
1158 if (SymReaper.
isDead(Sym)) {
1159 State = State->remove<ContainerCountMap>(Sym);
1160 State = State->remove<ContainerNonEmptyMap>(Sym);
1171 class ObjCNonNilReturnValueChecker
1172 :
public Checker<check::PostObjCMessage,
1173 check::PostStmt<ObjCArrayLiteral>,
1174 check::PostStmt<ObjCDictionaryLiteral>,
1175 check::PostStmt<ObjCBoxedExpr> > {
1178 mutable Selector ObjectAtIndexedSubscript;
1192 assumeExprIsNonNull(E, C);
1195 assumeExprIsNonNull(E, C);
1198 assumeExprIsNonNull(E, C);
1206 ObjCNonNilReturnValueChecker::assumeExprIsNonNull(
const Expr *NonNullExpr,
1211 return State->assume(*DV,
true);
1215 void ObjCNonNilReturnValueChecker::checkPostObjCMessage(
const ObjCMethodCall &M,
1223 ObjectAtIndexedSubscript =
GetUnarySelector(
"objectAtIndexedSubscript", Ctx);
1251 if (Sel == ObjectAtIndex || Sel == ObjectAtIndexedSubscript) {
1288 void ento::registerVariadicMethodTypeChecker(
CheckerManager &mgr) {
1297 ento::registerObjCNonNilReturnValueChecker(
CheckerManager &mgr) {
Defines the clang::ASTContext interface.
static Selector GetNullarySelector(StringRef name, ASTContext &Ctx)
Utility function for constructing a nullary selector.
FunctionDecl - An instance of this class is created to represent a function declaration or definition...
TypedValueRegion - An abstract class representing regions having a typed value.
nonloc::ConcreteInt makeIntVal(const IntegerLiteral *integer)
StringRef getName() const
getName - Get the name of identifier for this declaration as a StringRef.
Smart pointer class that efficiently represents Objective-C method names.
A (possibly-)qualified type.
ExplodedNode * generateErrorNode(ProgramStateRef State=nullptr, const ProgramPointTag *Tag=nullptr)
Generate a transition to a node that will be used to report an error.
Expr * getArg(unsigned Arg)
getArg - Return the specified argument.
ObjCInterfaceDecl * getClassInterface()
bool isInstanceMessage() const
static Selector GetUnarySelector(StringRef name, ASTContext &Ctx)
Utility function for constructing an unary selector.
static ProgramStateRef assumeCollectionNonEmpty(CheckerContext &C, ProgramStateRef State, SymbolRef CollectionS, bool Assumption)
Returns NULL state if the collection is known to contain elements (or is known not to contain element...
IdentifierInfo * getIdentifier() const
getIdentifier - Get the identifier that names this declaration, if there is one.
Stmt - This represents one statement.
The argument acts as if has been passed to CFMakeCollectable, which transfers the object to the Garba...
ProgramPoint getLocation() const
getLocation - Returns the edge associated with the given node.
ExplodedNode * addTransition(ProgramStateRef State=nullptr, const ProgramPointTag *Tag=nullptr)
Generates a new transition in the program state graph (ExplodedGraph).
virtual QualType getValueType() const =0
static StringRef GetReceiverInterfaceName(const ObjCMethodCall &msg)
const Expr * getInit() const
SourceRange getSourceRange() const override
bool isBlockPointerType() const
Value representing integer constant.
static ProgramStateRef checkCollectionNonNil(CheckerContext &C, ProgramStateRef State, const ObjCForCollectionStmt *FCS)
Assumes that the collection is non-nil.
ObjCDictionaryElement getKeyValueElement(unsigned Index) const
VarDecl - An instance of this class is created to represent a variable declaration or definition...
bool isReceiverSelfOrSuper() const
Checks if the receiver refers to 'self' or 'super'.
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
ObjCMethodDecl - Represents an instance or class method declaration.
ExplodedNode * getPredecessor()
Returns the previous node in the exploded graph, which includes the state of the program before the c...
Defines the Objective-C statement AST node classes.
bool isZeroConstant() const
const ObjCInterfaceDecl * getReceiverInterface() const
Get the interface for the receiver.
One of these records is kept for each identifier that is lexed.
An element in an Objective-C dictionary literal.
IdentifierInfo * getIdentifierInfoForSlot(unsigned argIndex) const
Retrieve the identifier at a given position in the selector.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
const FunctionDecl * getCalleeDecl(const CallExpr *CE) const
Get the declaration of the called function (path-sensitive).
static Selector getKeywordSelector(ASTContext &Ctx, IdentifierInfos *...IIs)
The argument is treated as if an -autorelease message had been sent to the referenced object...
static ProgramStateRef checkElementNonNil(CheckerContext &C, ProgramStateRef State, const ObjCForCollectionStmt *FCS)
Assumes that the collection elements are non-nil.
void addSymbolDependency(const SymbolRef Primary, const SymbolRef Dependent)
Add artificial symbol dependency.
ObjCArrayLiteral - used for objective-c array containers; as in: @["Hello", NSApp, [NSNumber numberWithInt:42]];.
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
Represents any expression that calls an Objective-C method.
SVal getReceiverSVal() const
Returns the value of the receiver at the time of this call.
ObjCMethodFamily getMethodFamily() const
Determines the family of this method.
void print(raw_ostream &OS, const PrintingPolicy &Policy, const Twine &PlaceHolder=Twine(), unsigned Indentation=0) const
Expr * Key
The key for the dictionary element.
void print(llvm::raw_ostream &OS) const
Prints the full selector name (e.g. "foo:bar:").
Represents an ObjC class declaration.
detail::InMemoryDirectory::const_iterator I
static SymbolRef getMethodReceiverIfKnownImmutable(const CallEvent *Call)
static bool isKnownNonNilCollectionType(QualType T)
The return type of classify().
#define REGISTER_MAP_WITH_PROGRAMSTATE(Name, Key, Value)
Declares an immutable map of type NameTy, suitable for placement into the ProgramState.
bool isUnarySelector() const
bool inTopFrame() const
Return true if the current LocationContext has no caller context.
bool isDead(SymbolRef sym) const
Returns whether or not a symbol has been confirmed dead.
DefinedOrUnknownSVal makeZeroVal(QualType type)
Construct an SVal representing '0' for the specified type.
Expr - This represents one expression.
static FoundationClass findKnownClass(const ObjCInterfaceDecl *ID, bool IncludeSuperclasses=true)
StringRef getName() const
Return the actual identifier string.
const ProgramStateRef & getState() const
unsigned getNumArgs() const
Optional< T > getAs() const
Convert to the specified SVal type, returning None if this SVal is not of the desired type...
ObjCDictionaryLiteral - AST node to represent objective-c dictionary literals; as in:"name" : NSUserN...
DeclContext * getDeclContext()
ObjCInterfaceDecl * getReceiverInterface() const
Retrieve the Objective-C interface to which this message is being directed, if known.
SymbolManager & getSymbolManager()
unsigned getNumElements() const
getNumElements - Return number of elements of objective-c array literal.
Expr * getElement(unsigned Index)
getExpr - Return the Expr at the specified index.
bool isCFObjectRef(QualType T)
SVal evalBinOp(ProgramStateRef state, BinaryOperator::Opcode op, SVal lhs, SVal rhs, QualType type)
ExplodedNode * generateNonFatalErrorNode(ProgramStateRef State=nullptr, const ProgramPointTag *Tag=nullptr)
Generate a transition to a node that will be used to report an error.
QualType getConditionType() const
void emitReport(std::unique_ptr< BugReport > R)
Emit the diagnostics report.
bool isIntegralOrEnumerationType() const
Determine whether this type is an integral or enumeration type.
CHECKER * registerChecker()
Used to register checkers.
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
ExplodedNode * generateSink(ProgramStateRef State, ExplodedNode *Pred, const ProgramPointTag *Tag=nullptr)
Generate a sink node.
DeclStmt - Adaptor class for mixing declarations with statements and expressions. ...
SVal - This represents a symbolic expression, which can be either an L-value or an R-value...
Selector getSelector() const
A class responsible for cleaning up unused symbols.
ObjCBoxedExpr - used for generalized expression boxing.
const ObjCMethodDecl * getDecl() const override
Expr * Value
The value of the dictionary element.
ASTContext & getASTContext()
static bool alreadyExecutedAtLeastOneLoopIteration(const ExplodedNode *N, const ObjCForCollectionStmt *FCS)
If the fist block edge is a back edge, we are reentering the loop.
Represents symbolic expression.
detail::InMemoryDirectory::const_iterator E
unsigned getNumArgs() const
getNumArgs - Return the number of actual arguments to this call.
CanQualType getCanonicalType(QualType T) const
Return the canonical (structural) type corresponding to the specified potentially non-canonical type ...
Represents an abstract call to a function or method along a particular path.
Optional< T > getAs() const
Convert to the specified ProgramPoint type, returning None if this ProgramPoint is not of the desired...
ObjCMessageKind getMessageKind() const
Returns how the message was written in the source (property access, subscript, or explicit message se...
PointerEscapeKind
Describes the different reasons a pointer escapes during analysis.
Represents a pointer to an Objective C object.
const LangOptions & getLangOpts() const
const ExplodedNode *const * const_pred_iterator
const T * getAs() const
Member-template getAs<specific type>'.
Represents Objective-C's collection statement.
ObjCInterfaceDecl * getInterfaceDecl() const
If this pointer points to an Objective @interface type, gets the declaration for that interface...
unsigned getNumArgs() const override
const Expr * getArgExpr(unsigned Index) const override
DefinedOrUnknownSVal evalEQ(ProgramStateRef state, DefinedOrUnknownSVal lhs, DefinedOrUnknownSVal rhs)
bool isObjCObjectPointerType() const
bool trackNullOrUndefValue(const ExplodedNode *N, const Stmt *S, BugReport &R, bool IsArg=false, bool EnableNullFPSuppression=true)
Attempts to add visitors to trace a null or undefined value back to its point of origin, whether it is a symbol constrained to null or an explicit assignment.
pred_iterator pred_begin()
SymbolRef getAsSymbol(bool IncludeBaseRegions=false) const
If this SVal wraps a symbol return that SymbolRef.
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
SValBuilder & getSValBuilder()
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
ObjCInterfaceDecl * getSuperClass() const
static Optional< uint64_t > GetCFNumberSize(ASTContext &Ctx, uint64_t i)
A trivial tuple used to represent a source range.
static bool isObjCNSObjectType(QualType Ty)
Return true if this is an NSObject object with its NSObject attribute set.
virtual const ObjCMessageExpr * getOriginExpr() const
const llvm::APSInt & getValue() const
T castAs() const
Convert to the specified SVal type, asserting that this SVal is of the desired type.
unsigned getNumElements() const
getNumElements - Return number of elements of objective-c dictionary literal.
TypedRegion - An abstract class representing regions that are typed.
const LocationContext * getLocationContext() const
SVal getSVal(const Stmt *S) const
Get the value of arbitrary expressions at this point in the path.