From: Fariborz Jahanian Date: Tue, 15 Dec 2009 23:59:41 +0000 (+0000) Subject: Diagnose attempting to assign to a sub-structure of an ivar X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=2514a309204341798f96912ce7a90841bea59727;p=clang Diagnose attempting to assign to a sub-structure of an ivar using objective-c property. (fixes radar 7449707) git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@91474 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h index 469598ff37..6807f2c5a2 100644 --- a/include/clang/AST/Expr.h +++ b/include/clang/AST/Expr.h @@ -156,7 +156,8 @@ public: LV_IncompleteVoidType, LV_DuplicateVectorComponents, LV_InvalidExpression, - LV_MemberFunction + LV_MemberFunction, + LV_SubObjCPropertySetting }; isLvalueResult isLvalue(ASTContext &Ctx) const; @@ -185,7 +186,8 @@ public: MLV_NotBlockQualified, MLV_ReadonlyProperty, MLV_NoSetterProperty, - MLV_MemberFunction + MLV_MemberFunction, + MLV_SubObjCPropertySetting }; isModifiableLvalueResult isModifiableLvalue(ASTContext &Ctx, SourceLocation *Loc = 0) const; diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index d2f2211de8..f80cb6a1e4 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -1704,6 +1704,8 @@ def ext_integer_complement_complex : Extension< "ISO C does not support '~' for complex conjugation of %0">; def error_nosetter_property_assignment : Error< "setter method is needed to assign to object using property" " assignment syntax">; +def error_no_subobject_property_setting : Error< + "cannot assign to a sub-structure of an ivar using property" " assignment syntax">; def ext_freestanding_complex : Extension< "complex numbers are an extension in a freestanding C99 implementation">; diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index 139e04b2ed..dcf4411d85 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -1047,8 +1047,13 @@ Expr::isLvalueResult Expr::isLvalueInternal(ASTContext &Ctx) const { // -- If E2 is a non-static data member [...]. If E1 is an // lvalue, then E1.E2 is an lvalue. - if (isa(Member)) - return m->isArrow() ? LV_Valid : m->getBase()->isLvalue(Ctx); + if (isa(Member)) { + if (m->isArrow()) + return LV_Valid; + Expr *BaseExp = m->getBase(); + return (BaseExp->getStmtClass() == ObjCPropertyRefExprClass) ? + LV_SubObjCPropertySetting : BaseExp->isLvalue(Ctx); + } // -- If it refers to a static member function [...], then // E1.E2 is an lvalue. @@ -1065,9 +1070,13 @@ Expr::isLvalueResult Expr::isLvalueInternal(ASTContext &Ctx) const { // Not an lvalue. return LV_InvalidExpression; } - + // C99 6.5.2.3p4 - return m->isArrow() ? LV_Valid : m->getBase()->isLvalue(Ctx); + if (m->isArrow()) + return LV_Valid; + Expr *BaseExp = m->getBase(); + return (BaseExp->getStmtClass() == ObjCPropertyRefExprClass) ? + LV_SubObjCPropertySetting : BaseExp->isLvalue(Ctx); } case UnaryOperatorClass: if (cast(this)->getOpcode() == UnaryOperator::Deref) @@ -1244,6 +1253,7 @@ Expr::isModifiableLvalue(ASTContext &Ctx, SourceLocation *Loc) const { } return MLV_InvalidExpression; case LV_MemberFunction: return MLV_MemberFunction; + case LV_SubObjCPropertySetting: return MLV_SubObjCPropertySetting; } // The following is illegal: diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 65c95b36aa..12c3a3a2b0 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -5573,6 +5573,9 @@ static bool CheckForModifiableLvalue(Expr *E, SourceLocation Loc, Sema &S) { case Expr::MLV_NoSetterProperty: Diag = diag::error_nosetter_property_assignment; break; + case Expr::MLV_SubObjCPropertySetting: + Diag = diag::error_no_subobject_property_setting; + break; } SourceRange Assign; diff --git a/test/SemaObjC/property-not-lvalue.m b/test/SemaObjC/property-not-lvalue.m new file mode 100644 index 0000000000..f1bda094c2 --- /dev/null +++ b/test/SemaObjC/property-not-lvalue.m @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +typedef struct NSSize { + int width; + struct { + int dim; + } inner; +} NSSize; + +@interface Foo { + NSSize _size; +} +@property NSSize size; +@end + +void foo() { + Foo *f; + f.size.width = 2.2; // expected-error {{cannot assign to a sub-structure of an ivar using property assignment syntax}} + f.size.inner.dim = 200; // expected-error {{cannot assign to a sub-structure of an ivar using property assignment syntax}} +}