aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/AST/Expr.h3
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.td2
-rw-r--r--lib/AST/ExprClassification.cpp6
-rw-r--r--lib/Sema/SemaExpr.cpp21
-rw-r--r--test/SemaObjC/assign-rvalue-message.m24
5 files changed, 54 insertions, 2 deletions
diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h
index 35264b820d..a6c3d49a2f 100644
--- a/include/clang/AST/Expr.h
+++ b/include/clang/AST/Expr.h
@@ -173,6 +173,7 @@ public:
LV_IncompleteVoidType,
LV_DuplicateVectorComponents,
LV_InvalidExpression,
+ LV_InvalidMessageExpression,
LV_MemberFunction,
LV_SubObjCPropertySetting,
LV_ClassTemporary
@@ -204,6 +205,7 @@ public:
MLV_NoSetterProperty,
MLV_MemberFunction,
MLV_SubObjCPropertySetting,
+ MLV_InvalidMessageExpression,
MLV_ClassTemporary
};
isModifiableLvalueResult isModifiableLvalue(ASTContext &Ctx,
@@ -223,6 +225,7 @@ public:
CL_MemberFunction, // An expression referring to a member function
CL_SubObjCPropertySetting,
CL_ClassTemporary, // A prvalue of class type
+ CL_ObjCMessageRValue, // ObjC message is an rvalue
CL_PRValue // A prvalue for any other reason, of any other type
};
/// \brief The results of modification testing.
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index cee572e7a2..8ab9ff1e0b 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -2697,6 +2697,8 @@ def ext_gnu_ptr_func_arith : Extension<
InGroup<PointerArith>;
def error_readonly_property_assignment : Error<
"assigning to property with 'readonly' attribute not allowed">;
+def error_readonly_message_assignment : Error<
+ "assigning to 'readonly' return result of an objective-c message not allowed">;
def ext_integer_increment_complex : Extension<
"ISO C does not support '++'/'--' on complex integer type %0">;
def ext_integer_complement_complex : Extension<
diff --git a/lib/AST/ExprClassification.cpp b/lib/AST/ExprClassification.cpp
index 376792223a..f90d59f505 100644
--- a/lib/AST/ExprClassification.cpp
+++ b/lib/AST/ExprClassification.cpp
@@ -75,6 +75,7 @@ Cl Expr::ClassifyImpl(ASTContext &Ctx, SourceLocation *Loc) const {
case Cl::CL_MemberFunction:
case Cl::CL_SubObjCPropertySetting:
case Cl::CL_ClassTemporary:
+ case Cl::CL_ObjCMessageRValue:
case Cl::CL_PRValue: assert(getValueKind() == VK_RValue); break;
}
@@ -293,7 +294,8 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) {
case Expr::ObjCMessageExprClass:
if (const ObjCMethodDecl *Method =
cast<ObjCMessageExpr>(E)->getMethodDecl()) {
- return ClassifyUnnamed(Ctx, Method->getResultType());
+ Cl::Kinds kind = ClassifyUnnamed(Ctx, Method->getResultType());
+ return (kind == Cl::CL_PRValue) ? Cl::CL_ObjCMessageRValue : kind;
}
return Cl::CL_PRValue;
@@ -551,6 +553,7 @@ Expr::LValueClassification Expr::ClassifyLValue(ASTContext &Ctx) const {
case Cl::CL_MemberFunction: return LV_MemberFunction;
case Cl::CL_SubObjCPropertySetting: return LV_SubObjCPropertySetting;
case Cl::CL_ClassTemporary: return LV_ClassTemporary;
+ case Cl::CL_ObjCMessageRValue: return LV_InvalidMessageExpression;
case Cl::CL_PRValue: return LV_InvalidExpression;
}
llvm_unreachable("Unhandled kind");
@@ -569,6 +572,7 @@ Expr::isModifiableLvalue(ASTContext &Ctx, SourceLocation *Loc) const {
case Cl::CL_MemberFunction: return MLV_MemberFunction;
case Cl::CL_SubObjCPropertySetting: return MLV_SubObjCPropertySetting;
case Cl::CL_ClassTemporary: return MLV_ClassTemporary;
+ case Cl::CL_ObjCMessageRValue: return MLV_InvalidMessageExpression;
case Cl::CL_PRValue:
return VC.getModifiable() == Cl::CM_LValueCast ?
MLV_LValueCast : MLV_InvalidExpression;
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index dbddc38451..dd81b38932 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -7378,6 +7378,20 @@ static bool IsReadonlyProperty(Expr *E, Sema &S) {
return false;
}
+static bool IsReadonlyMessage(Expr *E, Sema &S) {
+ if (E->getStmtClass() != Expr::MemberExprClass)
+ return false;
+ const MemberExpr *ME = cast<MemberExpr>(E);
+ NamedDecl *Member = ME->getMemberDecl();
+ if (isa<FieldDecl>(Member)) {
+ Expr *Base = ME->getBase()->IgnoreParenImpCasts();
+ if (Base->getStmtClass() != Expr::ObjCMessageExprClass)
+ return false;
+ return cast<ObjCMessageExpr>(Base)->getMethodDecl() != 0;
+ }
+ return false;
+}
+
/// CheckForModifiableLvalue - Verify that E is a modifiable lvalue. If not,
/// emit an error and return true. If so, return false.
static bool CheckForModifiableLvalue(Expr *E, SourceLocation Loc, Sema &S) {
@@ -7386,6 +7400,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 (IsLV == Expr::MLV_ClassTemporary && IsReadonlyMessage(E, S))
+ IsLV = Expr::MLV_InvalidMessageExpression;
if (IsLV == Expr::MLV_Valid)
return false;
@@ -7428,6 +7444,9 @@ static bool CheckForModifiableLvalue(Expr *E, SourceLocation Loc, Sema &S) {
case Expr::MLV_NoSetterProperty:
Diag = diag::error_nosetter_property_assignment;
break;
+ case Expr::MLV_InvalidMessageExpression:
+ Diag = diag::error_readonly_message_assignment;
+ break;
case Expr::MLV_SubObjCPropertySetting:
Diag = diag::error_no_subobject_property_setting;
break;
@@ -7812,7 +7831,7 @@ static QualType CheckAddressOfOperand(Sema &S, Expr *OrigOp,
ValueDecl *dcl = getPrimaryDecl(op);
Expr::LValueClassification lval = op->ClassifyLValue(S.Context);
- if (lval == Expr::LV_ClassTemporary) {
+ if (lval == Expr::LV_ClassTemporary) {
bool sfinae = S.isSFINAEContext();
S.Diag(OpLoc, sfinae ? diag::err_typecheck_addrof_class_temporary
: diag::ext_typecheck_addrof_class_temporary)
diff --git a/test/SemaObjC/assign-rvalue-message.m b/test/SemaObjC/assign-rvalue-message.m
new file mode 100644
index 0000000000..7e05c89afa
--- /dev/null
+++ b/test/SemaObjC/assign-rvalue-message.m
@@ -0,0 +1,24 @@
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fsyntax-only -verify -fobjc-nonfragile-abi %s
+// RUN: %clang_cc1 -x objective-c++ -triple x86_64-apple-darwin10 -fsyntax-only -verify -fobjc-nonfragile-abi %s
+// rdar://9005189
+
+@interface Foo
+@end
+
+struct Bar {
+ int x;
+};
+
+@implementation Foo {
+ struct Bar bar;
+}
+
+- (const struct Bar)bar {
+ return bar;
+}
+
+- (void)baz {
+ bar.x = 0;
+ [self bar].x = 10; // expected-error {{assigning to 'readonly' return result of an objective-c message not allowed}}
+}
+@end