]> granicus.if.org Git - clang/commitdiff
More detailed analysis of typecast to an objective-c pointer
authorFariborz Jahanian <fjahanian@apple.com>
Tue, 8 Dec 2009 23:09:15 +0000 (23:09 +0000)
committerFariborz Jahanian <fjahanian@apple.com>
Tue, 8 Dec 2009 23:09:15 +0000 (23:09 +0000)
in objective-c++ mode without being too lenient.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@90895 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/AST/Expr.h
lib/CodeGen/CGExprScalar.cpp
lib/Sema/SemaCXXCast.cpp
test/SemaObjCXX/cstyle-cast.mm

index 116d89df97018e8e20abb7dbb4a94e2c581ee103..48bd1e80411885b6a3dcc4c8c6891230d7f5a47e 100644 (file)
@@ -1571,7 +1571,11 @@ public:
     CK_FloatingCast,
     
     /// CK_MemberPointerToBoolean - Member pointer to boolean
-    CK_MemberPointerToBoolean
+    CK_MemberPointerToBoolean,
+
+    /// CK_AnyPointerToObjCPointerCast - Casting any pointer to objective-c 
+    /// pointer
+    CK_AnyPointerToObjCPointerCast
 
   };
 
index 0ad139af4cd46e3f170e1d2ab9e630f6b3d45b36..f19aa273d9f011977898ab4212a3e8d8da9003f5 100644 (file)
@@ -798,6 +798,7 @@ Value *ScalarExprEmitter::EmitCastExpr(CastExpr *CE) {
     //assert(0 && "Unknown cast kind!");
     break;
 
+  case CastExpr::CK_AnyPointerToObjCPointerCast:
   case CastExpr::CK_BitCast: {
     Value *Src = Visit(const_cast<Expr*>(E));
     return Builder.CreateBitCast(Src, ConvertType(DestTy));
index c11b5fdd75b841b8a96146f1942848efe56970ed..f9138902a67865455415dfe414a890bcad5b1cb4 100644 (file)
@@ -539,6 +539,11 @@ static TryCastResult TryStaticCast(Sema &Self, Expr *&SrcExpr,
           return TC_Success;
         }
       }
+      else if (CStyle && DestType->isObjCObjectPointerType()) {
+        // allow c-style cast of objective-c pointers as they are pervasive.
+        Kind = CastExpr::CK_AnyPointerToObjCPointerCast;
+        return TC_Success;
+      }
     }
   }
 
@@ -1053,8 +1058,10 @@ static TryCastResult TryReinterpretCast(Sema &Self, Expr *SrcExpr,
     return TC_Failed;
   }
   
-  bool destIsPtr = DestType->isPointerType();
-  bool srcIsPtr = SrcType->isPointerType();
+  bool destIsPtr = 
+    CStyle? DestType->isAnyPointerType() : DestType->isPointerType();
+  bool srcIsPtr = 
+    CStyle ? SrcType->isAnyPointerType() : SrcType->isPointerType();
   if (!destIsPtr && !srcIsPtr) {
     // Except for std::nullptr_t->integer and lvalue->reference, which are
     // handled above, at least one of the two arguments must be a pointer.
@@ -1106,7 +1113,11 @@ static TryCastResult TryReinterpretCast(Sema &Self, Expr *SrcExpr,
     msg = diag::err_bad_cxx_cast_const_away;
     return TC_Failed;
   }
-
+  if (CStyle && DestType->isObjCObjectPointerType()) {
+    Kind = CastExpr::CK_AnyPointerToObjCPointerCast;
+    return TC_Success;
+  }
+  
   // Not casting away constness, so the only remaining check is for compatible
   // pointer categories.
   Kind = CastExpr::CK_BitCast;
@@ -1141,7 +1152,6 @@ static TryCastResult TryReinterpretCast(Sema &Self, Expr *SrcExpr,
   // Void pointers are not specified, but supported by every compiler out there.
   // So we finish by allowing everything that remains - it's got to be two
   // object pointers.
-  Kind = CastExpr::CK_BitCast;
   return TC_Success;
 }
 
@@ -1160,10 +1170,6 @@ bool Sema::CXXCheckCStyleCast(SourceRange R, QualType CastTy, Expr *&CastExpr,
   if (CastTy->isDependentType() || CastExpr->isTypeDependent())
     return false;
 
-  // allow c-style cast of objective-c pointers as they are pervasive.
-  if (CastTy->isObjCObjectPointerType())
-    return false;
-  
   if (!CastTy->isLValueReferenceType() && !CastTy->isRecordType())
     DefaultFunctionArrayConversion(CastExpr);
 
index 97b7af3133cbef5e48791304fabbedea365602dc..4682c43e952020edd98f60349b943a3a2c2cc1fc 100644 (file)
@@ -3,7 +3,9 @@
 @protocol P @end
 @interface I @end
 
-int main() {
+struct X { X(); };
+
+void test1(X x) {
   void *cft;
   id oct = (id)cft;
 
@@ -12,9 +14,27 @@ int main() {
 
   I* iict = (I*)cft;
 
-  id<P> pid = (id<P>)cft;
+  id<P> qid = (id<P>)cft;
 
   I<P> *ip = (I<P>*)cft;
+
+  (id)x; // expected-error {{C-style cast from 'struct X' to 'id' is not allowed}}
+
+  id *pid = (id*)ccct;
+
+  id<P> *qpid = (id<P>*)ccct;
+
+  int **pii;
+
+  ccct = (Class)pii;
+
+  qpid = (id<P>*)pii;
+
+  iict = (I*)pii;
+
+  pii = (int **)ccct;
+
+  pii = (int **)qpid;
   
 }