llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
Author: Nemi26
<details>
<summary>Changes</summary>
Both constant evaluators assumed that a matrix initializer list holds one
initializer per element, which only holds for HLSL. Outside HLSL, `m{}` is the
only initializer list a matrix accepts, and evaluating it crashed: when
constant-initializing a namespace-scope `m3 x{};` in any C++ mode, or in a
constexpr function in C++23.
This value-initializes the matrix to zero for an empty initializer list, in
ExprConstant and in the bytecode interpreter, using the matrix `APValue` added
in #<!-- -->178762. The bytecode interpreter now also value-initializes a
matrix for `m3()`, which ExprConstant already accepted.
Reading a matrix element in a constant expression is still unsupported and
diagnosed as before (#<!-- -->120167).
Fixes #<!-- -->232999
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---
Full diff: https://github.com/llvm/llvm-project/pull/233008.diff
4 Files Affected:
- (modified) clang/docs/ReleaseNotes.md (+2)
- (modified) clang/lib/AST/ByteCode/Compiler.cpp (+13-3)
- (modified) clang/lib/AST/ExprConstant.cpp (+21)
- (added) clang/test/SemaCXX/matrix-type-constexpr.cpp (+24)
``````````diff
diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md
index 7d3f0eb702553d..a90ff6ad8b6e68 100644
--- a/clang/docs/ReleaseNotes.md
+++ b/clang/docs/ReleaseNotes.md
@@ -1076,6 +1076,8 @@ features cannot lower the translation-unit ABI level;
Objective-C `@implementation` that was ended by a nested `@interface`,
`@protocol` or `@implementation` before its `@end`. (#GH209503)
- Fixed use-after-free with annotate attribute on a C++ class method with a
this-adjusting thunk.
+- Fixed a crash when the constant evaluator initialized a `matrix_type`
+ variable with an empty initializer list, such as `m{}`. (#GH232999)
### OpenACC Specific Changes
diff --git a/clang/lib/AST/ByteCode/Compiler.cpp
b/clang/lib/AST/ByteCode/Compiler.cpp
index 40b36b4e715a10..7e0acd69c43c37 100644
--- a/clang/lib/AST/ByteCode/Compiler.cpp
+++ b/clang/lib/AST/ByteCode/Compiler.cpp
@@ -2661,7 +2661,9 @@ bool Compiler<Emitter>::visitInitList(ArrayRef<const Expr
*> Inits,
if (const auto *MT = QT->getAs<ConstantMatrixType>()) {
unsigned NumElems = MT->getNumElementsFlattened();
- assert(Inits.size() == NumElems);
+ // An empty initializer list value-initializes the matrix. Outside of HLSL,
+ // this is the only initializer list a matrix accepts.
+ assert(Inits.empty() || Inits.size() == NumElems);
QualType ElemQT = MT->getElementType();
PrimType ElemT = classifyPrim(ElemQT);
@@ -2670,8 +2672,12 @@ bool Compiler<Emitter>::visitInitList(ArrayRef<const
Expr *> Inits,
// the matrix APValue convention and therefore no index remapping is
// required.
for (unsigned I = 0; I != NumElems; ++I) {
- if (!this->visit(Inits[I]))
+ if (Inits.empty()) {
+ if (!this->visitZeroInitializer(ElemT, ElemQT, E))
+ return false;
+ } else if (!this->visit(Inits[I])) {
return false;
+ }
if (!this->emitInitElem(ElemT, I, E))
return false;
}
@@ -4202,7 +4208,8 @@ bool Compiler<Emitter>::VisitCXXScalarValueInitExpr(
if (OptPrimType T = classify(Ty))
return this->visitZeroInitializer(*T, Ty, E);
- if (Ty->isAnyComplexType() || Ty->isVectorType()) {
+ if (Ty->isAnyComplexType() || Ty->isVectorType() ||
+ Ty->isConstantMatrixType()) {
if (!Initializing) {
UnsignedOrNone LocalIndex = allocateLocal(E);
if (!LocalIndex)
@@ -4216,6 +4223,9 @@ bool Compiler<Emitter>::VisitCXXScalarValueInitExpr(
if (const auto *CT = Ty->getAs<ComplexType>()) {
NumElems = 2;
ElemQT = CT->getElementType();
+ } else if (const auto *MT = Ty->getAs<ConstantMatrixType>()) {
+ NumElems = MT->getNumElementsFlattened();
+ ElemQT = MT->getElementType();
} else {
const auto *VT = Ty->castAs<VectorType>();
NumElems = VT->getNumElements();
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 6d390032e2c717..95a1f6cf824842 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -15582,6 +15582,8 @@ class MatrixExprEvaluator : public
ExprEvaluatorBase<MatrixExprEvaluator> {
return true;
}
+ bool ZeroInitialization(const Expr *E);
+
bool VisitCastExpr(const CastExpr *E);
bool VisitInitListExpr(const InitListExpr *E);
};
@@ -15593,6 +15595,20 @@ static bool EvaluateMatrix(const Expr *E, APValue
&Result, EvalInfo &Info) {
return MatrixExprEvaluator(Info, Result).Visit(E);
}
+bool MatrixExprEvaluator::ZeroInitialization(const Expr *E) {
+ const auto *MT = E->getType()->castAs<ConstantMatrixType>();
+ QualType EltTy = MT->getElementType();
+ APValue ZeroElement;
+ if (EltTy->isIntegerType())
+ ZeroElement = APValue(Info.Ctx.MakeIntValue(0, EltTy));
+ else
+ ZeroElement =
+ APValue(APFloat::getZero(Info.Ctx.getFloatTypeSemantics(EltTy)));
+
+ SmallVector<APValue, 16> Elements(MT->getNumElementsFlattened(),
ZeroElement);
+ return Success(Elements, E);
+}
+
bool MatrixExprEvaluator::VisitCastExpr(const CastExpr *E) {
const auto *MT = E->getType()->castAs<ConstantMatrixType>();
unsigned NumRows = MT->getNumRows();
@@ -15641,6 +15657,11 @@ bool MatrixExprEvaluator::VisitInitListExpr(const
InitListExpr *E) {
const auto *MT = E->getType()->castAs<ConstantMatrixType>();
QualType EltTy = MT->getElementType();
+ // An empty initializer list value-initializes the matrix. Outside of HLSL,
+ // this is the only initializer list a matrix accepts.
+ if (E->getNumInits() == 0)
+ return ZeroInitialization(E);
+
assert(E->getNumInits() == MT->getNumElementsFlattened() &&
"Expected number of elements in initializer list to match the number "
"of matrix elements");
diff --git a/clang/test/SemaCXX/matrix-type-constexpr.cpp
b/clang/test/SemaCXX/matrix-type-constexpr.cpp
new file mode 100644
index 00000000000000..d3b4a66c7b4c10
--- /dev/null
+++ b/clang/test/SemaCXX/matrix-type-constexpr.cpp
@@ -0,0 +1,24 @@
+// RUN: %clang_cc1 -fsyntax-only -fenable-matrix -std=c++11 -verify %s
+// RUN: %clang_cc1 -fsyntax-only -fenable-matrix -std=c++11 -verify %s
-fexperimental-new-constant-interpreter
+// RUN: %clang_cc1 -fsyntax-only -fenable-matrix -std=c++23 -verify %s
+// RUN: %clang_cc1 -fsyntax-only -fenable-matrix -std=c++23 -verify %s
-fexperimental-new-constant-interpreter
+// expected-no-diagnostics
+
+// GH232999: an empty initializer list value-initializes a matrix in constant
+// evaluation.
+
+typedef float fx3x3_t __attribute__((matrix_type(3, 3)));
+typedef int ix2x4_t __attribute__((matrix_type(2, 4)));
+
+fx3x3_t GlobalFloat{};
+ix2x4_t GlobalInt{};
+
+#if __cplusplus >= 202302L
+constexpr bool f() {
+ fx3x3_t M{};
+ ix2x4_t N{};
+ fx3x3_t O = fx3x3_t();
+ return true;
+}
+static_assert(f());
+#endif
``````````
</details>
https://github.com/llvm/llvm-project/pull/233008
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits