[clang] 3fa6ced - Fix MaterializeTemporaryExpr's type when its an incomplete array.

Erich Keane via cfe-commits cfe-commits at lists.llvm.org
Wed Jan 6 07:24:45 PST 2021


Author: Erich Keane
Date: 2021-01-06T07:17:12-08:00
New Revision: 3fa6cedb6be809092f8a8b27e63bd4f6dc526a08

URL: https://github.com/llvm/llvm-project/commit/3fa6cedb6be809092f8a8b27e63bd4f6dc526a08
DIFF: https://github.com/llvm/llvm-project/commit/3fa6cedb6be809092f8a8b27e63bd4f6dc526a08.diff

LOG: Fix MaterializeTemporaryExpr's type when its an incomplete array.

Like the VarDecl that gets its type updated based on an init-list, this
patch corrects the MaterializeTemporaryExpr's type to make sure it isn't
creating an incomplete type, which leads to a handful of CodeGen crashes
(see PR 47636).

Based on @rsmith 's comments on D88236

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

Added: 
    clang/test/AST/pr47636.cpp

Modified: 
    clang/lib/Sema/SemaInit.cpp
    clang/test/CodeGenCXX/pr47636.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp
index b5f31bf403d4..38f6a5975ea3 100644
--- a/clang/lib/Sema/SemaInit.cpp
+++ b/clang/lib/Sema/SemaInit.cpp
@@ -8200,9 +8200,21 @@ ExprResult InitializationSequence::Perform(Sema &S,
       if (S.CheckExceptionSpecCompatibility(CurInit.get(), DestType))
         return ExprError();
 
+      QualType MTETy = Step->Type;
+
+      // When this is an incomplete array type (such as when this is
+      // initializing an array of unknown bounds from an init list), use THAT
+      // type instead so that we propogate the array bounds.
+      if (MTETy->isIncompleteArrayType() &&
+          !CurInit.get()->getType()->isIncompleteArrayType() &&
+          S.Context.hasSameType(
+              MTETy->getPointeeOrArrayElementType(),
+              CurInit.get()->getType()->getPointeeOrArrayElementType()))
+        MTETy = CurInit.get()->getType();
+
       // Materialize the temporary into memory.
       MaterializeTemporaryExpr *MTE = S.CreateMaterializeTemporaryExpr(
-          Step->Type, CurInit.get(), Entity.getType()->isLValueReferenceType());
+          MTETy, CurInit.get(), Entity.getType()->isLValueReferenceType());
       CurInit = MTE;
 
       // If we're extending this temporary to automatic storage duration -- we

diff  --git a/clang/test/AST/pr47636.cpp b/clang/test/AST/pr47636.cpp
new file mode 100644
index 000000000000..29d2a0a06e79
--- /dev/null
+++ b/clang/test/AST/pr47636.cpp
@@ -0,0 +1,26 @@
+// RUN: %clang_cc1 -fsyntax-only %s -ast-dump | FileCheck %s
+
+int(&&intu_rvref)[] {1,2,3,4};
+// CHECK: VarDecl 0x[[GLOB_ADDR:[0-9a-f]+]] {{.*}} intu_rvref 'int (&&)[4]' listinit
+// CHECK-NEXT: ExprWithCleanups {{.*}} 'int [4]' xvalue
+// CHECK-NEXT: MaterializeTemporaryExpr {{.*}} 'int [4]' xvalue extended by Var 0x[[GLOB_ADDR]] 'intu_rvref' 'int (&&)[4]'
+// CHECK-NEXT: InitListExpr {{.*}} 'int [4]'
+
+// CHECK: FunctionDecl {{.*}} static_const
+void static_const() {
+  static const int(&&intu_rvref)[] {1,2,3,4};
+  // CHECK: VarDecl 0x[[STATIC_ADDR:[0-9a-f]+]] {{.*}} intu_rvref 'const int (&&)[4]' static listinit
+  // CHECK-NEXT: ExprWithCleanups {{.*}} 'const int [4]' xvalue
+  // CHECK-NEXT: MaterializeTemporaryExpr {{.*}} 'const int [4]' xvalue extended by Var 0x[[STATIC_ADDR]] 'intu_rvref' 'const int (&&)[4]'
+  // CHECK-NEXT: InitListExpr {{.*}} 'const int [4]'
+}
+
+// CHECK: FunctionDecl {{.*}} const_expr
+constexpr int const_expr() {
+  int(&&intu_rvref)[]{1, 2, 3, 4};
+  // CHECK: VarDecl 0x[[CE_ADDR:[0-9a-f]+]] {{.*}} intu_rvref 'int (&&)[4]' listinit
+  // CHECK-NEXT: ExprWithCleanups {{.*}} 'int [4]' xvalue
+  // CHECK-NEXT: MaterializeTemporaryExpr {{.*}} 'int [4]' xvalue extended by Var 0x[[CE_ADDR]] 'intu_rvref' 'int (&&)[4]'
+  // CHECK-NEXT: InitListExpr {{.*}} 'int [4]'
+  return intu_rvref[0];
+}

diff  --git a/clang/test/CodeGenCXX/pr47636.cpp b/clang/test/CodeGenCXX/pr47636.cpp
index 64fb44114bd2..b6b31d623761 100644
--- a/clang/test/CodeGenCXX/pr47636.cpp
+++ b/clang/test/CodeGenCXX/pr47636.cpp
@@ -8,3 +8,15 @@ void foo() {
   // CHECK: @_ZZ3foovE10intu_rvref = internal constant [4 x i32]* @_ZGRZ3foovE10intu_rvref_
   // CHECK: @_ZGRZ3foovE10intu_rvref_ = internal constant [4 x i32] [i32 1, i32 2, i32 3, i32 4]
 }
+
+// Example given on review, ensure this doesn't crash as well.
+constexpr int f() {
+  // CHECK: i32 @_Z1fv()
+  int(&&intu_rvref)[]{1, 2, 3, 4};
+  // CHECK: %{{.*}} = alloca [4 x i32]*
+  return intu_rvref[2];
+}
+
+void use_f() {
+  int i = f();
+}


        


More information about the cfe-commits mailing list