ayzhao updated this revision to Diff 506754.
ayzhao added a comment.

clean up test


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D146465

Files:
  clang/lib/Sema/SemaExprCXX.cpp
  clang/lib/Sema/SemaInit.cpp
  clang/test/CodeGen/paren-list-agg-init.cpp

Index: clang/test/CodeGen/paren-list-agg-init.cpp
===================================================================
--- clang/test/CodeGen/paren-list-agg-init.cpp
+++ clang/test/CodeGen/paren-list-agg-init.cpp
@@ -69,6 +69,21 @@
   char b;
 };
 
+
+namespace gh61145 {
+  // CHECK-DAG: [[STRUCT_VEC:%.*]] = type { i8 }
+  struct Vec {
+    Vec();
+    Vec(Vec&&);
+    ~Vec();
+  };
+
+  // CHECK-DAG: [[STRUCT_S:%.*]] = type { [[STRUCT_VEC]] }
+  struct S {
+    Vec v;
+  };
+}
+
 // CHECK-DAG: [[A1:@.*a1.*]] = internal constant [[STRUCT_A]] { i8 3, double 2.000000e+00 }, align 8
 constexpr A a1(3.1, 2.0);
 // CHECK-DAG: [[A2:@.*a2.*]] = internal constant [[STRUCT_A]] { i8 99, double 0.000000e+00 }, align 8
@@ -349,3 +364,30 @@
 void foo19() {
   G g(2);
 }
+
+namespace gh61145 {
+  // a.k.a. void make<1>()
+  // CHECK: define {{.*}} void @_ZN7gh611454makeILi0EEEvv
+  // CHECK-NEXT: entry:
+  // CHECK-NEXT: [[V:%.*v.*]] = alloca [[STRUCT_VEC]], align 1
+  // CHECK-NEXT: [[AGG_TMP_ENSURED:%.*agg.tmp.ensured.*]] = alloca [[STRUCT_S]], align 1
+  // CHECK-NEXT: call void @_ZN7gh611453VecC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[V]])
+  // a.k.a. Vec::Vec()
+  // CHECK-NEXT: [[V1:%.*v1.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[AGG_TMP_ENSURED]], i32 0, i32 0
+  // a.k.a. Vec::Vec(Vec&&)
+  // CHECK-NEXT: call void @_ZN7gh611453VecC1EOS0_(ptr noundef nonnull align 1 dereferenceable(1) [[V1]], ptr noundef nonnull align 1 dereferenceable(1) [[V]])
+  // a.k.a. S::~S();
+  // CHECK-NEXT: call void @_ZN7gh611451SD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_TMP_ENSURED]]
+  // a.k.a.Vec::~Vec()
+  // CHECK-NEXT: call void @_ZN7gh611453VecD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[V]])
+  // CHECK-NEXT: ret void
+  template <int I>
+  void make() {
+    Vec v;
+    S((Vec&&) v);
+  }
+
+  void foo() {
+    make<0>();
+  }
+}
Index: clang/lib/Sema/SemaInit.cpp
===================================================================
--- clang/lib/Sema/SemaInit.cpp
+++ clang/lib/Sema/SemaInit.cpp
@@ -9180,6 +9180,8 @@
                                         /*VerifyOnly=*/false, &CurInit);
       if (CurInit.get() && ResultType)
         *ResultType = CurInit.get()->getType();
+      if (shouldBindAsTemporary(Entity))
+        CurInit = S.MaybeBindToTemporary(CurInit.get());
       break;
     }
     }
Index: clang/lib/Sema/SemaExprCXX.cpp
===================================================================
--- clang/lib/Sema/SemaExprCXX.cpp
+++ clang/lib/Sema/SemaExprCXX.cpp
@@ -1548,7 +1548,7 @@
   // conversion expression is equivalent (in definedness, and if defined in
   // meaning) to the corresponding cast expression.
   if (Exprs.size() == 1 && !ListInitialization &&
-      !isa<InitListExpr>(Exprs[0])) {
+      !isa<InitListExpr>(Exprs[0]) && !isa<CXXParenListInitExpr>(Exprs[0])) {
     Expr *Arg = Exprs[0];
     return BuildCXXFunctionalCastExpr(TInfo, Ty, LParenOrBraceLoc, Arg,
                                       RParenOrBraceLoc);
@@ -1579,10 +1579,28 @@
                           diag::err_invalid_incomplete_type_use, FullRange))
     return ExprError();
 
-  //   Otherwise, the expression is a prvalue of the specified type whose
-  //   result object is direct-initialized (11.6) with the initializer.
-  InitializationSequence InitSeq(*this, Entity, Kind, Exprs);
-  ExprResult Result = InitSeq.Perform(*this, Entity, Kind, Exprs);
+  MultiExprArg ExprsToPass;
+  if (Exprs.size() == 1 && isa<CXXParenListInitExpr>(Exprs[0])) {
+    // C++20 [expr.static.cast]p4:
+    //   An expression E can be explicitly converted to a type T...if T is an
+    //   aggregate type ([dcl.init.aggr]) having a first element x and there is
+    //   an implicit conversion sequence from E to the type of x
+    //
+    // Unlike for InitListExprs, InitializationSequence(..) doesn't take the
+    // overall CXXParenListInitExpr as the first element, so we instead pass
+    // it the elements of the CXXParenListInitExpr and have it deduce the
+    // initialization type and generate a new CXXParenListInitExpr.
+    auto *CPLIE = cast<CXXParenListInitExpr>(Exprs[0]);
+    ExprsToPass =
+        MultiExprArg(const_cast<Expr **>(CPLIE->getInitExprs().begin()),
+                     CPLIE->getInitExprs().size());
+  } else {
+    //   Otherwise, the expression is a prvalue of the specified type whose
+    //   result object is direct-initialized (11.6) with the initializer.
+    ExprsToPass = Exprs;
+  }
+  InitializationSequence InitSeq(*this, Entity, Kind, ExprsToPass);
+  ExprResult Result = InitSeq.Perform(*this, Entity, Kind, ExprsToPass);
 
   if (Result.isInvalid())
     return Result;
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to