[Mlir-commits] [clang] [llvm] [mlir] [Clang]Check for a valid Index in array before getting it (PR #172399)
Balaji V. Iyer.
llvmlistbot at llvm.org
Fri Dec 19 09:44:19 PST 2025
https://github.com/bviyer updated https://github.com/llvm/llvm-project/pull/172399
>From 18a648b9b1a5afb20ac964f581f80281377360e1 Mon Sep 17 00:00:00 2001
From: "Balaji V. Iyer" <bviyer at gmail.com>
Date: Mon, 15 Dec 2025 20:36:00 -0600
Subject: [PATCH 1/6] Check for a valid Index in array before getting it
Fixes https://github.com/llvm/llvm-project/issues/154713
---
clang/lib/AST/ExprConstant.cpp | 4 ++++
clang/test/AST/array-overflow-index.c | 9 +++++++++
2 files changed, 13 insertions(+)
create mode 100644 clang/test/AST/array-overflow-index.c
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 11c5e1c6e90f4..fb85119b137ab 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -9749,6 +9749,10 @@ bool LValueExprEvaluator::VisitArraySubscriptExpr(const ArraySubscriptExpr *E) {
if (Success) {
Result.setFrom(Info.Ctx, Val);
+ // If Index cannot be represented as a 64 bit integer, return unsuccessful.
+ if (!Index.tryExtValue().has_value())
+ return Error(E);
+
HandleLValueVectorElement(Info, E, Result, VT->getElementType(),
VT->getNumElements(), Index.getExtValue());
}
diff --git a/clang/test/AST/array-overflow-index.c b/clang/test/AST/array-overflow-index.c
new file mode 100644
index 0000000000000..8a43cfbb01f91
--- /dev/null
+++ b/clang/test/AST/array-overflow-index.c
@@ -0,0 +1,9 @@
+// RUN: %clang_cc1 -verify %s
+
+// ref-no-diagnostics
+// expected-no-diagnostics
+
+int __attribute__((vector_size(4))) test_vector = {1};
+int get_last_element(void) {
+ return test_vector[~0UL];
+}
>From 841213bf09f2e3779ad5d2f32af880c80a26e21a Mon Sep 17 00:00:00 2001
From: "Balaji V. Iyer" <bviyer at gmail.com>
Date: Mon, 15 Dec 2025 21:15:59 -0600
Subject: [PATCH 2/6] Added Linting
---
clang/lib/AST/ExprConstant.cpp | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index fb85119b137ab..4057183ae21c9 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -9749,7 +9749,8 @@ bool LValueExprEvaluator::VisitArraySubscriptExpr(const ArraySubscriptExpr *E) {
if (Success) {
Result.setFrom(Info.Ctx, Val);
- // If Index cannot be represented as a 64 bit integer, return unsuccessful.
+ // If Index cannot be represented as a 64 bit integer, return
+ // unsuccessful.
if (!Index.tryExtValue().has_value())
return Error(E);
>From f6ca4dabbab5ae1fdf8047a131a8d31335211568 Mon Sep 17 00:00:00 2001
From: "Balaji V. Iyer." <43187390+bviyer at users.noreply.github.com>
Date: Tue, 16 Dec 2025 13:41:06 -0600
Subject: [PATCH 3/6] Update clang/test/AST/array-overflow-index.c
Co-authored-by: Mariya Podchishchaeva <mariya.podchishchaeva at intel.com>
---
clang/test/AST/array-overflow-index.c | 1 -
1 file changed, 1 deletion(-)
diff --git a/clang/test/AST/array-overflow-index.c b/clang/test/AST/array-overflow-index.c
index 8a43cfbb01f91..99bd2b9318017 100644
--- a/clang/test/AST/array-overflow-index.c
+++ b/clang/test/AST/array-overflow-index.c
@@ -1,6 +1,5 @@
// RUN: %clang_cc1 -verify %s
-// ref-no-diagnostics
// expected-no-diagnostics
int __attribute__((vector_size(4))) test_vector = {1};
>From af050c97623b5d08d12f1e9de5ce107f88adb9fc Mon Sep 17 00:00:00 2001
From: Nishant Patel <nishant.b.patel at intel.com>
Date: Wed, 3 Dec 2025 13:38:17 -0800
Subject: [PATCH 4/6] [MLIR][Vector] Add unroll pattern for vector.create_mask
(#169119)
This PR adds unrolling for vector.create_mask op based on the
targetShape. Each unrolled vector computes its local mask size in each
dimension (d) as:
min(max(originalMaskSize[d] - offset[d], 0), unrolledMaskSize[d]).
---
.../mlir/Dialect/Vector/IR/VectorOps.td | 4 +-
.../Vector/Transforms/VectorUnroll.cpp | 96 ++++++++++++++++++-
.../Dialect/Vector/vector-unroll-options.mlir | 55 +++++++++++
.../Dialect/Vector/TestVectorTransforms.cpp | 6 ++
4 files changed, 158 insertions(+), 3 deletions(-)
diff --git a/mlir/include/mlir/Dialect/Vector/IR/VectorOps.td b/mlir/include/mlir/Dialect/Vector/IR/VectorOps.td
index 43ebcaa03a470..d8ed46c2820fe 100644
--- a/mlir/include/mlir/Dialect/Vector/IR/VectorOps.td
+++ b/mlir/include/mlir/Dialect/Vector/IR/VectorOps.td
@@ -2605,7 +2605,9 @@ def Vector_ConstantMaskOp :
}
def Vector_CreateMaskOp :
- Vector_Op<"create_mask", [Pure]>,
+ Vector_Op<"create_mask", [Pure,
+ DeclareOpInterfaceMethods<VectorUnrollOpInterface>
+ ]>,
Arguments<(ins Variadic<Index>:$operands)>,
Results<(outs VectorOfAnyRankOf<[I1]>)> {
let summary = "creates a vector mask";
diff --git a/mlir/lib/Dialect/Vector/Transforms/VectorUnroll.cpp b/mlir/lib/Dialect/Vector/Transforms/VectorUnroll.cpp
index b60f80534bfb6..462bd8c3dc4a6 100644
--- a/mlir/lib/Dialect/Vector/Transforms/VectorUnroll.cpp
+++ b/mlir/lib/Dialect/Vector/Transforms/VectorUnroll.cpp
@@ -1003,6 +1003,97 @@ struct UnrollFromElements : OpRewritePattern<vector::FromElementsOp> {
vector::UnrollVectorOptions options;
};
+/// This pattern unrolls `vector.create_mask` operations into smaller mask
+/// operations based on the target unroll shape. Each unrolled slice computes
+/// its local mask size in each dimension (d) as:
+/// min(max(originalMaskSize[d] - offset[d], 0), unrolledDimSize[d]).
+/// Example:
+/// Given a create_mask operation:
+/// %0 = vector.create_mask %c6, %c10 : vector<8x16xi1> // mask first 6x10
+/// elements
+///
+/// and a target unroll shape of <4x8>, the pattern produces:
+///
+/// %false = arith.constant dense<false> : vector<8x16xi1>
+///
+/// Slice [0,0]:
+/// mask size = min(max(6-0, 0), 4) x min(max(10-0, 0), 8) = 4x8
+/// %mask00 = vector.create_mask %c4, %c8 : vector<4x8xi1>
+/// %r0 = vector.insert_strided_slice %mask00, %false [0, 0], [1, 1]
+/// : vector<4x8xi1> into vector<8x16xi1>
+/// Slice [0,8]:
+/// mask size = min(max(6-0, 0), 4) x min(max(10-8, 0), 8) = 4x2
+/// %mask01 = vector.create_mask %c4, %c2 : vector<4x8xi1>
+/// %r1 = vector.insert_strided_slice %mask01, %r0 [0, 8], [1, 1]
+/// : vector<4x8xi1> into vector<8x16xi1>
+/// Slice [4,0]:
+/// mask size = min(max(6-4, 0), 4) x min(max(10-0, 0), 8) = 2x8
+/// %mask10 = vector.create_mask %c2, %c8 : vector<4x8xi1>
+/// %r2 = vector.insert_strided_slice %mask10, %r1 [4, 0], [1, 1]
+/// : vector<4x8xi1> into vector<8x16xi1>
+/// Slice [4,8]:
+/// mask size = min(max(6-4, 0), 4) x min(max(10-8, 0), 8) = 2x2
+/// %mask11 = vector.create_mask %c2, %c2 : vector<4x8xi1>
+/// %result = vector.insert_strided_slice %mask11, %r2 [4, 8], [1, 1]
+/// : vector<4x8xi1> into vector<8x16xi1>
+struct UnrollCreateMaskPattern : public OpRewritePattern<vector::CreateMaskOp> {
+ UnrollCreateMaskPattern(MLIRContext *context,
+ const vector::UnrollVectorOptions &options,
+ PatternBenefit benefit = 1)
+ : OpRewritePattern<vector::CreateMaskOp>(context, benefit),
+ options(options) {}
+
+ LogicalResult matchAndRewrite(vector::CreateMaskOp createMaskOp,
+ PatternRewriter &rewriter) const override {
+ auto targetShape = getTargetShape(options, createMaskOp);
+ if (!targetShape)
+ return failure();
+
+ VectorType resultType = createMaskOp.getVectorType();
+ SmallVector<int64_t> originalSize = *createMaskOp.getShapeForUnroll();
+ Location loc = createMaskOp.getLoc();
+
+ Value result = arith::ConstantOp::create(rewriter, loc, resultType,
+ rewriter.getZeroAttr(resultType));
+ VectorType targetVectorType =
+ VectorType::get(*targetShape, rewriter.getI1Type());
+ SmallVector<int64_t> strides(targetShape->size(), 1);
+
+ // In each dimension (d), each unrolled vector computes its mask size as:
+ // min(max(originalMaskOperands[d] - offset[d], 0), unrolledDimSize[d]).
+ for (SmallVector<int64_t> offsets :
+ StaticTileOffsetRange(originalSize, *targetShape)) {
+ SmallVector<Value> unrolledOperands;
+
+ for (auto [i, originalMaskOperand] :
+ llvm::enumerate(createMaskOp.getOperands())) {
+ Value offsetVal =
+ arith::ConstantIndexOp::create(rewriter, loc, offsets[i]);
+ Value adjustedMaskSize = rewriter.createOrFold<arith::SubIOp>(
+ loc, originalMaskOperand, offsetVal);
+ Value zero = arith::ConstantIndexOp::create(rewriter, loc, 0);
+ Value unrolledDimSize =
+ arith::ConstantIndexOp::create(rewriter, loc, (*targetShape)[i]);
+ Value nonNegative =
+ rewriter.createOrFold<arith::MaxSIOp>(loc, adjustedMaskSize, zero);
+ Value unrolledOperand = rewriter.createOrFold<arith::MinSIOp>(
+ loc, nonNegative, unrolledDimSize);
+ unrolledOperands.push_back(unrolledOperand);
+ }
+
+ auto unrolledMask = rewriter.createOrFold<vector::CreateMaskOp>(
+ loc, targetVectorType, unrolledOperands);
+ result = rewriter.createOrFold<vector::InsertStridedSliceOp>(
+ loc, unrolledMask, result, offsets, strides);
+ }
+ rewriter.replaceOp(createMaskOp, result);
+ return success();
+ }
+
+private:
+ vector::UnrollVectorOptions options;
+};
+
/// Checks whether extractShape is a contiguous slice of shape.
/// For extractShape to be contiguous in shape:
/// 1) All but the leading dimension of extractShape and shape must match
@@ -1202,8 +1293,9 @@ void mlir::vector::populateVectorUnrollPatterns(
UnrollReductionPattern, UnrollMultiReductionPattern,
UnrollTransposePattern, UnrollGatherPattern, UnrollLoadPattern,
UnrollStorePattern, UnrollBroadcastPattern, UnrollFromElements,
- UnrollToElements, UnrollStepPattern, UnrollShapeCastPattern>(
- patterns.getContext(), options, benefit);
+ UnrollToElements, UnrollStepPattern, UnrollShapeCastPattern,
+ UnrollCreateMaskPattern>(patterns.getContext(), options,
+ benefit);
}
void mlir::vector::populateVectorToElementsUnrollPatterns(
diff --git a/mlir/test/Dialect/Vector/vector-unroll-options.mlir b/mlir/test/Dialect/Vector/vector-unroll-options.mlir
index dec32e1c61a9b..805e66f133c59 100644
--- a/mlir/test/Dialect/Vector/vector-unroll-options.mlir
+++ b/mlir/test/Dialect/Vector/vector-unroll-options.mlir
@@ -497,6 +497,61 @@ func.func @elementwise_4D_to_2D(%v1: vector<2x2x2x2xf32>, %v2: vector<2x2x2x2xf3
// CHECK-NOT: arith.addf
// CHECK: return
+func.func @vector_create_mask(%size1: index, %size2: index) -> vector<16x16xi1> {
+ %0 = vector.create_mask %size1, %size2 : vector<16x16xi1>
+ return %0 : vector<16x16xi1>
+}
+
+// CHECK-LABEL: func @vector_create_mask
+// CHECK-SAME: (%[[ARG0:.*]]: index, %[[ARG1:.*]]: index) -> vector<16x16xi1>
+// CHECK: %[[CST:.*]] = arith.constant dense<false> : vector<16x16xi1>
+// CHECK: %[[C0:.*]] = arith.constant 0 : index
+// CHECK: %[[C8:.*]] = arith.constant 8 : index
+// CHECK: %[[MAX0:.*]] = arith.maxsi %[[ARG0]], %[[C0]] : index
+// CHECK: %[[MIN0:.*]] = arith.minsi %[[MAX0]], %[[C8]] : index
+// CHECK: %[[MAX1:.*]] = arith.maxsi %[[ARG1]], %[[C0]] : index
+// CHECK: %[[MIN1:.*]] = arith.minsi %[[MAX1]], %[[C8]] : index
+// CHECK: %[[MASK00:.*]] = vector.create_mask %[[MIN0]], %[[MIN1]] : vector<8x8xi1>
+// CHECK: %[[INS00:.*]] = vector.insert_strided_slice %[[MASK00]], %[[CST]] {offsets = [0, 0], strides = [1, 1]} : vector<8x8xi1> into vector<16x16xi1>
+// CHECK: %[[MAX0_2:.*]] = arith.maxsi %[[ARG0]], %[[C0]] : index
+// CHECK: %[[MIN0_2:.*]] = arith.minsi %[[MAX0_2]], %[[C8]] : index
+// CHECK: %[[SUB1:.*]] = arith.subi %[[ARG1]], %[[C8]] : index
+// CHECK: %[[MAX1_2:.*]] = arith.maxsi %[[SUB1]], %[[C0]] : index
+// CHECK: %[[MIN1_2:.*]] = arith.minsi %[[MAX1_2]], %[[C8]] : index
+// CHECK: %[[MASK01:.*]] = vector.create_mask %[[MIN0_2]], %[[MIN1_2]] : vector<8x8xi1>
+// CHECK: %[[INS01:.*]] = vector.insert_strided_slice %[[MASK01]], %[[INS00]] {offsets = [0, 8], strides = [1, 1]} : vector<8x8xi1> into vector<16x16xi1>
+// CHECK: %[[SUB0:.*]] = arith.subi %[[ARG0]], %[[C8]] : index
+// CHECK: %[[MAX0_3:.*]] = arith.maxsi %[[SUB0]], %[[C0]] : index
+// CHECK: %[[MIN0_3:.*]] = arith.minsi %[[MAX0_3]], %[[C8]] : index
+// CHECK: %[[MAX1_3:.*]] = arith.maxsi %[[ARG1]], %[[C0]] : index
+// CHECK: %[[MIN1_3:.*]] = arith.minsi %[[MAX1_3]], %[[C8]] : index
+// CHECK: %[[MASK10:.*]] = vector.create_mask %[[MIN0_3]], %[[MIN1_3]] : vector<8x8xi1>
+// CHECK: %[[INS10:.*]] = vector.insert_strided_slice %[[MASK10]], %[[INS01]] {offsets = [8, 0], strides = [1, 1]} : vector<8x8xi1> into vector<16x16xi1>
+// CHECK: %[[SUB0_2:.*]] = arith.subi %[[ARG0]], %[[C8]] : index
+// CHECK: %[[MAX0_4:.*]] = arith.maxsi %[[SUB0_2]], %[[C0]] : index
+// CHECK: %[[MIN0_4:.*]] = arith.minsi %[[MAX0_4]], %[[C8]] : index
+// CHECK: %[[SUB1_2:.*]] = arith.subi %[[ARG1]], %[[C8]] : index
+// CHECK: %[[MAX1_4:.*]] = arith.maxsi %[[SUB1_2]], %[[C0]] : index
+// CHECK: %[[MIN1_4:.*]] = arith.minsi %[[MAX1_4]], %[[C8]] : index
+// CHECK: %[[MASK11:.*]] = vector.create_mask %[[MIN0_4]], %[[MIN1_4]] : vector<8x8xi1>
+// CHECK: %[[INS11:.*]] = vector.insert_strided_slice %[[MASK11]], %[[INS10]] {offsets = [8, 8], strides = [1, 1]} : vector<8x8xi1> into vector<16x16xi1>
+// CHECK: return %[[INS11]] : vector<16x16xi1>
+
+func.func @vector_create_mask_constant_dim_sizes() -> vector<16x16xi1> {
+ %cst16 = arith.constant 16 : index
+ %0 = vector.create_mask %cst16, %cst16 : vector<16x16xi1>
+ return %0 : vector<16x16xi1>
+}
+
+// CHECK-LABEL: func @vector_create_mask_constant_dim_sizes() -> vector<16x16xi1> {
+// CHECK: %[[CST:.*]] = arith.constant dense<false> : vector<16x16xi1>
+// CHECK: %[[CST_0:.*]] = arith.constant dense<true> : vector<8x8xi1>
+// CHECK: %[[S0:.*]] = vector.insert_strided_slice %[[CST_0]], %[[CST]] {offsets = [0, 0], strides = [1, 1]} : vector<8x8xi1> into vector<16x16xi1>
+// CHECK: %[[S1:.*]] = vector.insert_strided_slice %[[CST_0]], %[[S0]] {offsets = [0, 8], strides = [1, 1]} : vector<8x8xi1> into vector<16x16xi1>
+// CHECK: %[[S2:.*]] = vector.insert_strided_slice %[[CST_0]], %[[S1]] {offsets = [8, 0], strides = [1, 1]} : vector<8x8xi1> into vector<16x16xi1>
+// CHECK: %[[S3:.*]] = vector.insert_strided_slice %[[CST_0]], %[[S2]] {offsets = [8, 8], strides = [1, 1]} : vector<8x8xi1> into vector<16x16xi1>
+// CHECK: return %[[S3]] : vector<16x16xi1>
+
func.func @shape_cast_1D(%v: vector<16xf32>) -> vector<2x2x4xf32> {
%0 = vector.shape_cast %v : vector<16xf32> to vector<2x2x4xf32>
diff --git a/mlir/test/lib/Dialect/Vector/TestVectorTransforms.cpp b/mlir/test/lib/Dialect/Vector/TestVectorTransforms.cpp
index e8ea0cc02d7f6..f834d0cdd42bd 100644
--- a/mlir/test/lib/Dialect/Vector/TestVectorTransforms.cpp
+++ b/mlir/test/lib/Dialect/Vector/TestVectorTransforms.cpp
@@ -178,6 +178,12 @@ struct TestVectorUnrollingPatterns
.setFilterConstraint([](Operation *op) {
return success(isa<vector::StepOp>(op));
}));
+ populateVectorUnrollPatterns(
+ patterns, UnrollVectorOptions()
+ .setNativeShape(ArrayRef<int64_t>{8, 8})
+ .setFilterConstraint([](Operation *op) {
+ return success(isa<vector::CreateMaskOp>(op));
+ }));
populateVectorUnrollPatterns(
patterns,
UnrollVectorOptions()
>From 60a2c3fce321569b5f6cb5c9a84b3a2c3d618a03 Mon Sep 17 00:00:00 2001
From: Matt Arsenault <Matthew.Arsenault at amd.com>
Date: Wed, 3 Dec 2025 16:42:19 -0500
Subject: [PATCH 5/6] DAG: Use poison for filler values on legalize error paths
(#170556)
---
llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
index 8336e1d1f4134..e739659d68561 100644
--- a/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
@@ -2130,7 +2130,7 @@ SelectionDAGLegalize::ExpandLibCall(RTLIB::Libcall LC, SDNode *Node,
if (const char *LibcallName = TLI.getLibcallName(LC))
Callee = DAG.getExternalSymbol(LibcallName, CodePtrTy);
else {
- Callee = DAG.getUNDEF(CodePtrTy);
+ Callee = DAG.getPOISON(CodePtrTy);
DAG.getContext()->emitError(Twine("no libcall available for ") +
Node->getOperationName(&DAG));
}
@@ -4992,7 +4992,7 @@ void SelectionDAGLegalize::ConvertNodeToLibcall(SDNode *Node) {
// If the exponent does not match with sizeof(int) a libcall to
// RTLIB::POWI would use the wrong type for the argument.
DAG.getContext()->emitError("POWI exponent does not match sizeof(int)");
- Results.push_back(DAG.getUNDEF(Node->getValueType(0)));
+ Results.push_back(DAG.getPOISON(Node->getValueType(0)));
break;
}
ExpandFPLibCall(Node, LC, Results);
>From a8e5a3547900b262016eefb0e81897b2fd9d2f5e Mon Sep 17 00:00:00 2001
From: "Balaji V. Iyer" <bviyer at gmail.com>
Date: Thu, 18 Dec 2025 20:08:30 -0600
Subject: [PATCH 6/6] Added changes suggested by reviewers
---
clang/docs/ReleaseNotes.rst | 2 ++
clang/lib/AST/ExprConstant.cpp | 2 +-
clang/test/AST/array-overflow-index.cpp | 10 ++++++++++
3 files changed, 13 insertions(+), 1 deletion(-)
create mode 100644 clang/test/AST/array-overflow-index.cpp
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 654a8e48cd104..46545e6f26f38 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -579,6 +579,8 @@ Bug Fixes to C++ Support
- Fix a crash when extracting unavailable member type from alias in template deduction. (#GH165560)
- Fix incorrect diagnostics for lambdas with init-captures inside braced initializers. (#GH163498)
- Fixed spurious diagnoses of certain nested lambda expressions. (#GH149121) (#GH156579)
+- Fixed a crash where the constexpr evaluation for an array index is failing when it is not
+ representable as a 64 bit number (#GH154713)
Bug Fixes to AST Handling
^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 4057183ae21c9..3856a28b2190f 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -9752,7 +9752,7 @@ bool LValueExprEvaluator::VisitArraySubscriptExpr(const ArraySubscriptExpr *E) {
// If Index cannot be represented as a 64 bit integer, return
// unsuccessful.
if (!Index.tryExtValue().has_value())
- return Error(E);
+ return false;
HandleLValueVectorElement(Info, E, Result, VT->getElementType(),
VT->getNumElements(), Index.getExtValue());
diff --git a/clang/test/AST/array-overflow-index.cpp b/clang/test/AST/array-overflow-index.cpp
new file mode 100644
index 0000000000000..197f8628d0f71
--- /dev/null
+++ b/clang/test/AST/array-overflow-index.cpp
@@ -0,0 +1,10 @@
+// RUN: %clang_cc1 --std=c++17 -fexperimental-new-constant-interpreter -verify %s
+
+
+constexpr int __attribute__((vector_size(4))) test_vector = {1};
+
+// expected-error at +1 {{constexpr function never produces a constant expression}}
+constexpr int get_last_element(void) {
+ // expected-note at +1 {{cannot refer to element 18446744073709551615 of array of 1 element in a constant expression}}
+ return test_vector[~0UL];
+}
More information about the Mlir-commits
mailing list