]> granicus.if.org Git - clang/commitdiff
Fix a NYI in IRGen which was due to incorrect AST
authorFariborz Jahanian <fjahanian@apple.com>
Sat, 25 Sep 2010 01:08:05 +0000 (01:08 +0000)
committerFariborz Jahanian <fjahanian@apple.com>
Sat, 25 Sep 2010 01:08:05 +0000 (01:08 +0000)
for property reference expression (of c++ object type)
in the conditional expression. Fixes // rdar://8291337

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

lib/Sema/SemaExprCXX.cpp
test/CodeGenObjCXX/property-object-conditional-exp.mm [new file with mode: 0644]

index f30fcf731288dcfa750647a121950031cd398abe..e4ee90d66846fe0b76242a7f5568c37f4709ec6a 100644 (file)
@@ -2592,8 +2592,16 @@ QualType Sema::CXXCheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS,
   //   the result is of that type [...]
   bool Same = Context.hasSameType(LTy, RTy);
   if (Same && LHS->isLvalue(Context) == Expr::LV_Valid &&
-      RHS->isLvalue(Context) == Expr::LV_Valid)
-    return LTy;
+      RHS->isLvalue(Context) == Expr::LV_Valid) {
+    // In this context, property reference is really a message call and
+    // is not considered an l-value.
+    bool lhsProperty = (isa<ObjCPropertyRefExpr>(LHS) || 
+                        isa<ObjCImplicitSetterGetterRefExpr>(LHS));
+    bool rhsProperty = (isa<ObjCPropertyRefExpr>(RHS) || 
+                        isa<ObjCImplicitSetterGetterRefExpr>(RHS));
+    if (!lhsProperty && !rhsProperty)
+      return LTy;
+  }
 
   // C++0x 5.16p5
   //   Otherwise, the result is an rvalue. If the second and third operands
diff --git a/test/CodeGenObjCXX/property-object-conditional-exp.mm b/test/CodeGenObjCXX/property-object-conditional-exp.mm
new file mode 100644 (file)
index 0000000..0f44a22
--- /dev/null
@@ -0,0 +1,36 @@
+// RUN: %clang_cc1 -emit-llvm -o - %s
+
+struct CGRect {
+  char* origin;
+  unsigned size;
+};
+typedef struct CGRect CGRect;
+
+extern "C" bool CGRectIsEmpty(CGRect);
+
+@interface Foo {
+  CGRect out;
+}
+@property CGRect bounds;
+- (CGRect) out;
+@end
+
+
+@implementation Foo
+
+- (void)bar {
+    CGRect dataRect;
+    CGRect virtualBounds;
+
+  dataRect = CGRectIsEmpty(virtualBounds) ? self.bounds : virtualBounds;
+  dataRect = CGRectIsEmpty(virtualBounds) ? [self bounds] : virtualBounds;
+  dataRect = CGRectIsEmpty(virtualBounds) ? virtualBounds : self.bounds;
+
+  dataRect = CGRectIsEmpty(virtualBounds) ? self.out : virtualBounds;
+  dataRect = CGRectIsEmpty(virtualBounds) ? [self out] : virtualBounds;
+  dataRect = CGRectIsEmpty(virtualBounds) ? virtualBounds : self.out;
+}
+
+@dynamic bounds;
+- (CGRect) out { return out; }
+@end