r194930 - ObjectiveC ARC. Validate toll free bridge casting

Fariborz Jahanian fjahanian at apple.com
Sat Nov 16 11:16:32 PST 2013


Author: fjahanian
Date: Sat Nov 16 13:16:32 2013
New Revision: 194930

URL: http://llvm.org/viewvc/llvm-project?rev=194930&view=rev
Log:
ObjectiveC ARC. Validate toll free bridge casting
of ObjectiveC objects to CF types when CF type
has the objc_bridge attribute.

Modified:
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/lib/Sema/SemaExprObjC.cpp
    cfe/trunk/test/SemaObjC/objcbridge-attribute.m

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=194930&r1=194929&r2=194930&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Sat Nov 16 13:16:32 2013
@@ -2447,10 +2447,14 @@ def err_objc_bridge_not_cftype : Error<
   "'objc_bridge' attribute must be applied to definition of CF types">;
 def err_objc_bridge_not_pointert_to_struct : Error<
   "'objc_bridge' attribute must be applied to a pointer to struct type">;
-def err_objc_bridged_not_interface : Error<
+def err_objc_cf_bridged_not_interface : Error<
   "CF object of type %0 is bridged to '%1', which is not an Objective-C class">;
+def err_objc_ns_bridged_invalid_cfobject : Error<
+  "ObjectiveC object of type %0 is bridged to %1, which is not valid CF object">;
 def warn_objc_invalid_bridge : Warning<
   "%0 bridges to %1, not %2">, InGroup<ObjCBridge>;
+def warn_objc_invalid_bridge_to_cf : Warning<
+  "%0 cannot bridge to %1">, InGroup<ObjCBridge>;
 
 // Function Parameter Semantic Analysis.
 def err_param_with_void_type : Error<"argument may not have 'void' type">;

Modified: cfe/trunk/lib/Sema/SemaExprObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprObjC.cpp?rev=194930&r1=194929&r2=194930&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExprObjC.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprObjC.cpp Sat Nov 16 13:16:32 2013
@@ -3165,7 +3165,7 @@ diagnoseObjCARCConversion(Sema &S, Sourc
     << castRange << castExpr->getSourceRange();
 }
 
-static bool CheckObjCBridgeCast(Sema &S, QualType castType, Expr *castExpr) {
+static bool CheckObjCBridgeNSCast(Sema &S, QualType castType, Expr *castExpr) {
   QualType T = castExpr->getType();
   while (const TypedefType *TD = dyn_cast<TypedefType>(T.getTypePtr())) {
     TypedefNameDecl *TDNDecl = TD->getDecl();
@@ -3193,7 +3193,7 @@ static bool CheckObjCBridgeCast(Sema &S,
             }
           }
         }
-        S.Diag(castExpr->getLocStart(), diag::err_objc_bridged_not_interface)
+        S.Diag(castExpr->getLocStart(), diag::err_objc_cf_bridged_not_interface)
         << castExpr->getType() << Parm->getName();
         S.Diag(TDNDecl->getLocStart(), diag::note_declared_at);
         if (Target)
@@ -3206,6 +3206,49 @@ static bool CheckObjCBridgeCast(Sema &S,
   return false;
 }
 
+// (CFErrorRef)ns
+static bool CheckObjCBridgeCFCast(Sema &S, QualType castType, Expr *castExpr) {
+  QualType T = castType;
+  while (const TypedefType *TD = dyn_cast<TypedefType>(T.getTypePtr())) {
+    TypedefNameDecl *TDNDecl = TD->getDecl();
+    if (TDNDecl->hasAttr<ObjCBridgeAttr>()) {
+      ObjCBridgeAttr *ObjCBAttr = TDNDecl->getAttr<ObjCBridgeAttr>();
+      IdentifierInfo *Parm = ObjCBAttr->getBridgedType();
+      NamedDecl *Target = 0;
+      if (Parm && S.getLangOpts().ObjC1) {
+        // Check for an existing type with this name.
+        LookupResult R(S, DeclarationName(Parm), SourceLocation(),
+                       Sema::LookupOrdinaryName);
+        if (S.LookupName(R, S.TUScope)) {
+          Target = R.getFoundDecl();
+          if (Target && isa<ObjCInterfaceDecl>(Target)) {
+            ObjCInterfaceDecl *CastClass = cast<ObjCInterfaceDecl>(Target);
+            if (const ObjCObjectPointerType *InterfacePointerType =
+                  castExpr->getType()->getAsObjCInterfacePointerType()) {
+              ObjCInterfaceDecl *ExprClass
+                = InterfacePointerType->getObjectType()->getInterface();
+              if ((CastClass == ExprClass) || (ExprClass && CastClass->isSuperClassOf(ExprClass)))
+                return true;
+              S.Diag(castExpr->getLocStart(), diag::warn_objc_invalid_bridge_to_cf)
+                << ExprClass->getName() << TDNDecl->getName();
+              S.Diag(TDNDecl->getLocStart(), diag::note_declared_at);
+              return true;
+            }
+          }
+        }
+        S.Diag(castExpr->getLocStart(), diag::err_objc_ns_bridged_invalid_cfobject)
+        << castExpr->getType() << castType;
+        S.Diag(TDNDecl->getLocStart(), diag::note_declared_at);
+        if (Target)
+          S.Diag(Target->getLocStart(), diag::note_declared_at);
+      }
+      return true;
+    }
+    T = TDNDecl->getUnderlyingType();
+  }
+  return false;
+}
+
 Sema::ARCConversionResult
 Sema::CheckObjCARCConversion(SourceRange castRange, QualType castType,
                              Expr *&castExpr, CheckedConversionKind CCK,
@@ -3266,7 +3309,12 @@ Sema::CheckObjCARCConversion(SourceRange
   
   if (castACTC == ACTC_retainable && exprACTC == ACTC_coreFoundation &&
       (CCK == CCK_CStyleCast || CCK == CCK_FunctionalCast))
-    if (CheckObjCBridgeCast(*this, castType, castExpr))
+    if (CheckObjCBridgeNSCast(*this, castType, castExpr))
+      return ACR_okay;
+    
+  if (castACTC == ACTC_coreFoundation && exprACTC == ACTC_retainable &&
+      (CCK == CCK_CStyleCast || CCK == CCK_FunctionalCast))
+    if (CheckObjCBridgeCFCast(*this, castType, castExpr))
       return ACR_okay;
     
 

Modified: cfe/trunk/test/SemaObjC/objcbridge-attribute.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/objcbridge-attribute.m?rev=194930&r1=194929&r2=194930&view=diff
==============================================================================
--- cfe/trunk/test/SemaObjC/objcbridge-attribute.m (original)
+++ cfe/trunk/test/SemaObjC/objcbridge-attribute.m Sat Nov 16 13:16:32 2013
@@ -1,7 +1,7 @@
 // RUN: %clang_cc1 -fsyntax-only -fobjc-arc -verify -Wno-objc-root-class %s
 // rdar://15454846
 
-typedef struct __CFErrorRef * __attribute__ ((objc_bridge(NSError))) CFErrorRef;
+typedef struct __CFErrorRef * __attribute__ ((objc_bridge(NSError))) CFErrorRef; // expected-note {{declared here}}
 
 typedef struct __CFMyColor  * __attribute__((objc_bridge(12))) CFMyColorRef; // expected-error {{parameter of 'objc_bridge' attribute must be a single name of an Objective-C class}}
 
@@ -48,8 +48,10 @@ typedef CFErrorRef1 CFErrorRef2;
 
 @class NSString;
 
-void Test2(CFErrorRef2 cf) {
+void Test2(CFErrorRef2 cf, NSError *ns, NSString *str) {
   (void)(NSString *)cf; // expected-warning {{CFErrorRef bridges to NSError, not NSString}}
   (void)(NSError *)cf; // okay
   (void)(MyError*)cf; // okay,
+  (void)(CFErrorRef)ns; // okay
+  (void)(CFErrorRef)str;  // expected-warning {{NSString cannot bridge to CFErrorRef}}
 }





More information about the cfe-commits mailing list