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

Reply via email to