[clang] [Clang] Support MSPropertyRefExpr as placement arg to new-expression (PR #75883)

via cfe-commits cfe-commits at lists.llvm.org
Mon Dec 18 17:56:43 PST 2023


https://github.com/Sirraide created https://github.com/llvm/llvm-project/pull/75883

It seems we were forgetting to call `checkArgsForPlaceholders` on the placement arguments of new-expressions in Sema. I don't think that was intended—at least doing so doesn't seem to break anything—so this pr adds that.

This also fixes #65053

>From f51b382fd33d4cf3f75bdaa172bb8697a6cadc9e Mon Sep 17 00:00:00 2001
From: Sirraide <aeternalmail at gmail.com>
Date: Tue, 19 Dec 2023 02:48:25 +0100
Subject: [PATCH] [Clang] Support MSPropertyRefExpr as placement arg to
 new-expression

---
 clang/include/clang/Sema/Sema.h           |  4 ++
 clang/lib/Sema/SemaExpr.cpp               | 12 ++----
 clang/lib/Sema/SemaExprCXX.cpp            |  3 ++
 clang/test/CodeGenCXX/ms-property-new.cpp | 52 +++++++++++++++++++++++
 clang/test/SemaCXX/ms-property-new.cpp    | 44 +++++++++++++++++++
 5 files changed, 107 insertions(+), 8 deletions(-)
 create mode 100644 clang/test/CodeGenCXX/ms-property-new.cpp
 create mode 100644 clang/test/SemaCXX/ms-property-new.cpp

diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index a4f8fc1845b1ce..90be0a648f0124 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -2108,6 +2108,10 @@ class Sema final {
 
   bool CheckFunctionReturnType(QualType T, SourceLocation Loc);
 
+  /// Check an argument list for placeholders that we won't try to
+  /// handle later.
+  bool CheckArgsForPlaceholders(MultiExprArg args);
+
   /// Build a function type.
   ///
   /// This routine checks the function type according to C++ rules and
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index c7185d56cc9973..2442c1e104055b 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -5058,8 +5058,6 @@ static QualType getDependentArraySubscriptType(Expr *LHS, Expr *RHS,
   return Result->isDependentType() ? Result : Ctx.DependentTy;
 }
 
-static bool checkArgsForPlaceholders(Sema &S, MultiExprArg args);
-
 ExprResult Sema::ActOnArraySubscriptExpr(Scope *S, Expr *base,
                                          SourceLocation lbLoc,
                                          MultiExprArg ArgExprs,
@@ -5163,7 +5161,7 @@ ExprResult Sema::ActOnArraySubscriptExpr(Scope *S, Expr *base,
       return ExprError();
     ArgExprs[0] = result.get();
   } else {
-    if (checkArgsForPlaceholders(*this, ArgExprs))
+    if (CheckArgsForPlaceholders(ArgExprs))
       return ExprError();
   }
 
@@ -6912,15 +6910,13 @@ static bool isPlaceholderToRemoveAsArg(QualType type) {
   llvm_unreachable("bad builtin type kind");
 }
 
-/// Check an argument list for placeholders that we won't try to
-/// handle later.
-static bool checkArgsForPlaceholders(Sema &S, MultiExprArg args) {
+bool Sema::CheckArgsForPlaceholders(MultiExprArg args) {
   // Apply this processing to all the arguments at once instead of
   // dying at the first failure.
   bool hasInvalid = false;
   for (size_t i = 0, e = args.size(); i != e; i++) {
     if (isPlaceholderToRemoveAsArg(args[i]->getType())) {
-      ExprResult result = S.CheckPlaceholderExpr(args[i]);
+      ExprResult result = CheckPlaceholderExpr(args[i]);
       if (result.isInvalid()) hasInvalid = true;
       else args[i] = result.get();
     }
@@ -7194,7 +7190,7 @@ ExprResult Sema::BuildCallExpr(Scope *Scope, Expr *Fn, SourceLocation LParenLoc,
   if (Result.isInvalid()) return ExprError();
   Fn = Result.get();
 
-  if (checkArgsForPlaceholders(*this, ArgExprs))
+  if (CheckArgsForPlaceholders(ArgExprs))
     return ExprError();
 
   if (getLangOpts().CPlusPlus) {
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index 081b568762ae22..49f0921ce324fc 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -2286,6 +2286,9 @@ ExprResult Sema::BuildCXXNew(SourceRange Range, bool UseGlobal,
   bool PassAlignment = getLangOpts().AlignedAllocation &&
                        Alignment > NewAlignment;
 
+  if (CheckArgsForPlaceholders(PlacementArgs))
+    return ExprError();
+
   AllocationFunctionScope Scope = UseGlobal ? AFS_Global : AFS_Both;
   if (!AllocType->isDependentType() &&
       !Expr::hasAnyTypeDependentArguments(PlacementArgs) &&
diff --git a/clang/test/CodeGenCXX/ms-property-new.cpp b/clang/test/CodeGenCXX/ms-property-new.cpp
new file mode 100644
index 00000000000000..e21ec3d6702f62
--- /dev/null
+++ b/clang/test/CodeGenCXX/ms-property-new.cpp
@@ -0,0 +1,52 @@
+// RUN: %clang_cc1 -emit-llvm -triple=x86_64-pc-win32 -fms-compatibility %s -o - | FileCheck %s
+// RUN: %clang_cc1 -triple=x86_64-pc-win32 -fms-compatibility -emit-pch -o %t %s
+// RUN: %clang_cc1 -emit-llvm -triple=x86_64-pc-win32 -fms-compatibility -include-pch %t -verify %s -o - | FileCheck %s
+// expected-no-diagnostics
+
+#ifndef HEADER
+#define HEADER
+
+struct S {
+  int GetX() { return 42; }
+  __declspec(property(get=GetX)) int x;
+
+  int GetY(int i, int j) { return i+j; }
+  __declspec(property(get=GetY)) int y[];
+
+  void* operator new(__SIZE_TYPE__, int);
+};
+
+template <typename T>
+struct TS {
+  T GetT() { return T(); }
+  __declspec(property(get=GetT)) T t;
+
+  T GetR(T i, T j) { return i+j; }
+  __declspec(property(get=GetR)) T r[];
+};
+
+// CHECK-LABEL: main
+int main(int argc, char **argv) {
+  S *s;
+  TS<double> *ts;
+
+  // CHECK: [[X:%.+]] = call noundef i32 @"?GetX at S@@QEAAHXZ"(ptr {{[^,]*}} %{{.+}})
+  // CHECK-NEXT: call noundef ptr @"??2S@@SAPEAX_KH at Z"(i64 noundef 1, i32 noundef [[X]])
+  new (s->x) S;
+
+  // CHECK: [[Y:%.+]] = call noundef i32 @"?GetY at S@@QEAAHHH at Z"(ptr {{[^,]*}} %{{.+}}, i32 noundef 1, i32 noundef 2)
+  // CHECK-NEXT: call noundef ptr @"??2S@@SAPEAX_KH at Z"(i64 noundef 1, i32 noundef [[Y]])
+  new ((s->y)[1][2]) S;
+
+  // CHECK: [[T:%.+]] = call noundef double @"?GetT@?$TS at N@@QEAANXZ"(ptr {{[^,]*}} %{{.+}})
+  // CHECK-NEXT: [[TI:%.+]] = fptosi double [[T]] to i32
+  // CHECK-NEXT: call noundef ptr @"??2S@@SAPEAX_KH at Z"(i64 noundef 1, i32 noundef [[TI]])
+  new (ts->t) S;
+
+  // CHECK: [[R:%.+]] = call noundef double @"?GetR@?$TS at N@@QEAANNN at Z"(ptr {{[^,]*}} %{{.+}}, double {{[^,]*}}, double {{[^,]*}})
+  // CHECK-NEXT: [[RI:%.+]] = fptosi double [[R]] to i32
+  // CHECK-NEXT: call noundef ptr @"??2S@@SAPEAX_KH at Z"(i64 noundef 1, i32 noundef [[RI]])
+  new ((ts->r)[1][2]) S;
+}
+
+#endif
\ No newline at end of file
diff --git a/clang/test/SemaCXX/ms-property-new.cpp b/clang/test/SemaCXX/ms-property-new.cpp
new file mode 100644
index 00000000000000..d17b0fdeb76715
--- /dev/null
+++ b/clang/test/SemaCXX/ms-property-new.cpp
@@ -0,0 +1,44 @@
+// RUN: %clang_cc1 -ast-print -verify -triple=x86_64-pc-win32 -fms-compatibility %s -o - | FileCheck %s
+// RUN: %clang_cc1 -triple=x86_64-pc-win32 -fms-compatibility -emit-pch -o %t %s
+// RUN: %clang_cc1 -triple=x86_64-pc-win32 -fms-compatibility -include-pch %t -verify %s -ast-print -o - | FileCheck %s
+// expected-no-diagnostics
+
+#ifndef HEADER
+#define HEADER
+
+struct S {
+  int GetX() { return 42; }
+  __declspec(property(get=GetX)) int x;
+
+  int GetY(int i, int j) { return i+j; }
+  __declspec(property(get=GetY)) int y[];
+
+  void* operator new(__SIZE_TYPE__, int);
+};
+
+template <typename T>
+struct TS {
+  T GetT() { return T(); }
+  __declspec(property(get=GetT)) T t;
+
+  T GetR(T i, T j) { return i+j; }
+  __declspec(property(get=GetR)) T r[];
+};
+
+int main(int argc, char **argv) {
+  // CHECK: S *s;
+  // CHECK-NEXT: new (s->x) S;
+  // CHECK-NEXT: new ((s->y)[1][2]) S;
+  S *s;
+  new (s->x) S;
+  new ((s->y)[1][2]) S;
+
+  // CHECK-NEXT: TS<double> *ts;
+  // CHECK-NEXT: new (ts->t) S;
+  // CHECK-NEXT: new ((ts->r)[1][2]) S;
+  TS<double> *ts;
+  new (ts->t) S;
+  new ((ts->r)[1][2]) S;
+}
+
+#endif
\ No newline at end of file



More information about the cfe-commits mailing list