35 using namespace clang;
50 class DynamicTypePropagation:
54 check::PostStmt<CastExpr>,
55 check::PostStmt<CXXNewExpr>,
56 check::PreObjCMessage,
57 check::PostObjCMessage > {
69 mutable std::unique_ptr<BugType> ObjCGenericsBugType;
70 void initBugType()
const {
71 if (!ObjCGenericsBugType)
72 ObjCGenericsBugType.reset(
80 void Profile(llvm::FoldingSetNodeID &
ID)
const override {
99 const Stmt *ReportedNode =
nullptr)
const;
115 void DynamicTypePropagation::checkDeadSymbols(
SymbolReaper &SR,
131 MostSpecializedTypeArgsMapTy TyArgMap =
132 State->get<MostSpecializedTypeArgsMap>();
137 State = State->remove<MostSpecializedTypeArgsMap>(
I->first);
157 void DynamicTypePropagation::checkPreCall(
const CallEvent &Call,
168 switch (Ctor->getOriginExpr()->getConstructionKind()) {
175 if (
const MemRegion *Target = Ctor->getCXXThisVal().getAsRegion())
185 if (!Dtor->isBaseDestructor())
188 const MemRegion *Target = Dtor->getCXXThisVal().getAsRegion();
192 const Decl *D = Dtor->getDecl();
201 void DynamicTypePropagation::checkPostCall(
const CallEvent &Call,
204 if (
const ObjCMethodCall *Msg = dyn_cast<ObjCMethodCall>(&Call)) {
215 switch (Msg->getMethodFamily()) {
226 const ObjCObjectType *ObjTy = getObjectTypeForAllocAndNew(MsgE, C);
237 const MemRegion *RecReg = Msg->getReceiverSVal().getAsRegion();
251 switch (Ctor->getOriginExpr()->getConstructionKind()) {
262 if (
const MemRegion *Target = Ctor->getCXXThisVal().getAsRegion()) {
277 ExplodedNode *DynamicTypePropagation::dynamicTypePropagationOnCasts(
284 if (isa<ExplicitCastExpr>(CE))
287 if (
const Type *NewTy = getBetterObjCType(CE, C)) {
294 void DynamicTypePropagation::checkPostStmt(
const CXXNewExpr *NewE,
309 DynamicTypePropagation::getObjectTypeForAllocAndNew(
const ObjCMessageExpr *MsgE,
328 if (
const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(RecE)) {
335 dyn_cast<ObjCObjectType>(MD->getClassInterface()->getTypeForDecl()))
346 DynamicTypePropagation::getBetterObjCType(
const Expr *CastE,
386 return MostInformativeCandidate;
398 const auto *SuperOfTo =
409 MostInformativeCandidate, C);
480 State = State->set<MostSpecializedTypeArgsMap>(Sym, StaticLowerBound);
486 State = State->set<MostSpecializedTypeArgsMap>(Sym, WithMostInfo);
502 if (WithMostInfo == *Current)
504 State = State->set<MostSpecializedTypeArgsMap>(Sym, WithMostInfo);
511 if (WithMostInfo != *Current) {
512 State = State->set<MostSpecializedTypeArgsMap>(Sym, WithMostInfo);
522 void DynamicTypePropagation::checkPostStmt(
const CastExpr *CE,
533 if (!OrigObjectPtrType || !DestObjectPtrType)
537 ExplodedNode *AfterTypeProp = dynamicTypePropagationOnCasts(CE, State, C);
546 OrigObjectPtrType = OrigObjectPtrType->stripObjCKindOfTypeAndQuals(ASTCtxt);
551 if (OrigObjectPtrType->isUnspecialized() &&
565 State->get<MostSpecializedTypeArgsMap>(Sym);
569 if (isa<ExplicitCastExpr>(CE) && !OrigToDest && !DestToOrig) {
573 State = State->set<MostSpecializedTypeArgsMap>(Sym, DestObjectPtrType);
575 }
else if (TrackedType) {
576 State = State->remove<MostSpecializedTypeArgsMap>(Sym);
591 reportGenericsBug(*TrackedType, DestObjectPtrType, N, Sym, C);
599 if (OrigToDest && !DestToOrig)
600 std::swap(LowerBound, UpperBound);
603 LowerBound = LowerBound->
isObjCIdType() ? UpperBound : LowerBound;
604 UpperBound = UpperBound->
isObjCIdType() ? LowerBound : UpperBound;
625 class IsObjCTypeParamDependentTypeVisitor
628 IsObjCTypeParamDependentTypeVisitor() :
Result(
false) {}
630 if (isa<ObjCTypeParamDecl>(Type->
getDecl())) {
640 IsObjCTypeParamDependentTypeVisitor Visitor;
641 Visitor.TraverseType(Type);
642 return Visitor.Result;
656 const auto *ReceiverObjectPtrType =
706 void DynamicTypePropagation::checkPreObjCMessage(
const ObjCMethodCall &M,
714 State->get<MostSpecializedTypeArgsMap>(Sym);
731 (*TrackedType)->getObjCSubstitutions(Method->getDeclContext());
737 for (
unsigned i = 0; i < Method->
param_size(); i++) {
749 const auto *ArgObjectPtrType =
751 if (!ParamObjectPtrType || !ArgObjectPtrType)
756 SVal ArgSVal = M.getArgSVal(i);
760 State->get<MostSpecializedTypeArgsMap>(ArgSym);
761 if (TrackedArgType &&
763 ArgObjectPtrType = *TrackedArgType;
772 reportGenericsBug(ArgObjectPtrType, ParamObjectPtrType, N, Sym, C, Arg);
785 void DynamicTypePropagation::checkPostObjCMessage(
const ObjCMethodCall &M,
789 SymbolRef RetSym = M.getReturnValue().getAsSymbol();
806 if (!ReceiverClassType->isSpecialized())
808 const auto *InferredType =
810 assert(InferredType);
812 State = State->set<MostSpecializedTypeArgsMap>(RetSym, InferredType);
823 State->get<MostSpecializedTypeArgsMap>(RecSym);
834 (*TrackedType)->getObjCSubstitutions(Method->getDeclContext());
844 const MemRegion *RetRegion = M.getReturnValue().getAsRegion();
860 if (!ResultPtrType || ResultPtrType->isUnspecialized())
865 if (!State->get<MostSpecializedTypeArgsMap>(RetSym)) {
866 State = State->set<MostSpecializedTypeArgsMap>(RetSym, ResultPtrType);
871 void DynamicTypePropagation::reportGenericsBug(
874 const Stmt *ReportedNode)
const {
880 llvm::raw_svector_ostream OS(Buf);
881 OS <<
"Conversion from value of type '";
883 OS <<
"' to incompatible type '";
886 std::unique_ptr<BugReport> R(
887 new BugReport(*ObjCGenericsBugType, OS.str(), N));
888 R->markInteresting(Sym);
889 R->addVisitor(llvm::make_unique<GenericsBugVisitor>(Sym));
891 R->addRange(ReportedNode->getSourceRange());
902 state->get<MostSpecializedTypeArgsMap>(Sym);
904 statePrev->get<MostSpecializedTypeArgsMap>(Sym);
908 if (TrackedTypePrev && *TrackedTypePrev == *TrackedType)
912 const Stmt *
S =
nullptr;
924 llvm::raw_svector_ostream OS(Buf);
927 OS <<
"' is inferred from ";
929 if (
const auto *ExplicitCast = dyn_cast<ExplicitCastExpr>(S)) {
930 OS <<
"explicit cast (from '";
935 LangOpts, llvm::Twine());
937 }
else if (
const auto *ImplicitCast = dyn_cast<ImplicitCastExpr>(S)) {
938 OS <<
"implicit cast (from '";
943 LangOpts, llvm::Twine());
946 OS <<
"this context";
957 DynamicTypePropagation *checker =
959 checker->CheckGenerics =
true;
CastKind getCastKind() const
const char *const CoreFoundationObjectiveC
The receiver is an object instance.
Smart pointer class that efficiently represents Objective-C method names.
A (possibly-)qualified type.
MemRegion - The root abstract class for all memory regions.
ASTContext & getASTContext()
bool hasDeadSymbols() const
QualType getClassReceiver() const
Returns the type of a class message send, or NULL if the message is not a class message.
A helper class which wraps a boolean value set to false by default.
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).
QualType substObjCTypeArgs(ASTContext &ctx, ArrayRef< QualType > typeArgs, ObjCSubstitutionContext context) const
Substitute type arguments for the Objective-C type parameters used in the subject type...
The base class of the type hierarchy.
QualType getRecordType(const RecordDecl *Decl) const
const ObjCObjectType * getObjectType() const
Gets the type pointed to by this ObjC pointer.
bool isUnspecialized() const
Whether this type is unspecialized, meaning that is has no type arguments.
static void recordFixedType(const MemRegion *Region, const CXXMethodDecl *MD, CheckerContext &C)
bool isSpecialized() const
Whether this type is specialized, meaning that it has type arguments.
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...
unsigned param_size() const
ParmVarDecl - Represents a parameter to a function.
The collection of all-type qualifiers we support.
static const ObjCMethodDecl * findMethodDecl(const ObjCMessageExpr *MessageExpr, const ObjCObjectPointerType *TrackedType, ASTContext &ASTCtxt)
A method might not be available in the interface indicated by the static type.
QualType getReceiverType() const
Retrieve the receiver type to which this message is being directed.
Represents a class type in Objective C.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
The GDM component containing the dynamic type info.
This class provides a convenience implementation for clone() using the Curiously-Recurring Template P...
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
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 isObjCTypeParamDependent(QualType Type)
Represents any expression that calls an Objective-C method.
SVal getReceiverSVal() const
Returns the value of the receiver at the time of this call.
const LangOptions & getLangOpts() const
bool isLiveRegion(const MemRegion *region)
QualType getSuperType() const
Retrieve the type referred to by 'super'.
const CXXRecordDecl * getParent() const
Returns the parent of this method declaration, which is the class in which this method is defined...
Selector getSelector() const
void print(raw_ostream &OS, const PrintingPolicy &Policy, const Twine &PlaceHolder=Twine(), unsigned Indentation=0) const
static QualType getReturnTypeForMethod(const ObjCMethodDecl *Method, ArrayRef< QualType > TypeArgs, const ObjCObjectPointerType *SelfType, ASTContext &C)
Get the returned ObjCObjectPointerType by a method based on the tracked type information, or null pointer when the returned type is not an ObjCObjectPointerType.
CastExpr - Base class for type casts, including both implicit casts (ImplicitCastExpr) and explicit c...
A class that does preordor or postorder depth-first traversal on the entire Clang AST and visits each...
Represents an ObjC class declaration.
detail::InMemoryDirectory::const_iterator I
const LocationContext * getLocationContext() const
bool isDead(SymbolRef sym) const
Returns whether or not a symbol has been confirmed dead.
const ObjCMethodDecl * getMethodDecl() const
QualType getSuperClassType() const
Retrieve the type of the superclass of this object type.
Expr - This represents one expression.
const ProgramStateRef & getState() const
const ProgramStateRef & getState() const
static bool storeWhenMoreInformative(ProgramStateRef &State, SymbolRef Sym, const ObjCObjectPointerType *const *Current, const ObjCObjectPointerType *StaticLowerBound, const ObjCObjectPointerType *StaticUpperBound, ASTContext &C)
Inputs:
Stores the currently inferred strictest bound on the runtime type of a region in a given state along ...
bool isObjCClassType() const
Represents an implicit call to a C++ destructor.
ObjCMethodDecl * lookupInstanceMethod(Selector Sel) const
Lookup an instance method for a given selector.
ObjCMethodDecl * lookupClassMethod(Selector Sel) const
Lookup a class method for a given selector.
bool isObjCIdType() const
const ObjCObjectPointerType * stripObjCKindOfTypeAndQuals(const ASTContext &ctx) const
Strip off the Objective-C "kindof" type and (with it) any protocol qualifiers.
ProgramStateRef setDynamicTypeInfo(ProgramStateRef State, const MemRegion *Reg, DynamicTypeInfo NewTy)
Set dynamic type information of the region; return the new state.
bool hasRelatedResultType() const
Determine whether this method has a result type that is related to the message receiver's type...
An expression that sends a message to the given Objective-C object or class.
The result type of a method or function.
Expr * getArg(unsigned Arg)
getArg - Return the specified argument.
void emitReport(std::unique_ptr< BugReport > R)
Emit the diagnostics report.
ArrayRef< ParmVarDecl * > parameters() const
OpaqueValueExpr - An expression referring to an opaque object of a fixed type and value class...
CHECKER * registerChecker()
Used to register checkers.
PseudoObjectExpr - An expression which accesses a pseudo-object l-value.
const TemplateArgument * iterator
Represents a new-expression for memory allocation and constructor calls, e.g: "new CXXNewExpr(foo)"...
Represents a static or instance method of a struct/union/class.
SVal - This represents a symbolic expression, which can be either an L-value or an R-value...
void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Ctx)
std::string getAsString() const
Derive the full selector name (e.g.
TypedefNameDecl * getDecl() const
const Decl * getDecl() const
A class responsible for cleaning up unused symbols.
QualType getReturnType() const
const StackFrameContext * getStackFrame() const
QualType getObjCInstanceType()
Retrieve the Objective-C "instancetype" type, if already known; otherwise, returns a NULL type;...
Expr * getInstanceReceiver()
Returns the object expression (receiver) for an instance message, or null for a message that is not a...
static const ObjCObjectPointerType * getMostInformativeDerivedClassImpl(const ObjCObjectPointerType *From, const ObjCObjectPointerType *To, const ObjCObjectPointerType *MostInformativeCandidate, ASTContext &C)
bool isSuperClassOf(const ObjCInterfaceDecl *I) const
isSuperClassOf - Return true if this class is the specified class or is a super class of the specifie...
ASTContext & getASTContext()
DynamicTypeInfo getDynamicTypeInfo(ProgramStateRef State, const MemRegion *Reg)
Get dynamic type information for a region.
QualType getPointerType(QualType T) const
Return the uniqued reference to the type for a pointer to the specified type.
QualType getObjCObjectPointerType(QualType OIT) const
Return a ObjCObjectPointerType type for the given ObjCObjectType.
detail::InMemoryDirectory::const_iterator E
const MemRegion * getAsRegion() const
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...
Expr * IgnoreParenImpCasts() LLVM_READONLY
IgnoreParenImpCasts - Ignore parentheses and implicit casts.
Represents a pointer to an Objective C object.
REGISTER_MAP_WITH_PROGRAMSTATE(MostSpecializedTypeArgsMap, SymbolRef, const ObjCObjectPointerType *) namespace
const LangOptions & getLangOpts() const
const T * getAs() const
Member-template getAs<specific type>'.
ObjCInterfaceDecl * getInterfaceDecl() const
If this pointer points to an Objective @interface type, gets the declaration for that interface...
ObjCInterfaceDecl * getCanonicalDecl() override
Retrieves the canonical declaration of this Objective-C class.
bool canAssignObjCInterfaces(const ObjCObjectPointerType *LHSOPT, const ObjCObjectPointerType *RHSOPT)
canAssignObjCInterfaces - Return true if the two interface types are compatible for assignment from R...
const ImplicitParamDecl * getSelfDecl() const
X
Add a minimal nested name specifier fixit hint to allow lookup of a tag name from an outer enclosing ...
static const ObjCObjectPointerType * getMostInformativeDerivedClass(const ObjCObjectPointerType *From, const ObjCObjectPointerType *To, ASTContext &C)
A downcast may loose specialization information.
The parameter type of a method or function.
static const Expr * stripCastsAndSugar(const Expr *E)
SymbolRef getAsSymbol(bool IncludeBaseRegions=false) const
If this SVal wraps a symbol return that SymbolRef.
A reference to a declared variable, function, enum, etc.
Tag that can use a checker name as a message provider (see SimpleProgramPointTag).
This class provides an interface through which checkers can create individual bug reports...
bool isNull() const
Return true if this QualType doesn't point to a type yet.
virtual const ObjCMessageExpr * getOriginExpr() const
The receiver is a superclass.
SVal getReturnValue() const
Returns the return value of the call.
bool isObjCIdType() const
True if this is equivalent to the 'id' type, i.e.
Represents a call to a C++ constructor.
ReceiverKind getReceiverKind() const
Determine the kind of receiver that this message is being sent to.
Defines enum values for all the target-independent builtin functions.
SourceManager & getSourceManager()
const LocationContext * getLocationContext() const
SVal getSVal(const Stmt *S) const
Get the value of arbitrary expressions at this point in the path.