forked from OSchip/llvm-project
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
This commit is contained in:
parent
0c41b1c9f9
commit
3fa6cedb6b
|
@ -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
|
||||
|
|
|
@ -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];
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue