brunodf updated this revision to Diff 380885.
brunodf edited the summary of this revision.
brunodf added a reviewer: akyrtzi.
brunodf added a subscriber: akyrtzi.
brunodf added a comment.

@rnk raises the remark that TreeTransform::RebuildCXXOperatorCallExpr already 
contains code to handle ObjC pseudo objects (including checking pseudo object 
assignment) and that calling Build*Op will re-run a lot of redundant checks.

To address this, in this updated diff, I tried to generalize the code for ObjC 
pseudo object handling (which originates from @akyrtzi in commit 0f99537ecac40) 
to handle other pseudo object kinds in addition to ObjC. I think calling 
`checkPseudoObjectAssignment` and `checkPseudoObjectIncDec` is critical for the 
PR I'm trying to solve, not sure about `CheckPlaceholderExpr`, but I retained 
that from @akyrtzi his patch.

Adding @akyrtzi as reviewer.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D111639/new/

https://reviews.llvm.org/D111639

Files:
  clang/lib/Sema/TreeTransform.h
  clang/test/SemaCXX/PR51855.cpp

Index: clang/test/SemaCXX/PR51855.cpp
===================================================================
--- /dev/null
+++ clang/test/SemaCXX/PR51855.cpp
@@ -0,0 +1,71 @@
+// RUN: %clang_cc1 -S -triple %itanium_abi_triple -fms-extensions -emit-llvm %s -o - | FileCheck %s
+
+struct F {};
+
+F operator*=(F &lhs, int rhs);
+
+F operator++(F &lhs);
+
+struct S {
+  short _m;
+  S(short _m) : _m(_m) {}
+
+  void putM(short rhs) { _m = rhs; }
+  short getM() { return _m; }
+
+  __declspec(property(get = getM, put = putM)) short theData;
+};
+
+int test1a(int i) {
+  S tmp(i);
+  tmp.theData *= 2;
+  return tmp.theData;
+}
+
+// CHECK-LABEL: define {{.*}} i32 @_Z6test1ai(i32 %i)
+// CHECK: call void @_ZN1SC1Es
+// CHECK: call {{(signext )?i16}} @_ZN1S4getMEv
+// CHECK: call void @_ZN1S4putMEs
+// CHECK: call {{(signext )?i16}} @_ZN1S4getMEv
+
+template <typename T>
+int test1b(int i) {
+  T tmp(i);
+  tmp.theData *= 2;
+  return tmp.theData;
+}
+
+template int test1b<S>(int);
+
+// CHECK-LABEL: define {{.*}} i32 @_Z6test1bI1SEii(i32 %i)
+// CHECK: call void @_ZN1SC1Es
+// CHECK: call {{(signext )?i16}} @_ZN1S4getMEv
+// CHECK: call void @_ZN1S4putMEs
+// CHECK: call {{(signext )?i16}} @_ZN1S4getMEv
+
+int test2a(int i) {
+  S tmp(i);
+  ++tmp.theData;
+  return tmp.theData;
+}
+
+// CHECK-LABEL: define {{.*}} i32 @_Z6test2ai(i32 %i)
+// CHECK: call void @_ZN1SC1Es
+// CHECK: call {{(signext )?i16}} @_ZN1S4getMEv
+// CHECK: call void @_ZN1S4putMEs
+// CHECK: call {{(signext )?i16}} @_ZN1S4getMEv
+
+template <typename T>
+int test2b(int i) {
+  T tmp(i);
+  ++tmp.theData;
+  return tmp.theData;
+}
+
+template int test2b<S>(int);
+
+// CHECK-LABEL: define {{.*}} i32 @_Z6test2bI1SEii(i32 %i)
+// CHECK: call void @_ZN1SC1Es
+// CHECK: call {{(signext )?i16}} @_ZN1S4getMEv
+// CHECK: call void @_ZN1S4putMEs
+// CHECK: call {{(signext )?i16}} @_ZN1S4getMEv
Index: clang/lib/Sema/TreeTransform.h
===================================================================
--- clang/lib/Sema/TreeTransform.h
+++ clang/lib/Sema/TreeTransform.h
@@ -14569,24 +14569,6 @@
   Expr *Callee = OrigCallee->IgnoreParenCasts();
   bool isPostIncDec = Second && (Op == OO_PlusPlus || Op == OO_MinusMinus);
 
-  if (First->getObjectKind() == OK_ObjCProperty) {
-    BinaryOperatorKind Opc = BinaryOperator::getOverloadedOpcode(Op);
-    if (BinaryOperator::isAssignmentOp(Opc))
-      return SemaRef.checkPseudoObjectAssignment(/*Scope=*/nullptr, OpLoc, Opc,
-                                                 First, Second);
-    ExprResult Result = SemaRef.CheckPlaceholderExpr(First);
-    if (Result.isInvalid())
-      return ExprError();
-    First = Result.get();
-  }
-
-  if (Second && Second->getObjectKind() == OK_ObjCProperty) {
-    ExprResult Result = SemaRef.CheckPlaceholderExpr(Second);
-    if (Result.isInvalid())
-      return ExprError();
-    Second = Result.get();
-  }
-
   // Determine whether this should be a builtin operation.
   if (Op == OO_Subscript) {
     if (!First->getType()->isOverloadableType() &&
@@ -14602,8 +14584,21 @@
       // The argument is not of overloadable type, or this is an expression
       // of the form &Class::member, so try to create a built-in unary
       // operation.
+      //
+      // But handle pseudo-objects in the LHS, and increment and decrement
+      // of pseudo-object l-value (see Sema::BuildUnaryOp).
       UnaryOperatorKind Opc
         = UnaryOperator::getOverloadedOpcode(Op, isPostIncDec);
+      if (const BuiltinType *pty = First->getType()->getAsPlaceholderType()) {
+        if (pty->getKind() == BuiltinType::PseudoObject &&
+            UnaryOperator::isIncrementDecrementOp(Opc))
+          return SemaRef.checkPseudoObjectIncDec(/*Scope=*/nullptr, OpLoc, Opc,
+                                                 First);
+        ExprResult Result = SemaRef.CheckPlaceholderExpr(First);
+        if (Result.isInvalid())
+          return ExprError();
+        First = Result.get();
+      }
 
       return getSema().CreateBuiltinUnaryOp(OpLoc, Opc, First);
     }
@@ -14612,7 +14607,26 @@
         !Second->getType()->isOverloadableType()) {
       // Neither of the arguments is an overloadable type, so try to
       // create a built-in binary operation.
+      //
+      // But handle pseudo-objects in the LHS/RHS, and assignments with a
+      // pseudo-object l-value (see Sema::BuildBinOp).
       BinaryOperatorKind Opc = BinaryOperator::getOverloadedOpcode(Op);
+      if (const BuiltinType *pty = First->getType()->getAsPlaceholderType()) {
+        if (pty->getKind() == BuiltinType::PseudoObject &&
+            BinaryOperator::isAssignmentOp(Opc))
+          return SemaRef.checkPseudoObjectAssignment(/*Scope=*/nullptr, OpLoc,
+                                                     Opc, First, Second);
+        ExprResult Result = SemaRef.CheckPlaceholderExpr(First);
+        if (Result.isInvalid())
+          return ExprError();
+        First = Result.get();
+      }
+      if (Second->getType()->isPlaceholderType()) {
+        ExprResult Result = SemaRef.CheckPlaceholderExpr(Second);
+        if (Result.isInvalid())
+          return ExprError();
+        Second = Result.get();
+      }
       ExprResult Result
         = SemaRef.CreateBuiltinBinOp(OpLoc, Opc, First, Second);
       if (Result.isInvalid())
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to