]> granicus.if.org Git - clang/commitdiff
Implements property of reference types. Adding
authorFariborz Jahanian <fjahanian@apple.com>
Mon, 28 Mar 2011 23:47:18 +0000 (23:47 +0000)
committerFariborz Jahanian <fjahanian@apple.com>
Mon, 28 Mar 2011 23:47:18 +0000 (23:47 +0000)
an executable test to llvm test suite.
// rdar://9070460.

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

lib/CodeGen/CGObjC.cpp
lib/Sema/SemaExpr.cpp
lib/Sema/SemaExprObjC.cpp
lib/Sema/SemaObjCProperty.cpp
test/SemaObjCXX/references.mm

index 0118537fbf09cf3cde107971e8879e934fd1fd57..dcdd81d1f84a39a9685063f19a909bb9616ad240 100644 (file)
@@ -294,11 +294,17 @@ void CodeGenFunction::GenerateObjCGetter(ObjCImplementationDecl *IMP,
     else {
         LValue LV = EmitLValueForIvar(TypeOfSelfObject(), LoadObjCSelf(), 
                                     Ivar, 0);
-        CodeGenTypes &Types = CGM.getTypes();
-        RValue RV = EmitLoadOfLValue(LV, IVART);
-        RV = RValue::get(Builder.CreateBitCast(RV.getScalarVal(),
+        if (PD->getType()->isReferenceType()) {
+          RValue RV = RValue::get(LV.getAddress());
+          EmitReturnOfRValue(RV, PD->getType());
+        }
+        else {
+          CodeGenTypes &Types = CGM.getTypes();
+          RValue RV = EmitLoadOfLValue(LV, IVART);
+          RV = RValue::get(Builder.CreateBitCast(RV.getScalarVal(),
                                                Types.ConvertType(PD->getType())));
-        EmitReturnOfRValue(RV, PD->getType());
+          EmitReturnOfRValue(RV, PD->getType());
+        }
     }
   }
 
@@ -436,7 +442,10 @@ void CodeGenFunction::GenerateObjCSetter(ObjCImplementationDecl *IMP,
       ObjCIvarDecl *Ivar = PID->getPropertyIvarDecl();
       DeclRefExpr Base(Self, Self->getType(), VK_RValue, Loc);
       ParmVarDecl *ArgDecl = *OMD->param_begin();
-      DeclRefExpr Arg(ArgDecl, ArgDecl->getType(), VK_LValue, Loc);
+      QualType T = ArgDecl->getType();
+      if (T->isReferenceType())
+        T = cast<ReferenceType>(T)->getPointeeType();
+      DeclRefExpr Arg(ArgDecl, T, VK_LValue, Loc);
       ObjCIvarRefExpr IvarRef(Ivar, Ivar->getType(), Loc, &Base, true, true);
     
       // The property type can differ from the ivar type in some situations with
index 945d35e8ce8b109974b23182c78dcb7ca9417c5a..8b7324e9661fe9aeebad12643afb004bcfaecec0 100644 (file)
@@ -7413,6 +7413,21 @@ static bool IsReadonlyProperty(Expr *E, Sema &S) {
   return false;
 }
 
+static bool IsConstProperty(Expr *E, Sema &S) {
+  if (E->getStmtClass() == Expr::ObjCPropertyRefExprClass) {
+    const ObjCPropertyRefExpr* PropExpr = cast<ObjCPropertyRefExpr>(E);
+    if (PropExpr->isImplicitProperty()) return false;
+    
+    ObjCPropertyDecl *PDecl = PropExpr->getExplicitProperty();
+    QualType T = PDecl->getType();
+    if (T->isReferenceType())
+      T = cast<ReferenceType>(T)->getPointeeType();
+    CanQualType CT = S.Context.getCanonicalType(T);
+    return CT.isConstQualified();
+  }
+  return false;
+}
+
 static bool IsReadonlyMessage(Expr *E, Sema &S) {
   if (E->getStmtClass() != Expr::MemberExprClass) 
     return false;
@@ -7435,6 +7450,8 @@ static bool CheckForModifiableLvalue(Expr *E, SourceLocation Loc, Sema &S) {
                                                               &Loc);
   if (IsLV == Expr::MLV_Valid && IsReadonlyProperty(E, S))
     IsLV = Expr::MLV_ReadonlyProperty;
+  else if (Expr::MLV_ConstQualified && IsConstProperty(E, S))
+    IsLV = Expr::MLV_Valid;
   else if (IsLV == Expr::MLV_ClassTemporary && IsReadonlyMessage(E, S))
     IsLV = Expr::MLV_InvalidMessageExpression;
   if (IsLV == Expr::MLV_Valid)
index cf38225de0cf9bd3c5f08972d0a32f8c590d2502..19215c6cfd693ed0e64995faa5339bdccdaa9070 100644 (file)
@@ -428,6 +428,7 @@ HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT,
     if (DiagnoseUseOfDecl(PD, MemberLoc))
       return ExprError();
     QualType ResTy = PD->getType();
+    ResTy = ResTy.getNonLValueExprType(Context);
     Selector Sel = PP.getSelectorTable().getNullarySelector(Member);
     ObjCMethodDecl *Getter = IFace->lookupInstanceMethod(Sel);
     if (DiagnosePropertyAccessorMismatch(PD, Getter, MemberLoc))
index f607d658951f11f801f5e67ebabb284947fec91c..43e30275e2ff4bb03c263af35a91a4e7c728269a 100644 (file)
@@ -45,11 +45,7 @@ Decl *Sema::ActOnProperty(Scope *S, SourceLocation AtLoc,
                     !(Attributes & ObjCDeclSpec::DQ_PR_copy)));
 
   TypeSourceInfo *TSI = GetTypeForDeclarator(FD.D, S);
-  QualType T = TSI->getType();
-  if (T->isReferenceType()) {
-    Diag(AtLoc, diag::error_reference_property);
-    return 0;
-  }
+
   // Proceed with constructing the ObjCPropertDecls.
   ObjCContainerDecl *ClassDecl =
     cast<ObjCContainerDecl>(ClassCategory);
@@ -404,13 +400,16 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S,
     if (!PropertyIvar)
       PropertyIvar = PropertyId;
     QualType PropType = Context.getCanonicalType(property->getType());
+    QualType PropertyIvarType = PropType;
+    if (PropType->isReferenceType())
+      PropertyIvarType = cast<ReferenceType>(PropType)->getPointeeType();
     // Check that this is a previously declared 'ivar' in 'IDecl' interface
     ObjCInterfaceDecl *ClassDeclared;
     Ivar = IDecl->lookupInstanceVariable(PropertyIvar, ClassDeclared);
     if (!Ivar) {
       Ivar = ObjCIvarDecl::Create(Context, ClassImpDecl,
                                   PropertyLoc, PropertyLoc, PropertyIvar,
-                                  PropType, /*Dinfo=*/0,
+                                  PropertyIvarType, /*Dinfo=*/0,
                                   ObjCIvarDecl::Private,
                                   (Expr *)0, true);
       ClassImpDecl->addDecl(Ivar);
@@ -433,19 +432,19 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S,
     QualType IvarType = Context.getCanonicalType(Ivar->getType());
 
     // Check that type of property and its ivar are type compatible.
-    if (PropType != IvarType) {
+    if (PropertyIvarType != IvarType) {
       bool compat = false;
-      if (isa<ObjCObjectPointerType>(PropType) 
+      if (isa<ObjCObjectPointerType>(PropertyIvarType) 
             && isa<ObjCObjectPointerType>(IvarType))
         compat = 
           Context.canAssignObjCInterfaces(
-                                  PropType->getAs<ObjCObjectPointerType>(),
+                                  PropertyIvarType->getAs<ObjCObjectPointerType>(),
                                   IvarType->getAs<ObjCObjectPointerType>());
       else {
         SourceLocation Loc = PropertyIvarLoc;
         if (Loc.isInvalid())
           Loc = PropertyLoc;
-        compat = (CheckAssignmentConstraints(Loc, PropType, IvarType)
+        compat = (CheckAssignmentConstraints(Loc, PropertyIvarType, IvarType)
                     == Compatible);
       }
       if (!compat) {
@@ -460,7 +459,7 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S,
       // FIXME! Rules for properties are somewhat different that those
       // for assignments. Use a new routine to consolidate all cases;
       // specifically for property redeclarations as well as for ivars.
-      QualType lhsType =Context.getCanonicalType(PropType).getUnqualifiedType();
+      QualType lhsType =Context.getCanonicalType(PropertyIvarType).getUnqualifiedType();
       QualType rhsType =Context.getCanonicalType(IvarType).getUnqualifiedType();
       if (lhsType != rhsType &&
           lhsType->isArithmeticType()) {
@@ -539,7 +538,10 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S,
                                       SelfExpr, true, true);
       ObjCMethodDecl::param_iterator P = setterMethod->param_begin();
       ParmVarDecl *Param = (*P);
-      Expr *rhs = new (Context) DeclRefExpr(Param, Param->getType(),
+      QualType T = Param->getType();
+      if (T->isReferenceType())
+        T = cast<ReferenceType>(T)->getPointeeType();
+      Expr *rhs = new (Context) DeclRefExpr(Param, T,
                                             VK_LValue, SourceLocation());
       ExprResult Res = BuildBinOp(S, lhs->getLocEnd(), 
                                   BO_Assign, lhs, rhs);
index 15033f6bde8d09038f27c55195daa39468941f49..585c75f3cdf9567e2652a98d89c449538cdd5496 100644 (file)
@@ -9,7 +9,7 @@ typedef struct {
 
 @interface A
 @property (assign) T p0;
-@property (assign) T& p1; // expected-error {{property of reference type is not supported}}
+@property (assign) T& p1; 
 @end
 
 int f0(const T& t) {
@@ -21,7 +21,7 @@ int f1(A *a) {
 }
 
 int f2(A *a) {
-  return f0(a.p1);     // expected-error {{property 'p1' not found on object of type 'A *'}}
+  return f0(a.p1);     
 }
 
 // PR7740