xazax.hun created this revision. xazax.hun added reviewers: zaks.anna, dcoughlin, jordan_rose. xazax.hun added a subscriber: cfe-commits.
This patch makes the DynamicTypePropagation checker utilize the information about generics. Using this additional information more precise inlining can be done. It also fixes an XFAIL test. The same stored information will be used by a separate general type checker. That checker will make it possible to get rid of the isReturnValueMisused function. http://reviews.llvm.org/D12916 Files: lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp test/Analysis/DynamicTypePropagation.m Index: test/Analysis/DynamicTypePropagation.m =================================================================== --- test/Analysis/DynamicTypePropagation.m +++ test/Analysis/DynamicTypePropagation.m @@ -1,5 +1,4 @@ // RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.osx.cocoa.ObjCGenerics -verify %s -// XFAIL: * #if !__has_feature(objc_generics) # error Compiler does not support Objective-C generics? Index: lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp =================================================================== --- lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp +++ lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp @@ -665,38 +665,36 @@ /// Get the returned ObjCObjectPointerType by a method based on the tracked type /// information, or null pointer when the returned type is not an /// ObjCObjectPointerType. -static const ObjCObjectPointerType *getReturnTypeForMethod( +static QualType getReturnTypeForMethod( const ObjCMethodDecl *Method, ArrayRef<QualType> TypeArgs, const ObjCObjectPointerType *SelfType, ASTContext &C) { QualType StaticResultType = Method->getReturnType(); // Is the return type declared as instance type? if (StaticResultType == C.getObjCInstanceType()) - return SelfType; + return QualType(SelfType, 0); // Check whether the result type depends on a type parameter. if (!isObjCTypeParamDependent(StaticResultType)) - return nullptr; + return QualType(); QualType ResultType = StaticResultType.substObjCTypeArgs( C, TypeArgs, ObjCSubstitutionContext::Result); - return ResultType->getAs<ObjCObjectPointerType>(); + return ResultType; } /// Validate that the return type of a message expression is used correctly. /// Returns true in case an error is detected. bool DynamicTypePropagation::isReturnValueMisused( const ObjCMessageExpr *MessageExpr, - const ObjCObjectPointerType *SeflType, SymbolRef Sym, + const ObjCObjectPointerType *ResultPtrType, SymbolRef Sym, const ObjCMethodDecl *Method, ArrayRef<QualType> TypeArgs, bool SubscriptOrProperty, CheckerContext &C) const { - ASTContext &ASTCtxt = C.getASTContext(); - const auto *ResultPtrType = - getReturnTypeForMethod(Method, TypeArgs, SeflType, ASTCtxt); if (!ResultPtrType) return false; + ASTContext &ASTCtxt = C.getASTContext(); const Stmt *Parent = C.getCurrentAnalysisDeclContext()->getParentMap().getParent(MessageExpr); if (SubscriptOrProperty) { @@ -861,20 +859,34 @@ if (!TypeArgs) return; - if (isReturnValueMisused(MessageExpr, *TrackedType, RecSym, Method, *TypeArgs, - M.getMessageKind() != OCM_Message, C)) + QualType ResultType = + getReturnTypeForMethod(Method, *TypeArgs, *TrackedType, ASTCtxt); + // The static type is the same as the deduced type. + if (ResultType.isNull()) + return; + + const MemRegion *RetRegion = M.getReturnValue().getAsRegion(); + ExplodedNode *Pred = C.getPredecessor(); + if (RetRegion) { + State = setDynamicTypeInfo(State, RetRegion, ResultType, + /*CanBeSubclass=*/true); + Pred = C.addTransition(State); + } + + const auto *ResultPtrType = ResultType->getAs<ObjCObjectPointerType>(); + + if (isReturnValueMisused(MessageExpr, ResultPtrType, RecSym, Method, + *TypeArgs, M.getMessageKind() != OCM_Message, C)) return; - const auto *ResultPtrType = - getReturnTypeForMethod(Method, *TypeArgs, *TrackedType, ASTCtxt); if (!ResultPtrType || ResultPtrType->isUnspecialized()) return; // When the result is a specialized type and it is not tracked yet, track it // for the result symbol. if (!State->get<MostSpecializedTypeArgsMap>(RetSym)) { State = State->set<MostSpecializedTypeArgsMap>(RetSym, ResultPtrType); - C.addTransition(State); + C.addTransition(State, Pred); } }
Index: test/Analysis/DynamicTypePropagation.m =================================================================== --- test/Analysis/DynamicTypePropagation.m +++ test/Analysis/DynamicTypePropagation.m @@ -1,5 +1,4 @@ // RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.osx.cocoa.ObjCGenerics -verify %s -// XFAIL: * #if !__has_feature(objc_generics) # error Compiler does not support Objective-C generics? Index: lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp =================================================================== --- lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp +++ lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp @@ -665,38 +665,36 @@ /// Get the returned ObjCObjectPointerType by a method based on the tracked type /// information, or null pointer when the returned type is not an /// ObjCObjectPointerType. -static const ObjCObjectPointerType *getReturnTypeForMethod( +static QualType getReturnTypeForMethod( const ObjCMethodDecl *Method, ArrayRef<QualType> TypeArgs, const ObjCObjectPointerType *SelfType, ASTContext &C) { QualType StaticResultType = Method->getReturnType(); // Is the return type declared as instance type? if (StaticResultType == C.getObjCInstanceType()) - return SelfType; + return QualType(SelfType, 0); // Check whether the result type depends on a type parameter. if (!isObjCTypeParamDependent(StaticResultType)) - return nullptr; + return QualType(); QualType ResultType = StaticResultType.substObjCTypeArgs( C, TypeArgs, ObjCSubstitutionContext::Result); - return ResultType->getAs<ObjCObjectPointerType>(); + return ResultType; } /// Validate that the return type of a message expression is used correctly. /// Returns true in case an error is detected. bool DynamicTypePropagation::isReturnValueMisused( const ObjCMessageExpr *MessageExpr, - const ObjCObjectPointerType *SeflType, SymbolRef Sym, + const ObjCObjectPointerType *ResultPtrType, SymbolRef Sym, const ObjCMethodDecl *Method, ArrayRef<QualType> TypeArgs, bool SubscriptOrProperty, CheckerContext &C) const { - ASTContext &ASTCtxt = C.getASTContext(); - const auto *ResultPtrType = - getReturnTypeForMethod(Method, TypeArgs, SeflType, ASTCtxt); if (!ResultPtrType) return false; + ASTContext &ASTCtxt = C.getASTContext(); const Stmt *Parent = C.getCurrentAnalysisDeclContext()->getParentMap().getParent(MessageExpr); if (SubscriptOrProperty) { @@ -861,20 +859,34 @@ if (!TypeArgs) return; - if (isReturnValueMisused(MessageExpr, *TrackedType, RecSym, Method, *TypeArgs, - M.getMessageKind() != OCM_Message, C)) + QualType ResultType = + getReturnTypeForMethod(Method, *TypeArgs, *TrackedType, ASTCtxt); + // The static type is the same as the deduced type. + if (ResultType.isNull()) + return; + + const MemRegion *RetRegion = M.getReturnValue().getAsRegion(); + ExplodedNode *Pred = C.getPredecessor(); + if (RetRegion) { + State = setDynamicTypeInfo(State, RetRegion, ResultType, + /*CanBeSubclass=*/true); + Pred = C.addTransition(State); + } + + const auto *ResultPtrType = ResultType->getAs<ObjCObjectPointerType>(); + + if (isReturnValueMisused(MessageExpr, ResultPtrType, RecSym, Method, + *TypeArgs, M.getMessageKind() != OCM_Message, C)) return; - const auto *ResultPtrType = - getReturnTypeForMethod(Method, *TypeArgs, *TrackedType, ASTCtxt); if (!ResultPtrType || ResultPtrType->isUnspecialized()) return; // When the result is a specialized type and it is not tracked yet, track it // for the result symbol. if (!State->get<MostSpecializedTypeArgsMap>(RetSym)) { State = State->set<MostSpecializedTypeArgsMap>(RetSym, ResultPtrType); - C.addTransition(State); + C.addTransition(State, Pred); } }
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits