malhar1995 created this revision.
malhar1995 added a project: clang.

As part of my Google Summer of Code project, I am working on adding support for 
Integer Set Library (ISL) annotations to the current RetainCountChecker.

Note about ISL:
ISL has annotations __isl_give and __isl_take which are analogous to 
cf_returns_retained and cf_consumed but in case of ISL, annotations precede 
datatypes of function parameters.

So far, to build the ISL codebase using scan-build, I was #define-ing 
__isl_give and __isl_take to __attribute__((cf_returns_retained)) and 
__attribute__((cf_consumed)) respectively which resulted in the analyzer 
treating ISL objects as Core Foundation objects while performing reference 
counting.

This patch aims to add support for generic annotations 
(__attribute__(annotate("give"))) and __attribute__(annotate("take")))) in 
RetainCountChecker hence enabling the RetainCountChecker to perform reference 
counting for any codebase written in C.

Let me know your comments on the same.


Repository:
  rL LLVM

https://reviews.llvm.org/D35613

Files:
  include/clang/StaticAnalyzer/Checkers/ObjCRetainCount.h
  lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp
  test/Analysis/retain-release-inline.m

Index: test/Analysis/retain-release-inline.m
===================================================================
--- test/Analysis/retain-release-inline.m
+++ test/Analysis/retain-release-inline.m
@@ -299,15 +299,15 @@
   bar(s);
 }
 
-__attribute__((cf_returns_retained)) isl_basic_map *isl_basic_map_cow(__attribute__((cf_consumed)) isl_basic_map *bmap);
+__attribute__((annotate("give"))) isl_basic_map *isl_basic_map_cow(__attribute__((annotate("take"))) isl_basic_map *bmap);
 void free(void *);
 
 // As 'isl_basic_map_free' is annotated with 'rc_ownership_trusted_implementation', RetainCountChecker trusts its
 // implementation and doesn't analyze its body. If the annotation 'rc_ownership_trusted_implementation' is removed,
 // a leak warning is raised by RetainCountChecker as the analyzer is unable to detect a decrement in the reference
 // count of 'bmap' along the path in 'isl_basic_map_free' assuming the predicate of the second 'if' branch to be
 // true or assuming both the predicates in the function to be false.
-__attribute__((annotate("rc_ownership_trusted_implementation"))) isl_basic_map *isl_basic_map_free(__attribute__((cf_consumed)) isl_basic_map *bmap) {
+__attribute__((annotate("rc_ownership_trusted_implementation"))) isl_basic_map *isl_basic_map_free(__attribute__((annotate("take"))) isl_basic_map *bmap) {
   if (!bmap)
     return NULL;
 
@@ -322,15 +322,15 @@
 // implementation and doesn't analyze its body. If that annotation is removed, a 'use-after-release' warning might
 // be raised by RetainCountChecker as the pointer which is passed as an argument to this function and the pointer
 // which is returned from the function point to the same memory location.
-__attribute__((annotate("rc_ownership_trusted_implementation"))) __attribute__((cf_returns_retained)) isl_basic_map *isl_basic_map_copy(isl_basic_map *bmap) {
+__attribute__((annotate("rc_ownership_trusted_implementation"))) __attribute__((annotate("give"))) isl_basic_map *isl_basic_map_copy(isl_basic_map *bmap) {
   if (!bmap)
     return NULL;
 
   bmap->ref++;
   return bmap;
 }
 
-void test_use_after_release_with_trusted_implementation_annotate_attribute(__attribute__((cf_consumed)) isl_basic_map *bmap) {
+void test_use_after_release_with_trusted_implementation_annotate_attribute(__attribute__((annotate("take"))) isl_basic_map *bmap) {
   // After this call, 'bmap' has a +1 reference count.
   bmap = isl_basic_map_cow(bmap);
   // After the call to 'isl_basic_map_copy', 'bmap' has a +1 reference count.
@@ -341,7 +341,7 @@
   isl_basic_map_free(temp);
 }
 
-void test_leak_with_trusted_implementation_annotate_attribute(__attribute__((cf_consumed)) isl_basic_map *bmap) {
+void test_leak_with_trusted_implementation_annotate_attribute(__attribute__((annotate("take"))) isl_basic_map *bmap) {
   // After this call, 'bmap' has a +1 reference count.
   bmap = isl_basic_map_cow(bmap); // no-warning
   // After this call, 'bmap' has a +0 reference count.
Index: lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp
===================================================================
--- lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp
+++ lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp
@@ -1340,6 +1340,8 @@
 
   if (D->hasAttr<CFReturnsRetainedAttr>())
     return RetEffect::MakeOwned(RetEffect::CF);
+  else if (hasRCAnnotation(D, "give"))
+    return RetEffect::MakeOwned(RetEffect::GenericC);
 
   if (D->hasAttr<CFReturnsNotRetainedAttr>())
     return RetEffect::MakeNotOwned(RetEffect::CF);
@@ -1363,9 +1365,10 @@
     const ParmVarDecl *pd = *pi;
     if (pd->hasAttr<NSConsumedAttr>())
       Template->addArg(AF, parm_idx, DecRefMsg);
-    else if (pd->hasAttr<CFConsumedAttr>())
+    else if (pd->hasAttr<CFConsumedAttr>() || hasRCAnnotation(pd, "take"))
       Template->addArg(AF, parm_idx, DecRef);
-    else if (pd->hasAttr<CFReturnsRetainedAttr>()) {
+    else if (pd->hasAttr<CFReturnsRetainedAttr>() ||
+             hasRCAnnotation(pd, "give")) {
       QualType PointeeTy = pd->getType()->getPointeeType();
       if (!PointeeTy.isNull())
         if (coreFoundation::isCFObjectRef(PointeeTy))
@@ -2005,8 +2008,14 @@
           os << " returns a Core Foundation object of type "
              << Sym->getType().getAsString() << " with a ";
         }
-      }
-      else {
+      } else if (CurrV.getObjKind() == RetEffect::GenericC) {
+        if (Sym->getType().isNull()) {
+          os << " returns an object with a ";
+        } else {
+          os << " returns an object of type " << Sym->getType().getAsString()
+             << " with a ";
+        }
+      } else {
         assert (CurrV.getObjKind() == RetEffect::ObjC);
         QualType T = Sym->getType();
         if (T.isNull() || !isa<ObjCObjectPointerType>(T)) {
Index: include/clang/StaticAnalyzer/Checkers/ObjCRetainCount.h
===================================================================
--- include/clang/StaticAnalyzer/Checkers/ObjCRetainCount.h
+++ include/clang/StaticAnalyzer/Checkers/ObjCRetainCount.h
@@ -145,9 +145,11 @@
     /// Indicates that the tracked object is an Objective-C object.
     ObjC,
     /// Indicates that the tracked object could be a CF or Objective-C object.
-    AnyObj
+    AnyObj,
+    /// Indicates that the tracked object is a generic C object.
+    GenericC
   };
-  
+
 private:
   Kind K;
   ObjKind O;
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to