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)
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) {
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()),
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;
1182 ObjCNonNilReturnValueChecker() :
Initialized(
false) {}
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.
SVal getReceiverSVal() const
Returns the value of the receiver at the time of this call.
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)
ObjCDictionaryElement getKeyValueElement(unsigned Index) const
Smart pointer class that efficiently represents Objective-C method names.
A (possibly-)qualified type.
bool isBlockPointerType() const
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()
void print(raw_ostream &OS, const PrintingPolicy &Policy, const Twine &PlaceHolder=Twine(), unsigned Indentation=0) const
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...
Stmt - This represents one statement.
unsigned getNumArgs() const
getNumArgs - Return the number of actual arguments to this call.
ObjCInterfaceDecl * getReceiverInterface() const
Retrieve the Objective-C interface to which this message is being directed, if known.
The argument acts as if has been passed to CFMakeCollectable, which transfers the object to the Garba...
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)
SourceRange getSourceRange() const override
Value representing integer constant.
static ProgramStateRef checkCollectionNonNil(CheckerContext &C, ProgramStateRef State, const ObjCForCollectionStmt *FCS)
Assumes that the collection is non-nil.
VarDecl - An instance of this class is created to represent a variable declaration or definition...
const T * getAs() const
Member-template getAs<specific type>'.
const FunctionDecl * getCalleeDecl(const CallExpr *CE) const
Get the declaration of the called function (path-sensitive).
ObjCMethodDecl - Represents an instance or class method declaration.
bool isDead(SymbolRef sym) const
Returns whether or not a symbol has been confirmed dead.
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.
SVal getSVal(const Stmt *S) const
Get the value of arbitrary expressions at this point in the path.
IdentifierInfo * getIdentifier() const
getIdentifier - Get the identifier that names this declaration, if there is one.
One of these records is kept for each identifier that is lexed.
An element in an Objective-C dictionary literal.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
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.
const ObjCInterfaceDecl * getReceiverInterface() const
Get the interface for the receiver.
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
bool isIntegralOrEnumerationType() const
Determine whether this type is an integral or enumeration type.
bool isUnarySelector() const
ObjCMethodFamily getMethodFamily() const
Determines the family of this method.
Represents any expression that calls an Objective-C method.
Selector GetNullarySelector(StringRef name, ASTContext &Ctx)
Utility function for constructing a nullary selector.
Expr * Key
The key for the dictionary element.
Represents an ObjC class declaration.
static SymbolRef getMethodReceiverIfKnownImmutable(const CallEvent *Call)
static bool isKnownNonNilCollectionType(QualType T)
SymbolRef getAsSymbol(bool IncludeBaseRegions=false) const
If this SVal wraps a symbol return that SymbolRef.
bool isReceiverSelfOrSuper() const
Checks if the receiver refers to 'self' or 'super'.
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.
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)
const FunctionProtoType * T
ObjCDictionaryLiteral - AST node to represent objective-c dictionary literals; as in:"name" : NSUserN...
DeclContext * getDeclContext()
QualType getConditionType() const
ObjCInterfaceDecl * getSuperClass() const
SymbolManager & getSymbolManager()
void print(llvm::raw_ostream &OS) const
Prints the full selector name (e.g. "foo:bar:").
Expr * getElement(unsigned Index)
getElement - Return the Element at the specified index.
bool isCFObjectRef(QualType T)
SVal evalBinOp(ProgramStateRef state, BinaryOperator::Opcode op, SVal lhs, SVal rhs, QualType type)
unsigned getNumArgs() const
ExplodedNode * generateNonFatalErrorNode(ProgramStateRef State=nullptr, const ProgramPointTag *Tag=nullptr)
Generate a transition to a node that will be used to report an error.
Optional< T > getAs() const
Convert to the specified SVal type, returning None if this SVal is not of the desired type...
void emitReport(std::unique_ptr< BugReport > R)
Emit the diagnostics report.
CHECKER * registerChecker()
Used to register checkers.
IdentifierInfo * getIdentifierInfoForSlot(unsigned argIndex) const
Retrieve the identifier at a given position in the selector.
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.
unsigned getNumElements() const
getNumElements - Return number of elements of objective-c dictionary literal.
DeclStmt - Adaptor class for mixing declarations with statements and expressions. ...
ProgramPoint getLocation() const
getLocation - Returns the edge associated with the given node.
SVal - This represents a symbolic expression, which can be either an L-value or an R-value...
bool isObjCObjectPointerType() 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.
StringRef getName() const
Return the actual identifier string.
virtual const ObjCMessageExpr * getOriginExpr() const
Selector getSelector() const
Dataflow Directional Tag Classes.
ASTContext & getASTContext()
bool isZeroConstant() const
static bool alreadyExecutedAtLeastOneLoopIteration(const ExplodedNode *N, const ObjCForCollectionStmt *FCS)
If the fist block edge is a back edge, we are reentering the loop.
const Expr * getInit() const
Represents symbolic expression.
Represents an abstract call to a function or method along a particular path.
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.
bool isInstanceMessage() const
T castAs() const
Convert to the specified SVal type, asserting that this SVal is of the desired type.
const ExplodedNode *const * const_pred_iterator
ObjCInterfaceDecl * getInterfaceDecl() const
If this pointer points to an Objective @interface type, gets the declaration for that interface...
unsigned getNumElements() const
getNumElements - Return number of elements of objective-c array literal.
Represents Objective-C's collection statement.
const ProgramStateRef & getState() const
unsigned getNumArgs() const override
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
CanQualType getCanonicalType(QualType T) const
Return the canonical (structural) type corresponding to the specified potentially non-canonical type ...
const Expr * getArgExpr(unsigned Index) const override
DefinedOrUnknownSVal evalEQ(ProgramStateRef state, DefinedOrUnknownSVal lhs, DefinedOrUnknownSVal rhs)
Selector GetUnarySelector(StringRef name, ASTContext &Ctx)
Utility function for constructing an unary selector.
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()
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]).
StringRef getName() const
getName - Get the name of identifier for this declaration as a StringRef.
static Optional< uint64_t > GetCFNumberSize(ASTContext &Ctx, uint64_t i)
A trivial tuple used to represent a source range.
Optional< T > getAs() const
Convert to the specified ProgramPoint type, returning None if this ProgramPoint is not of the desired...
bool inTopFrame() const
Return true if the current LocationContext has no caller context.
static bool isObjCNSObjectType(QualType Ty)
Return true if this is an NSObject object with its NSObject attribute set.
const LocationContext * getLocationContext() const
const LangOptions & getLangOpts() const
TypedRegion - An abstract class representing regions that are typed.