r348396 - [analyzer] Attribute for RetainCountChecker for OSObject should propagate with inheritance

George Karpenkov via cfe-commits cfe-commits at lists.llvm.org
Wed Dec 5 10:34:54 PST 2018


Author: george.karpenkov
Date: Wed Dec  5 10:34:54 2018
New Revision: 348396

URL: http://llvm.org/viewvc/llvm-project?rev=348396&view=rev
Log:
[analyzer] Attribute for RetainCountChecker for OSObject should propagate with inheritance

rdar://46388388

Differential Revision: https://reviews.llvm.org/D55154

Modified:
    cfe/trunk/lib/StaticAnalyzer/Core/RetainSummaryManager.cpp
    cfe/trunk/test/Analysis/osobject-retain-release.cpp

Modified: cfe/trunk/lib/StaticAnalyzer/Core/RetainSummaryManager.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/RetainSummaryManager.cpp?rev=348396&r1=348395&r2=348396&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/RetainSummaryManager.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/RetainSummaryManager.cpp Wed Dec  5 10:34:54 2018
@@ -686,9 +686,59 @@ RetainSummaryManager::getRetEffectFromAn
     return RetEffect::MakeNotOwned(RetEffect::Generalized);
   }
 
+  if (const auto *MD = dyn_cast<CXXMethodDecl>(D))
+    for (const auto *PD : MD->overridden_methods())
+      if (auto RE = getRetEffectFromAnnotations(RetTy, PD))
+        return RE;
+
   return None;
 }
 
+/// Apply the annotation of {@code pd} in function {@code FD}
+/// to the resulting summary stored in out-parameter {@code Template}.
+/// Return whether an annotation was applied.
+bool applyFunctionParamAnnotationEffect(const ParmVarDecl *pd,
+                                        unsigned parm_idx,
+                                        const FunctionDecl *FD,
+                                        ArgEffects::Factory &AF,
+                                        RetainSummaryTemplate &Template) {
+  if (pd->hasAttr<NSConsumedAttr>()) {
+    Template->addArg(AF, parm_idx, DecRefMsg);
+    return true;
+  } else if (pd->hasAttr<CFConsumedAttr>() || pd->hasAttr<OSConsumedAttr>() ||
+             hasRCAnnotation(pd, "rc_ownership_consumed")) {
+    Template->addArg(AF, parm_idx, DecRef);
+    return true;
+  } else if (pd->hasAttr<CFReturnsRetainedAttr>() ||
+             hasRCAnnotation(pd, "rc_ownership_returns_retained")) {
+    QualType PointeeTy = pd->getType()->getPointeeType();
+    if (!PointeeTy.isNull()) {
+      if (coreFoundation::isCFObjectRef(PointeeTy)) {
+        Template->addArg(AF, parm_idx, RetainedOutParameter);
+        return true;
+      }
+    }
+  } else if (pd->hasAttr<CFReturnsNotRetainedAttr>()) {
+    QualType PointeeTy = pd->getType()->getPointeeType();
+    if (!PointeeTy.isNull()) {
+      if (coreFoundation::isCFObjectRef(PointeeTy)) {
+        Template->addArg(AF, parm_idx, UnretainedOutParameter);
+        return true;
+      }
+    }
+  } else {
+    if (const auto *MD = dyn_cast<CXXMethodDecl>(FD)) {
+      for (const auto *OD : MD->overridden_methods()) {
+        const ParmVarDecl *OP = OD->parameters()[parm_idx];
+        if (applyFunctionParamAnnotationEffect(OP, parm_idx, MD, AF, Template))
+          return true;
+      }
+    }
+  }
+
+  return false;
+}
+
 void
 RetainSummaryManager::updateSummaryFromAnnotations(const RetainSummary *&Summ,
                                                    const FunctionDecl *FD) {
@@ -703,24 +753,7 @@ RetainSummaryManager::updateSummaryFromA
   for (auto pi = FD->param_begin(),
          pe = FD->param_end(); pi != pe; ++pi, ++parm_idx) {
     const ParmVarDecl *pd = *pi;
-    if (pd->hasAttr<NSConsumedAttr>()) {
-      Template->addArg(AF, parm_idx, DecRefMsg);
-    } else if (pd->hasAttr<CFConsumedAttr>() ||
-             pd->hasAttr<OSConsumedAttr>() ||
-             hasRCAnnotation(pd, "rc_ownership_consumed")) {
-      Template->addArg(AF, parm_idx, DecRef);
-    } else if (pd->hasAttr<CFReturnsRetainedAttr>() ||
-             hasRCAnnotation(pd, "rc_ownership_returns_retained")) {
-      QualType PointeeTy = pd->getType()->getPointeeType();
-      if (!PointeeTy.isNull())
-        if (coreFoundation::isCFObjectRef(PointeeTy))
-          Template->addArg(AF, parm_idx, RetainedOutParameter);
-    } else if (pd->hasAttr<CFReturnsNotRetainedAttr>()) {
-      QualType PointeeTy = pd->getType()->getPointeeType();
-      if (!PointeeTy.isNull())
-        if (coreFoundation::isCFObjectRef(PointeeTy))
-          Template->addArg(AF, parm_idx, UnretainedOutParameter);
-    }
+    applyFunctionParamAnnotationEffect(pd, parm_idx, FD, AF, Template);
   }
 
   QualType RetTy = FD->getReturnType();

Modified: cfe/trunk/test/Analysis/osobject-retain-release.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/osobject-retain-release.cpp?rev=348396&r1=348395&r2=348396&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/osobject-retain-release.cpp (original)
+++ cfe/trunk/test/Analysis/osobject-retain-release.cpp Wed Dec  5 10:34:54 2018
@@ -21,12 +21,13 @@ struct OSObject {
 
   unsigned int foo() { return 42; }
 
+  virtual OS_RETURNS_NOT_RETAINED OSObject *identity();
+
   static OSObject *generateObject(int);
 
   static OSObject *getObject();
   static OSObject *GetObject();
 
-
   static void * operator new(size_t size);
 
   static const OSMetaClass * const metaClass;
@@ -40,6 +41,12 @@ struct OSIterator : public OSObject {
 struct OSArray : public OSObject {
   unsigned int getCount();
 
+  OSIterator * getIterator();
+
+  OSObject *identity() override;
+
+  virtual void consumeReference(OS_CONSUME OSArray *other);
+
   static OSArray *generateArrayHasCode() {
     return new OSArray;
   }
@@ -51,14 +58,18 @@ struct OSArray : public OSObject {
     return nullptr;
   }
 
-  OSIterator * getIterator();
-
   static OS_RETURNS_NOT_RETAINED OSArray *MaskedGetter();
   static OS_RETURNS_RETAINED OSArray *getOoopsActuallyCreate();
 
   static const OSMetaClass * const metaClass;
 };
 
+struct MyArray : public OSArray {
+  void consumeReference(OSArray *other) override;
+
+  OSObject *identity() override;
+};
+
 struct OtherStruct {
   static void doNothingToArray(OSArray *array);
   OtherStruct(OSArray *arr);
@@ -68,6 +79,27 @@ struct OSMetaClassBase {
   static OSObject *safeMetaCast(const OSObject *inst, const OSMetaClass *meta);
 };
 
+void check_param_attribute_propagation(MyArray *parent) {
+  OSArray *arr = new OSArray;
+  parent->consumeReference(arr);
+}
+
+unsigned int check_attribute_propagation(OSArray *arr) {
+  OSObject *other = arr->identity();
+  OSArray *casted = OSDynamicCast(OSArray, other);
+  if (casted)
+    return casted->getCount();
+  return 0;
+}
+
+unsigned int check_attribute_indirect_propagation(MyArray *arr) {
+  OSObject *other = arr->identity();
+  OSArray *casted = OSDynamicCast(OSArray, other);
+  if (casted)
+    return casted->getCount();
+  return 0;
+}
+
 void check_free_no_error() {
   OSArray *arr = OSArray::withCapacity(10);
   arr->retain();




More information about the cfe-commits mailing list