36 using namespace clang;
51 class DynamicTypePropagation:
55 check::PostStmt<CastExpr>,
56 check::PostStmt<CXXNewExpr>,
57 check::PreObjCMessage,
58 check::PostObjCMessage > {
70 mutable std::unique_ptr<BugType> ObjCGenericsBugType;
71 void initBugType()
const {
72 if (!ObjCGenericsBugType)
73 ObjCGenericsBugType.reset(
79 GenericsBugVisitor(
SymbolRef S) : Sym(S) {}
81 void Profile(llvm::FoldingSetNodeID &
ID)
const override {
87 std::shared_ptr<PathDiagnosticPiece> VisitNode(
const ExplodedNode *N,
100 const Stmt *ReportedNode =
nullptr)
const;
116 void DynamicTypePropagation::checkDeadSymbols(
SymbolReaper &SR,
120 for (DynamicTypeMapImpl::iterator I = TypeMap.begin(), E = TypeMap.end();
132 MostSpecializedTypeArgsMapTy TyArgMap =
133 State->get<MostSpecializedTypeArgsMap>();
134 for (MostSpecializedTypeArgsMapTy::iterator I = TyArgMap.begin(),
137 if (SR.
isDead(I->first)) {
138 State = State->remove<MostSpecializedTypeArgsMap>(I->first);
158 void DynamicTypePropagation::checkPreCall(
const CallEvent &Call,
169 switch (Ctor->getOriginExpr()->getConstructionKind()) {
176 if (
const MemRegion *Target = Ctor->getCXXThisVal().getAsRegion())
186 if (!Dtor->isBaseDestructor())
189 const MemRegion *Target = Dtor->getCXXThisVal().getAsRegion();
193 const Decl *D = Dtor->getDecl();
202 void DynamicTypePropagation::checkPostCall(
const CallEvent &Call,
205 if (
const ObjCMethodCall *Msg = dyn_cast<ObjCMethodCall>(&Call)) {
216 switch (Msg->getMethodFamily()) {
227 const ObjCObjectType *ObjTy = getObjectTypeForAllocAndNew(MsgE, C);
238 const MemRegion *RecReg = Msg->getReceiverSVal().getAsRegion();
252 switch (Ctor->getOriginExpr()->getConstructionKind()) {
263 if (
const MemRegion *Target = Ctor->getCXXThisVal().getAsRegion()) {
274 if (dyn_cast_or_null<InitListExpr>(
289 ExplodedNode *DynamicTypePropagation::dynamicTypePropagationOnCasts(
296 if (isa<ExplicitCastExpr>(CE))
299 if (
const Type *NewTy = getBetterObjCType(CE, C)) {
306 void DynamicTypePropagation::checkPostStmt(
const CXXNewExpr *NewE,
321 DynamicTypePropagation::getObjectTypeForAllocAndNew(
const ObjCMessageExpr *MsgE,
340 if (
const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(RecE)) {
347 dyn_cast<ObjCObjectType>(MD->getClassInterface()->getTypeForDecl()))
358 DynamicTypePropagation::getBetterObjCType(
const Expr *CastE,
398 return MostInformativeCandidate;
410 const auto *SuperOfTo =
421 MostInformativeCandidate, C);
492 State = State->set<MostSpecializedTypeArgsMap>(Sym, StaticLowerBound);
498 State = State->set<MostSpecializedTypeArgsMap>(Sym, WithMostInfo);
514 if (WithMostInfo == *Current)
516 State = State->set<MostSpecializedTypeArgsMap>(Sym, WithMostInfo);
523 if (WithMostInfo != *Current) {
524 State = State->set<MostSpecializedTypeArgsMap>(Sym, WithMostInfo);
534 void DynamicTypePropagation::checkPostStmt(
const CastExpr *CE,
545 if (!OrigObjectPtrType || !DestObjectPtrType)
549 ExplodedNode *AfterTypeProp = dynamicTypePropagationOnCasts(CE, State, C);
558 OrigObjectPtrType = OrigObjectPtrType->stripObjCKindOfTypeAndQuals(ASTCtxt);
561 if (OrigObjectPtrType->isUnspecialized() &&
570 State->get<MostSpecializedTypeArgsMap>(Sym);
572 if (isa<ExplicitCastExpr>(CE)) {
582 State = State->remove<MostSpecializedTypeArgsMap>(Sym);
603 reportGenericsBug(*TrackedType, DestObjectPtrType, N, Sym, C);
611 if (OrigToDest && !DestToOrig)
612 std::swap(LowerBound, UpperBound);
615 LowerBound = LowerBound->
isObjCIdType() ? UpperBound : LowerBound;
616 UpperBound = UpperBound->
isObjCIdType() ? LowerBound : UpperBound;
637 class IsObjCTypeParamDependentTypeVisitor
640 IsObjCTypeParamDependentTypeVisitor() : Result(
false) {}
642 if (isa<ObjCTypeParamDecl>(Type->
getDecl())) {
652 IsObjCTypeParamDependentTypeVisitor Visitor;
653 Visitor.TraverseType(Type);
654 return Visitor.Result;
668 const auto *ReceiverObjectPtrType =
718 void DynamicTypePropagation::checkPreObjCMessage(
const ObjCMethodCall &M,
726 State->get<MostSpecializedTypeArgsMap>(Sym);
780 for (
unsigned i = 0; i < Method->
param_size(); i++) {
792 const auto *ArgObjectPtrType =
794 if (!ParamObjectPtrType || !ArgObjectPtrType)
799 SVal ArgSVal = M.getArgSVal(i);
803 State->get<MostSpecializedTypeArgsMap>(ArgSym);
804 if (TrackedArgType &&
806 ArgObjectPtrType = *TrackedArgType;
815 reportGenericsBug(ArgObjectPtrType, ParamObjectPtrType, N, Sym, C, Arg);
828 void DynamicTypePropagation::checkPostObjCMessage(
const ObjCMethodCall &M,
832 SymbolRef RetSym = M.getReturnValue().getAsSymbol();
849 if (!ReceiverClassType->isSpecialized())
851 const auto *InferredType =
853 assert(InferredType);
855 State = State->set<MostSpecializedTypeArgsMap>(RetSym, InferredType);
866 State->get<MostSpecializedTypeArgsMap>(RecSym);
887 const MemRegion *RetRegion = M.getReturnValue().getAsRegion();
903 if (!ResultPtrType || ResultPtrType->isUnspecialized())
908 if (!State->get<MostSpecializedTypeArgsMap>(RetSym)) {
909 State = State->set<MostSpecializedTypeArgsMap>(RetSym, ResultPtrType);
914 void DynamicTypePropagation::reportGenericsBug(
917 const Stmt *ReportedNode)
const {
923 llvm::raw_svector_ostream OS(Buf);
924 OS <<
"Conversion from value of type '";
926 OS <<
"' to incompatible type '";
929 std::unique_ptr<BugReport> R(
930 new BugReport(*ObjCGenericsBugType, OS.str(), N));
931 R->markInteresting(Sym);
932 R->addVisitor(llvm::make_unique<GenericsBugVisitor>(Sym));
938 std::shared_ptr<PathDiagnosticPiece>
939 DynamicTypePropagation::GenericsBugVisitor::VisitNode(
const ExplodedNode *N,
947 state->get<MostSpecializedTypeArgsMap>(Sym);
949 statePrev->get<MostSpecializedTypeArgsMap>(Sym);
953 if (TrackedTypePrev && *TrackedTypePrev == *TrackedType)
964 llvm::raw_svector_ostream OS(Buf);
967 OS <<
"' is inferred from ";
969 if (
const auto *ExplicitCast = dyn_cast<ExplicitCastExpr>(S)) {
970 OS <<
"explicit cast (from '";
975 LangOpts, llvm::Twine());
977 }
else if (
const auto *ImplicitCast = dyn_cast<ImplicitCastExpr>(S)) {
978 OS <<
"implicit cast (from '";
983 LangOpts, llvm::Twine());
986 OS <<
"this context";
992 return std::make_shared<PathDiagnosticEventPiece>(Pos, OS.str(),
true,
998 DynamicTypePropagation *checker =
1000 checker->CheckGenerics =
true;
SVal getReceiverSVal() const
Returns the value of the receiver at the time of this call.
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.
QualType substObjCTypeArgs(ASTContext &ctx, ArrayRef< QualType > typeArgs, ObjCSubstitutionContext context) const
Substitute type arguments for the Objective-C type parameters used in the subject type...
unsigned param_size() const
ASTContext & getASTContext()
Selector getSelector() const
ObjCInterfaceDecl * getClassInterface()
void print(raw_ostream &OS, const PrintingPolicy &Policy, const Twine &PlaceHolder=Twine(), unsigned Indentation=0) const
Stmt - This represents one statement.
A helper class which wraps a boolean value set to false by default.
ExplodedNode * addTransition(ProgramStateRef State=nullptr, const ProgramPointTag *Tag=nullptr)
Generates a new transition in the program state graph (ExplodedGraph).
Decl - This represents one declaration (or definition), e.g.
ObjCTypeParamList * getTypeParamList() const
Retrieve the type parameters of this class.
The base class of the type hierarchy.
Stmt * getParent(Stmt *) const
bool isUnspecialized() const
Whether this type is unspecialized, meaning that is has no type arguments.
const ProgramStateRef & getState() const
const T * getAs() const
Member-template getAs<specific type>'.
static void recordFixedType(const MemRegion *Region, const CXXMethodDecl *MD, CheckerContext &C)
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...
bool isDead(SymbolRef sym) const
Returns whether or not a symbol has been confirmed dead.
SVal getSVal(const Stmt *S) const
Get the value of arbitrary expressions at this point in the path.
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.
Represents a class type in Objective C.
ObjCMethodDecl * lookupInstanceMethod(Selector Sel) const
Lookup an instance method for a given selector.
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.
bool isObjCIdType() const
This class provides a convenience implementation for clone() using the Curiously-Recurring Template P...
bool isSpecialized() const
Whether this type is specialized, meaning that it has type arguments.
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
const ObjCObjectPointerType * stripObjCKindOfTypeAndQuals(const ASTContext &ctx) const
Strip off the Objective-C "kindof" type and (with it) any protocol qualifiers.
static bool isObjCTypeParamDependent(QualType Type)
Represents any expression that calls an Objective-C method.
const ImplicitParamDecl * getSelfDecl() const
bool isLiveRegion(const MemRegion *region)
const LocationContext * getLocationContext() const
SVal getReturnValue() const
Returns the return value of the call.
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.
ObjCMethodDecl * lookupClassMethod(Selector Sel) const
Lookup a class method for a given selector.
CastExpr - Base class for type casts, including both implicit casts (ImplicitCastExpr) and explicit c...
A class that does preorder or postorder depth-first traversal on the entire Clang AST and visits each...
Represents an ObjC class declaration.
QualType getReturnType() const
SymbolRef getAsSymbol(bool IncludeBaseRegions=false) const
If this SVal wraps a symbol return that SymbolRef.
bool hasDeadSymbols() const
ObjCTypeParamDecl * getDecl() const
Expr - This represents one expression.
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 ...
Represents an implicit call to a C++ destructor.
bool hasRelatedResultType() const
Determine whether this method has a result type that is related to the message receiver's type...
bool isObjCClassType() const
DeclContext * getDeclContext()
bool isObjCIdType() const
True if this is equivalent to the 'id' type, i.e.
ProgramStateRef setDynamicTypeInfo(ProgramStateRef State, const MemRegion *Reg, DynamicTypeInfo NewTy)
Set dynamic type information of the region; return the new state.
An expression that sends a message to the given Objective-C object or class.
QualType getRecordType(const RecordDecl *Decl) const
ReceiverKind getReceiverKind() const
Determine the kind of receiver that this message is being sent to.
The result type of a method or function.
bool isNull() const
Return true if this QualType doesn't point to a type yet.
ParentMap & getParentMap() const
Expr * getArg(unsigned Arg)
getArg - Return the specified argument.
void emitReport(std::unique_ptr< BugReport > R)
Emit the diagnostics report.
static const Stmt * getStmt(const ExplodedNode *N)
Given an exploded node, retrieve the statement that should be used for the diagnostic location...
OpaqueValueExpr - An expression referring to an opaque object of a fixed type and value class...
std::string getAsString() const
Derive the full selector name (e.g.
CHECKER * registerChecker()
Used to register checkers.
PseudoObjectExpr - An expression which accesses a pseudo-object l-value.
CastKind getCastKind() const
const MemRegion * getAsRegion() const
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...
QualType getReceiverType() const
Retrieve the receiver type to which this message is being directed.
A class responsible for cleaning up unused symbols.
bool isSuperClassOf(const ObjCInterfaceDecl *I) const
isSuperClassOf - Return true if this class is the specified class or is a super class of the specifie...
QualType getSuperClassType() const
Retrieve the type of the superclass of this object type.
const ObjCMethodDecl * getMethodDecl() 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)
virtual const ObjCMessageExpr * getOriginExpr() const
Dataflow Directional Tag Classes.
ASTContext & getASTContext()
DynamicTypeInfo getDynamicTypeInfo(ProgramStateRef State, const MemRegion *Reg)
Get dynamic type information for a region.
QualType getSuperType() const
Retrieve the type referred to by 'super'.
Represents the declaration of an Objective-C type parameter.
const CXXRecordDecl * getParent() const
Returns the parent of this method declaration, which is the class in which this method is defined...
const ObjCObjectType * getObjectType() const
Gets the type pointed to by this ObjC pointer.
Represents an abstract call to a function or method along a particular path.
const Decl * getDecl() const
Expr * IgnoreParenImpCasts() LLVM_READONLY
IgnoreParenImpCasts - Ignore parentheses and implicit casts.
QualType getClassReceiver() const
Returns the type of a class message send, or NULL if the message is not a class message.
Represents a pointer to an Objective C object.
REGISTER_MAP_WITH_PROGRAMSTATE(MostSpecializedTypeArgsMap, SymbolRef, const ObjCObjectPointerType *) namespace
const StackFrameContext * getStackFrame() const
ObjCInterfaceDecl * getInterfaceDecl() const
If this pointer points to an Objective @interface type, gets the declaration for that interface...
const ProgramStateRef & getState() const
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...
X
Add a minimal nested name specifier fixit hint to allow lookup of a tag name from an outer enclosing ...
Represents a type parameter type in Objective C.
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)
Stores a list of Objective-C type parameters for a parameterized class or a category/extension thereo...
QualType getPointerType(QualType T) const
Return the uniqued reference to the type for a pointer to the specified type.
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
A reference to a declared variable, function, enum, etc.
Tag that can use a checker name as a message provider (see SimpleProgramPointTag).
QualType getObjCObjectPointerType(QualType OIT) const
Return a ObjCObjectPointerType type for the given ObjCObjectType.
This class provides an interface through which checkers can create individual bug reports...
The receiver is a superclass.
const LocationContext * getLocationContext() const
Represents a call to a C++ constructor.
const LangOptions & getLangOpts() const
The parameter is invariant: must match exactly.
Defines enum values for all the target-independent builtin functions.
SourceManager & getSourceManager()
const LangOptions & getLangOpts() const
ArrayRef< ParmVarDecl * > parameters() const