From: John McCall Date: Tue, 8 Nov 2011 22:54:08 +0000 (+0000) Subject: Bind function "r-values" as l-values when emitting them as X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=a5493f885095bd63d525a7035ad1c224de3ae5f2;p=clang Bind function "r-values" as l-values when emitting them as opaque values. Silly C type system. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@144144 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp index d7e3168a3a..4d14d18e59 100644 --- a/lib/CodeGen/CGExpr.cpp +++ b/lib/CodeGen/CGExpr.cpp @@ -2137,7 +2137,7 @@ LValue CodeGenFunction::EmitNullInitializationLValue( } LValue CodeGenFunction::EmitOpaqueValueLValue(const OpaqueValueExpr *e) { - assert(e->isGLValue() || e->getType()->isRecordType()); + assert(OpaqueValueMappingData::shouldBindAsLValue(e)); return getOpaqueLValueMapping(e); } diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index 3a0be7a562..383eb587ca 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -970,7 +970,14 @@ public: OpaqueValueMappingData() : OpaqueValue(0) {} static bool shouldBindAsLValue(const Expr *expr) { - return expr->isGLValue() || expr->getType()->isRecordType(); + // gl-values should be bound as l-values for obvious reasons. + // Records should be bound as l-values because IR generation + // always keeps them in memory. Expressions of function type + // act exactly like l-values but are formally required to be + // r-values in C. + return expr->isGLValue() || + expr->getType()->isRecordType() || + expr->getType()->isFunctionType(); } static OpaqueValueMappingData bind(CodeGenFunction &CGF, diff --git a/test/CodeGenObjC/property.m b/test/CodeGenObjC/property.m index 3cc9200f33..30f68e5b27 100644 --- a/test/CodeGenObjC/property.m +++ b/test/CodeGenObjC/property.m @@ -112,3 +112,14 @@ void test4(Test4 *t) { @implementation Test5 @synthesize x = _x; @end + +// rdar://problem/10410531 +@interface Test6 +@property void (*prop)(void); +@end + +void test6_func(void); +void test6(Test6 *a) { + a.prop = test6_func; +} +