[cfe-commits] r135381 - in /cfe/trunk: lib/ARCMigrate/ARCMT.cpp lib/ARCMigrate/CMakeLists.txt lib/ARCMigrate/Internals.h lib/ARCMigrate/TransAPIUses.cpp lib/ARCMigrate/TransformActions.cpp lib/ARCMigrate/Transforms.cpp lib/ARCMigrate/Transforms.h test/ARCMT/check-api.m

Argyrios Kyrtzidis akyrtzi at gmail.com
Mon Jul 18 00:44:45 PDT 2011


Author: akirtzidis
Date: Mon Jul 18 02:44:45 2011
New Revision: 135381

URL: http://llvm.org/viewvc/llvm-project?rev=135381&view=rev
Log:
[arcmt] NSInvocation's [get/set]ReturnValue and [get/set]Argument are only safe
with __unsafe_unretained parameters. Emit error for strong/weak ones. rdar://9206226

Added:
    cfe/trunk/lib/ARCMigrate/TransAPIUses.cpp
    cfe/trunk/test/ARCMT/check-api.m
Modified:
    cfe/trunk/lib/ARCMigrate/ARCMT.cpp
    cfe/trunk/lib/ARCMigrate/CMakeLists.txt
    cfe/trunk/lib/ARCMigrate/Internals.h
    cfe/trunk/lib/ARCMigrate/TransformActions.cpp
    cfe/trunk/lib/ARCMigrate/Transforms.cpp
    cfe/trunk/lib/ARCMigrate/Transforms.h

Modified: cfe/trunk/lib/ARCMigrate/ARCMT.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ARCMigrate/ARCMT.cpp?rev=135381&r1=135380&r2=135381&view=diff
==============================================================================
--- cfe/trunk/lib/ARCMigrate/ARCMT.cpp (original)
+++ cfe/trunk/lib/ARCMigrate/ARCMT.cpp Mon Jul 18 02:44:45 2011
@@ -266,7 +266,7 @@
   // to remove it so that we don't get errors from normal compilation.
   origCI.getLangOpts().ObjCAutoRefCount = false;
 
-  return capturedDiags.hasErrors();
+  return capturedDiags.hasErrors() || testAct.hasReportedErrors();
 }
 
 //===----------------------------------------------------------------------===//

Modified: cfe/trunk/lib/ARCMigrate/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ARCMigrate/CMakeLists.txt?rev=135381&r1=135380&r2=135381&view=diff
==============================================================================
--- cfe/trunk/lib/ARCMigrate/CMakeLists.txt (original)
+++ cfe/trunk/lib/ARCMigrate/CMakeLists.txt Mon Jul 18 02:44:45 2011
@@ -4,6 +4,7 @@
   ARCMT.cpp
   ARCMTActions.cpp
   FileRemapper.cpp
+  TransAPIUses.cpp
   TransARCAssign.cpp
   TransAutoreleasePool.cpp
   TransBlockObjCVariable.cpp

Modified: cfe/trunk/lib/ARCMigrate/Internals.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ARCMigrate/Internals.h?rev=135381&r1=135380&r2=135381&view=diff
==============================================================================
--- cfe/trunk/lib/ARCMigrate/Internals.h (original)
+++ cfe/trunk/lib/ARCMigrate/Internals.h Mon Jul 18 02:44:45 2011
@@ -37,6 +37,7 @@
 class TransformActions {
   Diagnostic &Diags;
   CapturedDiagList &CapturedDiags;
+  bool ReportedErrors;
   void *Impl; // TransformActionsImpl.
 
 public:
@@ -88,6 +89,8 @@
   void reportNote(llvm::StringRef note, SourceLocation loc,
                   SourceRange range = SourceRange());
 
+  bool hasReportedErrors() const { return ReportedErrors; }
+
   class RewriteReceiver {
   public:
     virtual ~RewriteReceiver();

Added: cfe/trunk/lib/ARCMigrate/TransAPIUses.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ARCMigrate/TransAPIUses.cpp?rev=135381&view=auto
==============================================================================
--- cfe/trunk/lib/ARCMigrate/TransAPIUses.cpp (added)
+++ cfe/trunk/lib/ARCMigrate/TransAPIUses.cpp Mon Jul 18 02:44:45 2011
@@ -0,0 +1,89 @@
+//===--- TransAPIUses.cpp - Tranformations to ARC mode --------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// checkAPIUses:
+//
+// Emits error with some API uses that are not safe in ARC mode:
+//
+// - NSInvocation's [get/set]ReturnValue and [get/set]Argument are only safe
+//   with __unsafe_unretained objects.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Transforms.h"
+#include "Internals.h"
+
+using namespace clang;
+using namespace arcmt;
+using namespace trans;
+using llvm::StringRef;
+
+namespace {
+
+class APIChecker : public RecursiveASTVisitor<APIChecker> {
+  MigrationPass &Pass;
+  Selector getReturnValueSel, setReturnValueSel;
+  Selector getArgumentSel, setArgumentSel;
+
+public:
+  APIChecker(MigrationPass &pass) : Pass(pass) {
+    SelectorTable &sels = Pass.Ctx.Selectors;
+    IdentifierTable &ids = Pass.Ctx.Idents;
+    getReturnValueSel = sels.getUnarySelector(&ids.get("getReturnValue"));
+    setReturnValueSel = sels.getUnarySelector(&ids.get("setReturnValue"));
+
+    IdentifierInfo *selIds[2];
+    selIds[0] = &ids.get("getArgument");
+    selIds[1] = &ids.get("atIndex");
+    getArgumentSel = sels.getSelector(2, selIds);
+    selIds[0] = &ids.get("setArgument");
+    setArgumentSel = sels.getSelector(2, selIds);
+  }
+
+  bool VisitObjCMessageExpr(ObjCMessageExpr *E) {
+    if (E->isInstanceMessage() &&
+        E->getReceiverInterface() &&
+        E->getReceiverInterface()->getName() == "NSInvocation") {
+      StringRef selName;
+      if (E->getSelector() == getReturnValueSel)
+        selName = "getReturnValue";
+      else if (E->getSelector() == setReturnValueSel)
+        selName = "setReturnValue";
+      else if (E->getSelector() == getArgumentSel)
+        selName = "getArgument";
+      else if (E->getSelector() == setArgumentSel)
+        selName = "setArgument";
+
+      if (selName.empty())
+        return true;
+
+      Expr *parm = E->getArg(0)->IgnoreParenCasts();
+      QualType pointee = parm->getType()->getPointeeType();
+      if (pointee.isNull())
+        return true;
+
+      if (pointee.getObjCLifetime() > Qualifiers::OCL_ExplicitNone) {
+        std::string err = "NSInvocation's ";
+        err += selName;
+        err += " is not safe to be used with an object with ownership other "
+            "than __unsafe_unretained";
+        Pass.TA.reportError(err, parm->getLocStart(), parm->getSourceRange());
+      }
+      return true;
+    }
+
+    return true;
+  }
+};
+
+} // anonymous namespace
+
+void trans::checkAPIUses(MigrationPass &pass) {
+  APIChecker(pass).TraverseDecl(pass.Ctx.getTranslationUnitDecl());
+}

Modified: cfe/trunk/lib/ARCMigrate/TransformActions.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ARCMigrate/TransformActions.cpp?rev=135381&r1=135380&r2=135381&view=diff
==============================================================================
--- cfe/trunk/lib/ARCMigrate/TransformActions.cpp (original)
+++ cfe/trunk/lib/ARCMigrate/TransformActions.cpp Mon Jul 18 02:44:45 2011
@@ -600,7 +600,7 @@
 TransformActions::TransformActions(Diagnostic &diag,
                                    CapturedDiagList &capturedDiags,
                                    ASTContext &ctx, Preprocessor &PP)
-  : Diags(diag), CapturedDiags(capturedDiags) {
+  : Diags(diag), CapturedDiags(capturedDiags), ReportedErrors(false) {
   Impl = new TransformActionsImpl(capturedDiags, ctx, PP);
 }
 
@@ -683,6 +683,7 @@
      = Diags.getDiagnosticIDs()->getCustomDiagID(DiagnosticIDs::Error,
                                                  rewriteErr);
   Diags.Report(loc, diagID) << range;
+  ReportedErrors = true;
 }
 
 void TransformActions::reportNote(llvm::StringRef note, SourceLocation loc,

Modified: cfe/trunk/lib/ARCMigrate/Transforms.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ARCMigrate/Transforms.cpp?rev=135381&r1=135380&r2=135381&view=diff
==============================================================================
--- cfe/trunk/lib/ARCMigrate/Transforms.cpp (original)
+++ cfe/trunk/lib/ARCMigrate/Transforms.cpp Mon Jul 18 02:44:45 2011
@@ -283,6 +283,7 @@
   makeAssignARCSafe(pass);
   rewriteUnbridgedCasts(pass);
   rewriteBlockObjCVariable(pass);
+  checkAPIUses(pass);
 }
 
 std::vector<TransformFn> arcmt::getAllTransformations() {

Modified: cfe/trunk/lib/ARCMigrate/Transforms.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ARCMigrate/Transforms.h?rev=135381&r1=135380&r2=135381&view=diff
==============================================================================
--- cfe/trunk/lib/ARCMigrate/Transforms.h (original)
+++ cfe/trunk/lib/ARCMigrate/Transforms.h Mon Jul 18 02:44:45 2011
@@ -37,6 +37,7 @@
 void rewriteProperties(MigrationPass &pass);
 void rewriteBlockObjCVariable(MigrationPass &pass);
 void rewriteUnusedInitDelegate(MigrationPass &pass);
+void checkAPIUses(MigrationPass &pass);
 
 void removeEmptyStatementsAndDealloc(MigrationPass &pass);
 
@@ -65,7 +66,8 @@
   BodyTransform(MigrationPass &pass) : Pass(pass) { }
 
   bool TraverseStmt(Stmt *rootS) {
-    BODY_TRANS(Pass).transformBody(rootS);
+    if (rootS)
+      BODY_TRANS(Pass).transformBody(rootS);
     return true;
   }
 };

Added: cfe/trunk/test/ARCMT/check-api.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/ARCMT/check-api.m?rev=135381&view=auto
==============================================================================
--- cfe/trunk/test/ARCMT/check-api.m (added)
+++ cfe/trunk/test/ARCMT/check-api.m Mon Jul 18 02:44:45 2011
@@ -0,0 +1,43 @@
+// RUN: %clang_cc1 -arcmt-check -verify -triple x86_64-apple-macosx10.7 -fobjc-nonfragile-abi %s
+
+#include "Common.h"
+
+ at interface NSInvocation : NSObject
+- (void)getReturnValue:(void *)retLoc;
+- (void)setReturnValue:(void *)retLoc;
+
+- (void)getArgument:(void *)argumentLocation atIndex:(int)idx;
+- (void)setArgument:(void *)argumentLocation atIndex:(int)idx;
+ at end
+
+ at interface Test
+ at end
+
+ at implementation Test {
+  id strong_id;
+  __weak id weak_id;
+  __unsafe_unretained id unsafe_id;
+  int arg;
+}
+- (void) test:(NSInvocation *)invok {
+  [invok getReturnValue:&strong_id]; // expected-error {{NSInvocation's getReturnValue is not safe to be used with an object with ownership other than __unsafe_unretained}}
+  [invok getReturnValue:&weak_id]; // expected-error {{NSInvocation's getReturnValue is not safe to be used with an object with ownership other than __unsafe_unretained}}
+  [invok getReturnValue:&unsafe_id];
+  [invok getReturnValue:&arg];
+
+  [invok setReturnValue:&strong_id]; // expected-error {{NSInvocation's setReturnValue is not safe to be used with an object with ownership other than __unsafe_unretained}}
+  [invok setReturnValue:&weak_id]; // expected-error {{NSInvocation's setReturnValue is not safe to be used with an object with ownership other than __unsafe_unretained}}
+  [invok setReturnValue:&unsafe_id];
+  [invok setReturnValue:&arg];
+
+  [invok getArgument:&strong_id atIndex:0]; // expected-error {{NSInvocation's getArgument is not safe to be used with an object with ownership other than __unsafe_unretained}}
+  [invok getArgument:&weak_id atIndex:0]; // expected-error {{NSInvocation's getArgument is not safe to be used with an object with ownership other than __unsafe_unretained}}
+  [invok getArgument:&unsafe_id atIndex:0];
+  [invok getArgument:&arg atIndex:0];
+
+  [invok setArgument:&strong_id atIndex:0]; // expected-error {{NSInvocation's setArgument is not safe to be used with an object with ownership other than __unsafe_unretained}}
+  [invok setArgument:&weak_id atIndex:0]; // expected-error {{NSInvocation's setArgument is not safe to be used with an object with ownership other than __unsafe_unretained}}
+  [invok setArgument:&unsafe_id atIndex:0];
+  [invok setArgument:&arg atIndex:0];
+}
+ at end





More information about the cfe-commits mailing list