[clang][initlist] handle incomplete array type in Constant Expr Calculation (#155080)
fix: #151716
In #65918, support of incomplete array type is added in
TryReferenceListInitialization. It causes the crash in Constant Expr
Calculation since it only considers the case where it is
ConstantArrayType.
This patch wants to add support for incomplete array type also.
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index b510fa5..e13de5e 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -338,6 +338,8 @@
- Fix the parsing of variadic member functions when the ellipis immediately follows a default argument.(#GH153445)
- Fixed a bug that caused ``this`` captured by value in a lambda with a dependent explicit object parameter to not be
instantiated properly. (#GH154054)
+- Fixed a crash when implicit conversions from initialize list to arrays of
+ unknown bound during constant evaluation. (#GH151716)
Bug Fixes to AST Handling
^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 66362d4..f0592b0 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -4030,10 +4030,12 @@
LastField = nullptr;
if (ObjType->isArrayType()) {
// Next subobject is an array element.
- const ConstantArrayType *CAT = Info.Ctx.getAsConstantArrayType(ObjType);
- assert(CAT && "vla in literal type?");
+ const ArrayType *AT = Info.Ctx.getAsArrayType(ObjType);
+ assert((isa<ConstantArrayType>(AT) || isa<IncompleteArrayType>(AT)) &&
+ "vla in literal type?");
uint64_t Index = Sub.Entries[I].getAsArrayIndex();
- if (CAT->getSize().ule(Index)) {
+ if (const auto *CAT = dyn_cast<ConstantArrayType>(AT);
+ CAT && CAT->getSize().ule(Index)) {
// Note, it should not be possible to form a pointer with a valid
// designator which points more than one past the end of the array.
if (Info.getLangOpts().CPlusPlus11)
@@ -4044,12 +4046,13 @@
return handler.failed();
}
- ObjType = CAT->getElementType();
+ ObjType = AT->getElementType();
if (O->getArrayInitializedElts() > Index)
O = &O->getArrayInitializedElt(Index);
else if (!isRead(handler.AccessKind)) {
- if (!CheckArraySize(Info, CAT, E->getExprLoc()))
+ if (const auto *CAT = dyn_cast<ConstantArrayType>(AT);
+ CAT && !CheckArraySize(Info, CAT, E->getExprLoc()))
return handler.failed();
expandArray(*O, Index);
diff --git a/clang/test/CodeGenCXX/cxx20-p0388-unbound-ary.cpp b/clang/test/CodeGenCXX/cxx20-p0388-unbound-ary.cpp
index a29f4d7..007b47c4 100644
--- a/clang/test/CodeGenCXX/cxx20-p0388-unbound-ary.cpp
+++ b/clang/test/CodeGenCXX/cxx20-p0388-unbound-ary.cpp
@@ -32,4 +32,19 @@
f({a});
}
+constexpr int gh151716() {
+ int(&&g)[]{0,1,2};
+ return g[2];
+}
+// CHECK-LABEL: @_ZN3One10gh151716_fEv
+// CHECK-NEXT: entry:
+// CHECK-NEXT: %v = alloca i32, align 4
+// CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr nonnull %v)
+// CHECK-NEXT: store volatile i32 2, ptr %v, align 4
+// CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr nonnull %v)
+// CHECK-NEXT: ret void
+void gh151716_f() {
+ volatile const int v = gh151716();
+}
+
} // namespace One