;
52classDynamicTypePropagation:
53 public Checker< check::PreCall,
56check::PostStmt<CastExpr>,
57check::PostStmt<CXXNewExpr>,
58check::PreObjCMessage,
59check::PostObjCMessage > {
69 mutablestd::unique_ptr<BugType> ObjCGenericsBugType;
70 voidinitBugType()
const{
71 if(!ObjCGenericsBugType)
72ObjCGenericsBugType.reset(
new BugType(
78GenericsBugVisitor(
SymbolRefS) : Sym(S) {}
80 voidProfile(llvm::FoldingSetNodeID &
ID)
const override{
98 const Stmt*ReportedNode =
nullptr)
const;
110 boolCheckGenerics =
false;
115 if(
const auto*
PointerType= dyn_cast<ObjCObjectPointerType>(
Type)) {
116 return PointerType->getObjectType()->isObjCClass();
123 boolPrecise =
false;
125 operator bool()
const{
return Type!=
nullptr; }
159 if(
const auto*ObjTy =
161 return{ObjTy->getObjectType(),
true};
172 SValReceiverSVal =
C.getSVal(RecE);
182 if(InferredType.
isNull()) {
183InferredType = ReceiverSymbol->getType();
188 if(isObjCClassType(InferredType)) {
194 return{cast<ObjCObjectType>(DTI.getType()), !DTI.canBeASubClass()};
197 SValSelfSVal = State->getSelfSVal(
C.getLocationContext());
201 if(ReceiverSVal == SelfSVal) {
205dyn_cast<ObjCMethodDecl>(
C.getStackFrame()->getDecl()))
207MD->getClassInterface()->getTypeForDecl()))
214 if(InferredType.
isNull()) {
220 if(
const auto*ReceiverInferredType =
221dyn_cast<ObjCObjectPointerType>(InferredType)) {
222 return{ReceiverInferredType->getObjectType()};
230voidDynamicTypePropagation::checkDeadSymbols(
SymbolReaper&SR,
235MostSpecializedTypeArgsMapTy TyArgMap =
236State->get<MostSpecializedTypeArgsMap>();
237 for(
SymbolRefSym : llvm::make_first_range(TyArgMap)) {
239State = State->remove<MostSpecializedTypeArgsMap>(Sym);
243 C.addTransition(State);
256 C.addTransition(State);
259voidDynamicTypePropagation::checkPreCall(
const CallEvent&
Call,
270 switch(Ctor->getOriginExpr()->getConstructionKind()) {
271 caseCXXConstructionKind::Complete:
272 caseCXXConstructionKind::Delegating:
275 caseCXXConstructionKind::NonVirtualBase:
276 caseCXXConstructionKind::VirtualBase:
287 if(!Dtor->isBaseDestructor())
294 const Decl*
D= Dtor->getDecl();
303voidDynamicTypePropagation::checkPostCall(
const CallEvent&
Call,
309 const MemRegion*RetReg =
Call.getReturnValue().getAsRegion();
316 if(
D&&
D->hasRelatedResultType()) {
317 switch(Msg->getMethodFamily()) {
327RuntimeType ObjTy = inferReceiverType(*Msg,
C);
333 C.getASTContext().getObjCObjectPointerType(
QualType(ObjTy.Type, 0));
348 const MemRegion*RecReg = Msg->getReceiverSVal().getAsRegion();
362 switch(Ctor->getOriginExpr()->getConstructionKind()) {
363 caseCXXConstructionKind::Complete:
364 caseCXXConstructionKind::Delegating:
371 caseCXXConstructionKind::NonVirtualBase:
372 caseCXXConstructionKind::VirtualBase:
384 if(isa_and_nonnull<InitListExpr>(
399ExplodedNode*DynamicTypePropagation::dynamicTypePropagationOnCasts(
402 const MemRegion*ToR =
C.getSVal(CE).getAsRegion();
404 return C.getPredecessor();
406 if(isa<ExplicitCastExpr>(CE))
407 return C.getPredecessor();
409 if(
const Type*NewTy = getBetterObjCType(CE,
C)) {
411 return C.addTransition(State);
413 return C.getPredecessor();
416voidDynamicTypePropagation::checkPostStmt(
const CXXNewExpr*NewE,
422 const MemRegion*MR =
C.getSVal(NewE).getAsRegion();
434DynamicTypePropagation::getBetterObjCType(
const Expr*CastE,
436 const MemRegion*ToR =
C.getSVal(CastE).getAsRegion();
474 returnMostInformativeCandidate;
486 const auto*SuperOfTo =
490 C.getObjCObjectPointerType(
QualType(SuperOfTo, 0));
497MostInformativeCandidate,
C);
563assert(!Current || (*Current)->isSpecialized());
568State = State->set<MostSpecializedTypeArgsMap>(Sym, StaticLowerBound);
574State = State->set<MostSpecializedTypeArgsMap>(Sym, WithMostInfo);
579 if(
C.canAssignObjCInterfaces(StaticLowerBound, *Current)) {
584 if(
C.canAssignObjCInterfaces(*Current, StaticUpperBound)) {
590 if(WithMostInfo == *Current)
592State = State->set<MostSpecializedTypeArgsMap>(Sym, WithMostInfo);
599 if(WithMostInfo != *Current) {
600State = State->set<MostSpecializedTypeArgsMap>(Sym, WithMostInfo);
610voidDynamicTypePropagation::checkPostStmt(
const CastExpr*CE,
621 if(!OrigObjectPtrType || !DestObjectPtrType)
625 ExplodedNode*AfterTypeProp = dynamicTypePropagationOnCasts(CE, State,
C);
634OrigObjectPtrType = OrigObjectPtrType->stripObjCKindOfTypeAndQuals(ASTCtxt);
637 if(OrigObjectPtrType->isUnspecialized() &&
646State->get<MostSpecializedTypeArgsMap>(Sym);
648 if(isa<ExplicitCastExpr>(CE)) {
658State = State->remove<MostSpecializedTypeArgsMap>(Sym);
659 C.addTransition(State, AfterTypeProp);
678 ExplodedNode*N =
C.addTransition(State, AfterTypeProp, &IllegalConv);
679reportGenericsBug(*TrackedType, DestObjectPtrType, N, Sym,
C);
687 if(OrigToDest && !DestToOrig)
688std::swap(LowerBound, UpperBound);
691LowerBound = LowerBound->
isObjCIdType() ? UpperBound : LowerBound;
692UpperBound = UpperBound->
isObjCIdType() ? LowerBound : UpperBound;
696 C.addTransition(State, AfterTypeProp);
713 classIsObjCTypeParamDependentTypeVisitor
716IsObjCTypeParamDependentTypeVisitor() =
default;
718 if(isa<ObjCTypeParamDecl>(
Type->getDecl())) {
725 boolResult =
false;
728IsObjCTypeParamDependentTypeVisitor Visitor;
729Visitor.TraverseType(
Type);
730 returnVisitor.Result;
778 if(StaticResultType ==
C.getObjCInstanceType())
786 C, TypeArgs, ObjCSubstitutionContext::Result);
793voidDynamicTypePropagation::checkPreObjCMessage(
const ObjCMethodCall&M,
801State->get<MostSpecializedTypeArgsMap>(Sym);
844 if(TypeParam->getVariance() != ObjCTypeParamVariance::Invariant)
848std::optional<ArrayRef<QualType>> TypeArgs =
855 for(
unsignedi = 0; i < Method->
param_size(); i++) {
864ASTCtxt, *TypeArgs, ObjCSubstitutionContext::Parameter);
867 const auto*ArgObjectPtrType =
869 if(!ParamObjectPtrType || !ArgObjectPtrType)
878State->get<MostSpecializedTypeArgsMap>(ArgSym);
879 if(TrackedArgType &&
881ArgObjectPtrType = *TrackedArgType;
890reportGenericsBug(ArgObjectPtrType, ParamObjectPtrType, N, Sym,
C, Arg);
903voidDynamicTypePropagation::checkPostObjCMessage(
const ObjCMethodCall&M,
917 if(RuntimeType ReceiverRuntimeType = inferReceiverType(M,
C)) {
919ReceiverRuntimeType.Type->getSuperClassType();
920 QualTypeReceiverClassType(ReceiverRuntimeType.Type, 0);
923 if(ReceiverRuntimeType.Type->isSpecialized() &&
924ReceiverRuntimeType.Precise) {
926 C.getASTContext().getObjCObjectPointerType(ReceiverClassType);
927 const auto*InferredType =
929State = State->set<MostSpecializedTypeArgsMap>(RetSym, InferredType);
934!ReceiverRuntimeType.Precise);
936 C.addTransition(State);
944 if(RuntimeType ReceiverRuntimeType = inferReceiverType(M,
C)) {
948ReceiverRuntimeType.Type->getSuperClassType();
954 if(!ReceiversSuperClass.
isNull()) {
957State, RetSym, ReceiversSuperClass, !ReceiverRuntimeType.Precise);
959 C.addTransition(State);
971State->get<MostSpecializedTypeArgsMap>(RecSym);
981std::optional<ArrayRef<QualType>> TypeArgs =
989 if(ResultType.
isNull())
1003Pred =
C.addTransition(State);
1008 if(!ResultPtrType || ResultPtrType->isUnspecialized())
1013 if(!State->get<MostSpecializedTypeArgsMap>(RetSym)) {
1014State = State->set<MostSpecializedTypeArgsMap>(RetSym, ResultPtrType);
1015 C.addTransition(State, Pred);
1019voidDynamicTypePropagation::reportGenericsBug(
1022 const Stmt*ReportedNode)
const{
1028llvm::raw_svector_ostream OS(Buf);
1029OS <<
"Conversion from value of type '";
1031OS <<
"' to incompatible type '";
1034 autoR = std::make_unique<PathSensitiveBugReport>(*ObjCGenericsBugType,
1036R->markInteresting(Sym);
1037R->addVisitor(std::make_unique<GenericsBugVisitor>(Sym));
1040 C.emitReport(std::move(R));
1050state->get<MostSpecializedTypeArgsMap>(Sym);
1052statePrev->get<MostSpecializedTypeArgsMap>(Sym);
1056 if(TrackedTypePrev && *TrackedTypePrev == *TrackedType)
1067llvm::raw_svector_ostream OS(Buf);
1070OS <<
"' is inferred from ";
1072 if(
const auto*ExplicitCast = dyn_cast<ExplicitCastExpr>(S)) {
1073OS <<
"explicit cast (from '";
1078LangOpts, llvm::Twine());
1080}
else if(
const auto*ImplicitCast = dyn_cast<ImplicitCastExpr>(S)) {
1081OS <<
"implicit cast (from '";
1086LangOpts, llvm::Twine());
1089OS <<
"this context";
1095 returnstd::make_shared<PathDiagnosticEventPiece>(Pos, OS.str(),
true);
1100DynamicTypePropagation *checker = mgr.
getChecker<DynamicTypePropagation>();
1101checker->CheckGenerics =
true;
1105boolento::shouldRegisterObjCGenericsChecker(
const CheckerManager&mgr) {
1113boolento::shouldRegisterDynamicTypePropagation(
const CheckerManager&mgr) {
Defines enum values for all the target-independent builtin functions.
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,...
static void recordFixedType(const MemRegion *Region, const CXXMethodDecl *MD, CheckerContext &C)
static const ObjCObjectPointerType * getMostInformativeDerivedClassImpl(const ObjCObjectPointerType *From, const ObjCObjectPointerType *To, const ObjCObjectPointerType *MostInformativeCandidate, ASTContext &C)
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. However it might be av...
static bool isObjCTypeParamDependent(QualType Type)
static const Expr * stripCastsAndSugar(const Expr *E)
static const ObjCObjectPointerType * getMostInformativeDerivedClass(const ObjCObjectPointerType *From, const ObjCObjectPointerType *To, ASTContext &C)
A downcast may loose specialization information. E. g.: MutableMap<T, U> : Map The downcast to Mutabl...
static bool storeWhenMoreInformative(ProgramStateRef &State, SymbolRef Sym, const ObjCObjectPointerType *const *Current, const ObjCObjectPointerType *StaticLowerBound, const ObjCObjectPointerType *StaticUpperBound, ASTContext &C)
Inputs:
llvm::MachO::Target Target
#define REGISTER_MAP_WITH_PROGRAMSTATE(Name, Key, Value)
Declares an immutable map of type NameTy, suitable for placement into the ProgramState.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
QualType getRecordType(const RecordDecl *Decl) const
QualType getPointerType(QualType T) const
Return the uniqued reference to the type for a pointer to the specified type.
bool canAssignObjCInterfaces(const ObjCObjectPointerType *LHSOPT, const ObjCObjectPointerType *RHSOPT)
canAssignObjCInterfaces - Return true if the two interface types are compatible for assignment from R...
const LangOptions & getLangOpts() const
Represents a static or instance method of a struct/union/class.
const CXXRecordDecl * getParent() const
Return the parent of this method declaration, which is the class in which this method is defined.
Represents a new-expression for memory allocation and constructor calls, e.g: "new CXXNewExpr(foo)".
CastExpr - Base class for type casts, including both implicit casts (ImplicitCastExpr) and explicit c...
CastKind getCastKind() const
Decl - This represents one declaration (or definition), e.g.
DeclContext * getDeclContext()
Recursive AST visitor that supports extension via dynamic dispatch.
This represents one expression.
Expr * IgnoreParenImpCasts() LLVM_READONLY
Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
It wraps the AnalysisDeclContext to represent both the call stack with the help of StackFrameContext ...
const Decl * getDecl() const
const ParentMap & getParentMap() const
Represents an ObjC class declaration.
ObjCMethodDecl * lookupClassMethod(Selector Sel) const
Lookup a class method for a given selector.
ObjCMethodDecl * lookupInstanceMethod(Selector Sel) const
Lookup an instance method for a given selector.
ObjCInterfaceDecl * getCanonicalDecl() override
Retrieves the canonical declaration of this Objective-C class.
bool isSuperClassOf(const ObjCInterfaceDecl *I) const
isSuperClassOf - Return true if this class is the specified class or is a super class of the specifie...
An expression that sends a message to the given Objective-C object or class.
Expr * getArg(unsigned Arg)
getArg - Return the specified argument.
Expr * getInstanceReceiver()
Returns the object expression (receiver) for an instance message, or null for a message that is not a...
Selector getSelector() const
@ SuperInstance
The receiver is the instance of the superclass object.
@ Instance
The receiver is an object instance.
@ SuperClass
The receiver is a superclass.
@ Class
The receiver is a class.
QualType getClassReceiver() const
Returns the type of a class message send, or NULL if the message is not a class message.
QualType getSuperType() const
Retrieve the type referred to by 'super'.
const ObjCMethodDecl * getMethodDecl() const
ReceiverKind getReceiverKind() const
Determine the kind of receiver that this message is being sent to.
QualType getReceiverType() const
Retrieve the receiver type to which this message is being directed.
ObjCMethodDecl - Represents an instance or class method declaration.
ArrayRef< ParmVarDecl * > parameters() const
unsigned param_size() const
QualType getReturnType() const
ObjCInterfaceDecl * getClassInterface()
Represents a pointer to an Objective C object.
bool isSpecialized() const
Whether this type is specialized, meaning that it has type arguments.
const ObjCObjectPointerType * stripObjCKindOfTypeAndQuals(const ASTContext &ctx) const
Strip off the Objective-C "kindof" type and (with it) any protocol qualifiers.
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.
bool isObjCIdType() const
True if this is equivalent to the 'id' type, i.e.
ObjCInterfaceDecl * getInterfaceDecl() const
If this pointer points to an Objective @interface type, gets the declaration for that interface.
Represents a class type in Objective C.
QualType getSuperClassType() const
Retrieve the type of the superclass of this object type.
Represents the declaration of an Objective-C type parameter.
Stores a list of Objective-C type parameters for a parameterized class or a category/extension thereo...
Represents a type parameter type in Objective C.
OpaqueValueExpr - An expression referring to an opaque object of a fixed type and value class.
Stmt * getParent(Stmt *) const
Represents a parameter to a function.
PointerType - C99 6.7.5.1 - Pointer Declarators.
PseudoObjectExpr - An expression which accesses a pseudo-object l-value.
A (possibly-)qualified type.
bool isNull() const
Return true if this QualType doesn't point to a type yet.
void print(raw_ostream &OS, const PrintingPolicy &Policy, const Twine &PlaceHolder=Twine(), unsigned Indentation=0) const
QualType getCanonicalType() const
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 collection of all-type qualifiers we support.
Smart pointer class that efficiently represents Objective-C method names.
std::string getAsString() const
Derive the full selector name (e.g.
Stmt - This represents one statement.
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
The base class of the type hierarchy.
const T * castAs() const
Member-template castAs<specific type>.
bool isObjCIdType() const
bool isObjCClassType() const
const T * getAs() const
Member-template getAs<specific type>'.
ASTContext & getASTContext() const
const SourceManager & getSourceManager() const
BugReporterVisitors are used to add custom diagnostics along a path.
Represents a call to a C++ constructor.
Represents an implicit call to a C++ destructor.
Represents an abstract call to a function or method along a particular path.
virtual SVal getArgSVal(unsigned Index) const
Returns the value of a given argument at the time of the call.
SVal getReturnValue() const
Returns the return value of the call.
CHECKER * registerChecker(AT &&... Args)
Used to register checkers.
CheckerNameRef getCurrentCheckerName() const
This wrapper is used to ensure that only StringRefs originating from the CheckerRegistry are used as ...
Tag that can use a checker name as a message provider (see SimpleProgramPointTag).
Stores the currently inferred strictest bound on the runtime type of a region in a given state along ...
QualType getType() const
Returns the currently inferred upper bound on the runtime type.
const ProgramStateRef & getState() const
const Stmt * getStmtForDiagnostics() const
If the node's program point corresponds to a statement, retrieve that statement.
const LocationContext * getLocationContext() const
ExplodedNode * getFirstPred()
MemRegion - The root abstract class for all memory regions.
Represents any expression that calls an Objective-C method.
const ObjCMessageExpr * getOriginExpr() const override
Returns the expression whose value will be the result of this call.
SVal getReceiverSVal() const
Returns the value of the receiver at the time of this call.
SVal - This represents a symbolic expression, which can be either an L-value or an R-value.
SymbolRef getAsSymbol(bool IncludeBaseRegions=false) const
If this SVal wraps a symbol return that SymbolRef.
const MemRegion * getAsRegion() const
A class responsible for cleaning up unused symbols.
bool isDead(SymbolRef sym)
Returns whether or not a symbol has been confirmed dead.
const char *const CoreFoundationObjectiveC
ProgramStateRef setClassObjectDynamicTypeInfo(ProgramStateRef State, SymbolRef Sym, DynamicTypeInfo NewTy)
Set constraint on a type contained in a class object; return the new state.
ProgramStateRef removeDeadClassObjectTypes(ProgramStateRef State, SymbolReaper &SR)
Removes the dead Class object type informations from State.
DynamicTypeInfo getDynamicTypeInfo(ProgramStateRef State, const MemRegion *MR)
Get dynamic type information for the region MR.
const DynamicTypeInfo * getRawDynamicTypeInfo(ProgramStateRef State, const MemRegion *MR)
Get raw dynamic type information for the region MR.
ProgramStateRef setDynamicTypeInfo(ProgramStateRef State, const MemRegion *MR, DynamicTypeInfo NewTy)
Set dynamic type information of the region; return the new state.
ProgramStateRef removeDeadTypes(ProgramStateRef State, SymbolReaper &SR)
Removes the dead type informations from State.
std::shared_ptr< PathDiagnosticPiece > PathDiagnosticPieceRef
DynamicTypeInfo getClassObjectDynamicTypeInfo(ProgramStateRef State, SymbolRef Sym)
Get dynamic type information stored in a class object represented by Sym.
The JSON file list parser is used to communicate input to InstallAPI.
@ Interface
The "__interface" keyword introduces the elaborated-type-specifier.
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4