]> granicus.if.org Git - clang/commitdiff
[arcmt] Don't remove retains/releases on a global variable, flag them with errors...
authorArgyrios Kyrtzidis <akyrtzi@gmail.com>
Thu, 14 Jul 2011 23:32:04 +0000 (23:32 +0000)
committerArgyrios Kyrtzidis <akyrtzi@gmail.com>
Thu, 14 Jul 2011 23:32:04 +0000 (23:32 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@135213 91177308-0d34-0410-b5e6-96231b3b80d8

lib/ARCMigrate/TransRetainReleaseDealloc.cpp
lib/ARCMigrate/TransUnbridgedCasts.cpp
lib/ARCMigrate/Transforms.cpp
lib/ARCMigrate/Transforms.h
test/ARCMT/checking.m

index 4eeb47437e3478bc951cdf3eb975df0339b4cc77..c72312b2600ba6d9aa271bf157601e23764c4d11 100644 (file)
@@ -78,6 +78,15 @@ public:
             Pass.TA.reportError(err, rec->getLocStart());
             return true;
           }
+
+          if (isGlobalVar(rec) &&
+              (E->getMethodFamily() != OMF_retain || isRemovable(E))) {
+            std::string err = "it is not safe to remove '";
+            err += E->getSelector().getAsString() + "' message on "
+                "a global variable";
+            Pass.TA.reportError(err, rec->getLocStart());
+            return true;
+          }
         }
     case OMF_dealloc:
       break;
index 6513d98c9297892d5351e85c604a592716cec1ca..1cacd6d84e6d1fbc2a7c6f2ad980878fda618cad 100644 (file)
@@ -193,17 +193,6 @@ private:
         return true;
     return false;
   }
-
-  static bool isGlobalVar(Expr *E) {
-    E = E->IgnoreParenCasts();
-    if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E))
-      return DRE->getDecl()->getDeclContext()->isFileContext();
-    if (ConditionalOperator *condOp = dyn_cast<ConditionalOperator>(E))
-      return isGlobalVar(condOp->getTrueExpr()) &&
-             isGlobalVar(condOp->getFalseExpr());
-
-    return false;  
-  }
 };
 
 } // end anonymous namespace
index 7a439d95e3adc58e1c75ba9b2120df3f41b65077..7bd95e54bc27081f0d681f205c9e8f3e7703ab18 100644 (file)
@@ -152,6 +152,17 @@ bool trans::hasSideEffects(Expr *E, ASTContext &Ctx) {
   return true;
 }
 
+bool trans::isGlobalVar(Expr *E) {
+  E = E->IgnoreParenCasts();
+  if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E))
+    return DRE->getDecl()->getDeclContext()->isFileContext();
+  if (ConditionalOperator *condOp = dyn_cast<ConditionalOperator>(E))
+    return isGlobalVar(condOp->getTrueExpr()) &&
+           isGlobalVar(condOp->getFalseExpr());
+
+  return false;  
+}
+
 namespace {
 
 class ReferenceClear : public RecursiveASTVisitor<ReferenceClear> {
index 00ff733f47ea7a9dc59906be056e3d03fec17955..b47d6d8e9b8b64e6a9f39d66d131ef40792589b3 100644 (file)
@@ -54,6 +54,8 @@ bool canApplyWeak(ASTContext &Ctx, QualType type);
 SourceLocation findLocationAfterSemi(SourceLocation loc, ASTContext &Ctx);
 
 bool hasSideEffects(Expr *E, ASTContext &Ctx);
+bool isGlobalVar(Expr *E);
+
 
 template <typename BODY_TRANS>
 class BodyTransform : public RecursiveASTVisitor<BodyTransform<BODY_TRANS> > {
index 7ab54ceb05d5457cbec2aa29c7d5cce5e443e76f..2e4ec122d64c7f9ff29f4b77474a4e426817b25b 100644 (file)
@@ -36,10 +36,16 @@ struct UnsafeS {
 - (oneway void)release { } // expected-error {{ARC forbids implementation}}
 @end
 
+id global_foo;
+
 void test1(A *a, BOOL b, struct UnsafeS *unsafeS) {
   [unsafeS->unsafeObj retain]; // expected-error {{it is not safe to remove 'retain' message on an __unsafe_unretained type}} \
                                // expected-error {{ARC forbids explicit message send}}
   id foo = [unsafeS->unsafeObj retain]; // no warning.
+  [global_foo retain]; // expected-error {{it is not safe to remove 'retain' message on a global variable}} \
+                       // expected-error {{ARC forbids explicit message send}}
+  [global_foo release]; // expected-error {{it is not safe to remove 'release' message on a global variable}} \
+                        // expected-error {{ARC forbids explicit message send}}
   [a dealloc];
   [a retain];
   [a retainCount]; // expected-error {{ARC forbids explicit message send of 'retainCount'}}