[clang] 0c047a8 - [Sema] check PseudoObject when rebuilding CXXOperatorCallExpr in template instantiation

Jeroen Dobbelaere via cfe-commits cfe-commits at lists.llvm.org
Wed Dec 1 02:02:51 PST 2021


Author: Jeroen Dobbelaere
Date: 2021-12-01T11:02:28+01:00
New Revision: 0c047a8e13320fb8e9dabbf7a3c6a00fe81198c7

URL: https://github.com/llvm/llvm-project/commit/0c047a8e13320fb8e9dabbf7a3c6a00fe81198c7
DIFF: https://github.com/llvm/llvm-project/commit/0c047a8e13320fb8e9dabbf7a3c6a00fe81198c7.diff

LOG: [Sema] check PseudoObject when rebuilding CXXOperatorCallExpr in template instantiation

The invocation of a unary or binary operator for type-dependent expressions is represented as a CXXOperatorCallExpr. Upon template instantiation, TreeTransform::RebuildCXXOperatorCallExpr checks for the case of an overloaded operator, but not for a (non-ObjC) PseudoObject, and will directly create a UnaryOperator or BinaryOperator.

Generalizing commit 0f99537ecac40 from @akyrtzi to handle non-ObjC pseudo objects (and also handle the case of unary pseudo object inc/dec).

This fixes https://bugs.llvm.org/show_bug.cgi?id=51855

Reviewed By: rnk

Differential Revision: https://reviews.llvm.org/D111639

Added: 
    clang/test/SemaCXX/PR51855.cpp

Modified: 
    clang/lib/Sema/TreeTransform.h
    clang/test/SemaObjCXX/instantiate-property-access.mm

Removed: 
    


################################################################################
diff  --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index 7f3326c13263f..152feac4041c4 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -14630,18 +14630,28 @@ TreeTransform<Derived>::RebuildCXXOperatorCallExpr(OverloadedOperatorKind Op,
   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);
+  if (const BuiltinType *pty = First->getType()->getAsPlaceholderType()) {
+    if (Second && !isPostIncDec) {
+      BinaryOperatorKind Opc = BinaryOperator::getOverloadedOpcode(Op);
+      if (pty->getKind() == BuiltinType::PseudoObject &&
+          BinaryOperator::isAssignmentOp(Opc))
+        return SemaRef.checkPseudoObjectAssignment(/*Scope=*/nullptr, OpLoc,
+                                                   Opc, First, Second);
+    } else {
+      UnaryOperatorKind Opc =
+          UnaryOperator::getOverloadedOpcode(Op, isPostIncDec);
+      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();
   }
 
-  if (Second && Second->getObjectKind() == OK_ObjCProperty) {
+  if (Second && Second->getType()->isPlaceholderType()) {
     ExprResult Result = SemaRef.CheckPlaceholderExpr(Second);
     if (Result.isInvalid())
       return ExprError();

diff  --git a/clang/test/SemaCXX/PR51855.cpp b/clang/test/SemaCXX/PR51855.cpp
new file mode 100644
index 0000000000000..6ace3bf085aa5
--- /dev/null
+++ b/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 {{.*}} @_Z6test1ai(
+// CHECK: call {{.*}} @_ZN1SC1Es(
+// CHECK: call {{.*}} @_ZN1S4getMEv(
+// CHECK: call {{.*}} @_ZN1S4putMEs(
+// CHECK: call {{.*}} @_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 {{.*}} @_Z6test1bI1SEii(
+// CHECK: call {{.*}} @_ZN1SC1Es(
+// CHECK: call {{.*}} @_ZN1S4getMEv(
+// CHECK: call {{.*}} @_ZN1S4putMEs(
+// CHECK: call {{.*}} @_ZN1S4getMEv(
+
+int test2a(int i) {
+  S tmp(i);
+  ++tmp.theData;
+  return tmp.theData;
+}
+
+// CHECK-LABEL: define {{.*}} i32 @_Z6test2ai(
+// CHECK: call {{.*}} @_ZN1SC1Es(
+// CHECK: call {{.*}} @_ZN1S4getMEv(
+// CHECK: call {{.*}} @_ZN1S4putMEs(
+// CHECK: call {{.*}} @_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(
+// CHECK: call void @_ZN1SC1Es(
+// CHECK: call {{.*}} @_ZN1S4getMEv(
+// CHECK: call {{.*}} @_ZN1S4putMEs(
+// CHECK: call {{.*}} @_ZN1S4getMEv(

diff  --git a/clang/test/SemaObjCXX/instantiate-property-access.mm b/clang/test/SemaObjCXX/instantiate-property-access.mm
index 8d5c201a80a19..e792825facf46 100644
--- a/clang/test/SemaObjCXX/instantiate-property-access.mm
+++ b/clang/test/SemaObjCXX/instantiate-property-access.mm
@@ -1,4 +1,5 @@
 // RUN: %clang_cc1 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -fsyntax-only -DDEPENDENT -verify %s
 // expected-no-diagnostics
 
 class C {};
@@ -9,6 +10,10 @@
 
 C operator += (C c1, C c2);
 
+C operator++(C c1);
+
+bool operator!(C c1);
+
 enum TextureType { TextureType3D  };
 
 @interface Texture
@@ -16,9 +21,13 @@ @interface Texture
 @property  C c;
 @end
 
-template <typename> class Framebuffer {
+template <typename T> class Framebuffer {
 public:
-  Texture **color_attachment;  
+#ifdef DEPENDENT
+  T **color_attachment;
+#else
+  Texture **color_attachment;
+#endif
   Framebuffer();
 };
 
@@ -28,8 +37,15 @@ @interface Texture
   (void)(color_attachment[0].c == color_attachment[0].c);
   (void)(color_attachment[0].c == 1);
   (void)(1 == color_attachment[0].c);
+  (void)(!color_attachment[0].textureType);
+  ++color_attachment[0].textureType;
+  (void)(!color_attachment[0].c);
 }
 
 void foo() {
+#ifdef DEPENDENT
+  Framebuffer<Texture>();
+#else
   Framebuffer<int>();
+#endif
 }


        


More information about the cfe-commits mailing list