[clang] [CIR] Relative vtable layout for virtual base offset (PR #195025)
via cfe-commits
cfe-commits at lists.llvm.org
Thu May 7 02:21:33 PDT 2026
https://github.com/xiongzile updated https://github.com/llvm/llvm-project/pull/195025
>From bc30eea7f976d182909bea07e4d7a1de7079e7ef Mon Sep 17 00:00:00 2001
From: Zile Xiong <xiongzile at bytedance.com>
Date: Thu, 30 Apr 2026 15:14:45 +0800
Subject: [PATCH 1/3] [CIR] Relative vtable layout for virtual base offset
---
clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp b/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp
index 946739d4e1702..f56f291c70772 100644
--- a/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp
@@ -2057,8 +2057,10 @@ mlir::Value CIRGenItaniumCXXABI::getVirtualBaseClassOffset(
mlir::Value vbaseOffset;
if (cgm.getLangOpts().RelativeCXXABIVTables) {
- assert(!cir::MissingFeatures::vtableRelativeLayout());
- cgm.errorNYI(loc, "getVirtualBaseClassOffset: relative layout");
+ mlir::Value offsetPtr = builder.createBitcast(vbaseOffsetPtr, builder.getPointerTo(cgm.sInt32Ty));
+ vbaseOffset = cgf.getBuilder().createLoad(
+ loc, Address(offsetPtr, cgm.sInt32Ty,
+ CharUnits::fromQuantity(4))); // vbase.offset
} else {
mlir::Value offsetPtr = builder.createBitcast(
vbaseOffsetPtr, builder.getPointerTo(cgm.ptrDiffTy));
>From c22a4d7db8f00d90c4900c85402a5f24f602a611 Mon Sep 17 00:00:00 2001
From: Zile Xiong <xiongzile99 at gmail.com>
Date: Thu, 30 Apr 2026 17:24:00 +0800
Subject: [PATCH 2/3] [CIR] add test for getVirtualBaseOffsetOffset:
RelativeCXXABIVTables
---
clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp | 3 +-
.../CodeGenCXX/vtable-relative-baseoffset.cpp | 65 +++++++++++++++++++
2 files changed, 67 insertions(+), 1 deletion(-)
create mode 100644 clang/test/CIR/CodeGenCXX/vtable-relative-baseoffset.cpp
diff --git a/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp b/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp
index f56f291c70772..b6e6bd4857c9b 100644
--- a/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp
@@ -2057,7 +2057,8 @@ mlir::Value CIRGenItaniumCXXABI::getVirtualBaseClassOffset(
mlir::Value vbaseOffset;
if (cgm.getLangOpts().RelativeCXXABIVTables) {
- mlir::Value offsetPtr = builder.createBitcast(vbaseOffsetPtr, builder.getPointerTo(cgm.sInt32Ty));
+ mlir::Value offsetPtr = builder.createBitcast(
+ vbaseOffsetPtr, builder.getPointerTo(cgm.sInt32Ty));
vbaseOffset = cgf.getBuilder().createLoad(
loc, Address(offsetPtr, cgm.sInt32Ty,
CharUnits::fromQuantity(4))); // vbase.offset
diff --git a/clang/test/CIR/CodeGenCXX/vtable-relative-baseoffset.cpp b/clang/test/CIR/CodeGenCXX/vtable-relative-baseoffset.cpp
new file mode 100644
index 0000000000000..b58cf0622781c
--- /dev/null
+++ b/clang/test/CIR/CodeGenCXX/vtable-relative-baseoffset.cpp
@@ -0,0 +1,65 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fexperimental-relative-c++-abi-vtables -fclangir -emit-cir %s -o - | FileCheck --check-prefix=CIR %s
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fexperimental-relative-c++-abi-vtables -fclangir -emit-llvm %s -o - | FileCheck --check-prefix=LLVM %s
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fexperimental-relative-c++-abi-vtables -emit-llvm %s -o - | FileCheck --check-prefix=OGCG %s
+
+// vbase-offset.cpp
+
+struct V {
+ int x;
+};
+
+struct A : virtual V {
+};
+
+struct B : A {
+};
+// CIR-LABEL: @_Z1fP1B(
+// CIR: [[P:%.*]] = cir.load align(8) {{%.*}} : !cir.ptr<!cir.ptr<!rec_B>>, !cir.ptr<!rec_B>
+// CIR-NEXT: [[VPTR_PTR:%.*]] = cir.vtable.get_vptr [[P]] : !cir.ptr<!rec_B> -> !cir.ptr<!cir.vptr>
+// CIR-NEXT: [[VTABLE:%.*]] = cir.load align(8) [[VPTR_PTR]] : !cir.ptr<!cir.vptr>, !cir.vptr
+// CIR-NEXT: [[VTABLE_BYTES:%.*]] = cir.cast bitcast [[VTABLE]] : !cir.vptr -> !cir.ptr<!u8i>
+// CIR-NEXT: [[VBASE_OFFSET_SLOT_OFFSET:%.*]] = cir.const #cir.int<-12> : !s64i
+// CIR-NEXT: [[VBASE_OFFSET_SLOT:%.*]] = cir.ptr_stride [[VTABLE_BYTES]], [[VBASE_OFFSET_SLOT_OFFSET]] : (!cir.ptr<!u8i>, !s64i) -> !cir.ptr<!u8i>
+// CIR-NEXT: [[VBASE_OFFSET_PTR:%.*]] = cir.cast bitcast [[VBASE_OFFSET_SLOT]] : !cir.ptr<!u8i> -> !cir.ptr<!s32i>
+// CIR-NEXT: [[VBASE_OFFSET:%.*]] = cir.load align(4) [[VBASE_OFFSET_PTR]] : !cir.ptr<!s32i>, !s32i
+// CIR-NEXT: [[P_BYTES:%.*]] = cir.cast bitcast [[P]] : !cir.ptr<!rec_B> -> !cir.ptr<!u8i>
+// CIR-NEXT: [[VBASE_PTR_BYTES:%.*]] = cir.ptr_stride [[P_BYTES]], [[VBASE_OFFSET]] : (!cir.ptr<!u8i>, !s32i) -> !cir.ptr<!u8i>
+// CIR-NEXT: [[VBASE_PTR_B:%.*]] = cir.cast bitcast [[VBASE_PTR_BYTES]] : !cir.ptr<!u8i> -> !cir.ptr<!rec_B>
+// CIR-NEXT: [[VBASE_PTR:%.*]] = cir.cast bitcast [[VBASE_PTR_B]] : !cir.ptr<!rec_B> -> !cir.ptr<!rec_V>
+// CIR-NEXT: [[X_PTR:%.*]] = cir.get_member [[VBASE_PTR]][0] {name = "x"} : !cir.ptr<!rec_V> -> !cir.ptr<!s32i>
+// CIR-NEXT: [[X:%.*]] = cir.load align(4) [[X_PTR]] : !cir.ptr<!s32i>, !s32i
+//
+// LLVM-LABEL: @_Z1fP1B(
+// LLVM: [[P:%.*]] = load ptr, ptr {{.*}}, align 8
+// LLVM-NEXT: [[VTABLE:%.*]] = load ptr, ptr [[P]], align 8
+// LLVM-NEXT: [[VBASE_OFFSET_PTR:%.*]] = getelementptr i8, ptr [[VTABLE]], i64 -12
+// LLVM-NEXT: [[VBASE_OFFSET_I32:%.*]] = load i32, ptr [[VBASE_OFFSET_PTR]], align 4
+// LLVM-NEXT: [[VBASE_OFFSET:%.*]] = sext i32 [[VBASE_OFFSET_I32]] to i64
+// LLVM-NEXT: [[VBASE_PTR:%.*]] = getelementptr i8, ptr [[P]], i64 [[VBASE_OFFSET]]
+// LLVM-NEXT: [[X_PTR:%.*]] = getelementptr inbounds nuw [[STRUCT_V:%.*]], ptr [[VBASE_PTR]], i32 0, i32 0
+// LLVM-NEXT: [[X:%.*]] = load i32, ptr [[X_PTR]], align 4
+// LLVM: ret i32
+//
+// OGCG-LABEL: define dso_local noundef i32 @_Z1fP1B(
+// OGCG-SAME: ptr noundef [[P:%.*]]) #[[ATTR0:[0-9]+]] {
+// OGCG-NEXT: [[ENTRY:.*]]:
+// OGCG-NEXT: [[P_ADDR:%.*]] = alloca ptr, align 8
+// OGCG-NEXT: store ptr [[P]], ptr [[P_ADDR]], align 8
+// OGCG-NEXT: [[TMP0:%.*]] = load ptr, ptr [[P_ADDR]], align 8
+// OGCG-NEXT: [[TMP1:%.*]] = icmp eq ptr [[TMP0]], null
+// OGCG-NEXT: br i1 [[TMP1]], label %[[CAST_END:.*]], label %[[CAST_NOTNULL:.*]]
+// OGCG: [[CAST_NOTNULL]]:
+// OGCG-NEXT: [[VTABLE:%.*]] = load ptr, ptr [[TMP0]], align 8
+// OGCG-NEXT: [[VBASE_OFFSET_PTR:%.*]] = getelementptr i8, ptr [[VTABLE]], i64 -12
+// OGCG-NEXT: [[VBASE_OFFSET:%.*]] = load i32, ptr [[VBASE_OFFSET_PTR]], align 4
+// OGCG-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i8, ptr [[TMP0]], i32 [[VBASE_OFFSET]]
+// OGCG-NEXT: br label %[[CAST_END]]
+// OGCG: [[CAST_END]]:
+// OGCG-NEXT: [[CAST_RESULT:%.*]] = phi ptr [ [[ADD_PTR]], %[[CAST_NOTNULL]] ], [ null, %[[ENTRY]] ]
+// OGCG-NEXT: [[X:%.*]] = getelementptr inbounds nuw [[STRUCT_V:%.*]], ptr [[CAST_RESULT]], i32 0, i32 0
+// OGCG-NEXT: [[TMP2:%.*]] = load i32, ptr [[X]], align 4
+// OGCG-NEXT: ret i32 [[TMP2]]
+//
+int f(B *p) {
+ return static_cast<V *>(p)->x;
+}
>From 27cdfe91a9d86f26ef7a28ab9396bbfc22f25d20 Mon Sep 17 00:00:00 2001
From: Zile Xiong <xiongzile99 at gmail.com>
Date: Wed, 6 May 2026 23:33:48 +0800
Subject: [PATCH 3/3] CIR: try to do full support for vtable
---
clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp | 40 ++++++----
clang/lib/CIR/CodeGen/CIRGenVTables.cpp | 76 ++++++++++++++-----
clang/lib/CIR/CodeGen/CIRGenVTables.h | 3 +
clang/lib/CIR/Dialect/IR/CIRAttrs.cpp | 12 ++-
4 files changed, 91 insertions(+), 40 deletions(-)
diff --git a/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp b/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp
index b6e6bd4857c9b..7e8d47f5e9a2e 100644
--- a/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp
@@ -26,6 +26,7 @@
#include "clang/AST/VTableBuilder.h"
#include "clang/CIR/MissingFeatures.h"
#include "llvm/Support/ErrorHandling.h"
+#include <cassert>
using namespace clang;
using namespace clang::CIRGen;
@@ -479,20 +480,27 @@ void CIRGenItaniumCXXABI::emitVTableDefinitions(CIRGenVTables &cgvt,
cir::GlobalOp vtable = getAddrOfVTable(rd, CharUnits());
if (vtable.hasInitializer())
return;
-
+ llvm::errs() << "vtable = ";
+ vtable->dump();
+ llvm::errs() << "";
ItaniumVTableContext &vtContext = cgm.getItaniumVTableContext();
const VTableLayout &vtLayout = vtContext.getVTableLayout(rd);
cir::GlobalLinkageKind linkage = cgm.getVTableLinkage(rd);
mlir::Attribute rtti =
cgm.getAddrOfRTTIDescriptor(cgm.getLoc(rd->getBeginLoc()),
cgm.getASTContext().getCanonicalTagType(rd));
-
+ llvm::errs() << "rtti = ";
+ rtti.dump();
+ llvm::errs() << "\n";
// Classic codegen uses ConstantInitBuilder here, which is a very general
// and feature-rich class to generate initializers for global values.
// For now, this is using a simpler approach to create the initializer in CIR.
cgvt.createVTableInitializer(vtable, vtLayout, rtti,
cir::isLocalLinkage(linkage));
-
+ llvm::errs() << "new vtable = ";
+ vtable->dump();
+ llvm::errs() << "\n";
+ llvm::errs() << "\n";
// Set the correct linkage.
vtable.setLinkage(linkage);
@@ -530,10 +538,11 @@ void CIRGenItaniumCXXABI::emitVTableDefinitions(CIRGenVTables &cgvt,
"emitVTableDefinitions: WholeProgramVTables");
}
- assert(!cir::MissingFeatures::vtableRelativeLayout());
- if (cgm.getLangOpts().RelativeCXXABIVTables) {
- cgm.errorNYI(rd->getSourceRange(), "vtableRelativeLayout");
- }
+ // TODO: by @Elio
+ // assert(!cir::MissingFeatures::vtableRelativeLayout());
+ // if (cgm.getLangOpts().RelativeCXXABIVTables) {
+ // cgm.errorNYI(rd->getSourceRange(), "vtableRelativeLayout");
+ // }
}
mlir::Value CIRGenItaniumCXXABI::emitVirtualDestructorCall(
@@ -1223,11 +1232,6 @@ void CIRGenItaniumRTTIBuilder::buildVTablePointer(mlir::Location loc,
const char *vTableName = vTableClassNameForType(cgm, ty);
// Check if the alias exists. If it doesn't, then get or create the global.
- if (cgm.getLangOpts().RelativeCXXABIVTables) {
- cgm.errorNYI("buildVTablePointer: isRelativeLayout");
- return;
- }
-
mlir::Type vtableGlobalTy = builder.getPointerTo(builder.getUInt8PtrTy());
llvm::Align align = cgm.getDataLayout().getABITypeAlign(vtableGlobalTy);
cir::GlobalOp vTable = cgm.createOrReplaceCXXRuntimeVariable(
@@ -1235,13 +1239,17 @@ void CIRGenItaniumRTTIBuilder::buildVTablePointer(mlir::Location loc,
CharUnits::fromQuantity(align));
// The vtable address point is 2.
+ SmallVector<mlir::Attribute, 4> offsets{
+ cgm.getBuilder().getI32IntegerAttr(2)};
+ auto indices = mlir::ArrayAttr::get(builder.getContext(), offsets);
mlir::Attribute field{};
if (cgm.getLangOpts().RelativeCXXABIVTables) {
- cgm.errorNYI("buildVTablePointer: isRelativeLayout");
+ // TODO: by @Elio.
+ // For relative vtables, this needs special handling during lowering: the
+ // GlobalViewAttr target should be emitted as target - current slot.
+ auto symbol = mlir::FlatSymbolRefAttr::get(vTable.getSymNameAttr());
+ field = cir::GlobalViewAttr::get(builder.getSInt32Ty(), symbol, indices);
} else {
- SmallVector<mlir::Attribute, 4> offsets{
- cgm.getBuilder().getI32IntegerAttr(2)};
- auto indices = mlir::ArrayAttr::get(builder.getContext(), offsets);
field = cgm.getBuilder().getGlobalViewAttr(cgm.getBuilder().getUInt8PtrTy(),
vTable, indices);
}
diff --git a/clang/lib/CIR/CodeGen/CIRGenVTables.cpp b/clang/lib/CIR/CodeGen/CIRGenVTables.cpp
index 756ce62458290..2b8e18d06fd29 100644
--- a/clang/lib/CIR/CodeGen/CIRGenVTables.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenVTables.cpp
@@ -52,9 +52,12 @@ static void setThunkProperties(CIRGenModule &cgm, const ThunkInfo &thunk,
}
mlir::Type CIRGenModule::getVTableComponentType() {
- mlir::Type ptrTy = builder.getUInt8PtrTy();
- assert(!cir::MissingFeatures::vtableRelativeLayout());
- return ptrTy;
+ mlir::Type ty = builder.getUInt8PtrTy();
+ // assert(!cir::MissingFeatures::vtableRelativeLayout());
+ if (getLangOpts().RelativeCXXABIVTables) {
+ ty = builder.getSInt32Ty();
+ }
+ return ty;
}
mlir::Type CIRGenVTables::getVTableComponentType() {
@@ -134,6 +137,40 @@ void CIRGenVTables::generateClassData(const CXXRecordDecl *rd) {
cgm.getCXXABI().emitVTableDefinitions(*this, rd);
}
+mlir::Attribute CIRGenVTables::getVTableIntegerOrNullComponent(
+ const VTableComponent &component) {
+ CIRGenBuilderTy &builder = cgm.getBuilder();
+ bool isRelative = cgm.getLangOpts().RelativeCXXABIVTables;
+
+ auto getOffsetAttr = [&](CharUnits offset) -> mlir::Attribute {
+ if (isRelative) {
+ return builder.getI32IntegerAttr(offset.getQuantity());
+ }
+ return builder.getConstPtrAttr(builder.getUInt8PtrTy(),
+ offset.getQuantity());
+ };
+
+ switch (component.getKind()) {
+ case VTableComponent::CK_UnusedFunctionPointer:
+ if (isRelative)
+ return builder.getI32IntegerAttr(0);
+
+ return builder.getConstNullPtrAttr(builder.getUInt8PtrTy());
+
+ case VTableComponent::CK_VCallOffset:
+ return getOffsetAttr(component.getVCallOffset());
+
+ case VTableComponent::CK_VBaseOffset:
+ return getOffsetAttr(component.getVBaseOffset());
+
+ case VTableComponent::CK_OffsetToTop:
+ return getOffsetAttr(component.getOffsetToTop());
+
+ default:
+ llvm_unreachable("expected integer or null vtable component");
+ }
+}
+
mlir::Attribute CIRGenVTables::getVTableComponent(
const VTableLayout &layout, unsigned componentIndex, mlir::Attribute rtti,
unsigned &nextVTableThunkIndex, unsigned vtableAddressPoint,
@@ -142,28 +179,26 @@ mlir::Attribute CIRGenVTables::getVTableComponent(
CIRGenBuilderTy builder = cgm.getBuilder();
- assert(!cir::MissingFeatures::vtableRelativeLayout());
+ // assert(!cir::MissingFeatures::vtableRelativeLayout());
switch (component.getKind()) {
case VTableComponent::CK_UnusedFunctionPointer:
- return builder.getConstNullPtrAttr(builder.getUInt8PtrTy());
-
case VTableComponent::CK_VCallOffset:
- return builder.getConstPtrAttr(builder.getUInt8PtrTy(),
- component.getVCallOffset().getQuantity());
-
case VTableComponent::CK_VBaseOffset:
- return builder.getConstPtrAttr(builder.getUInt8PtrTy(),
- component.getVBaseOffset().getQuantity());
-
case VTableComponent::CK_OffsetToTop:
- return builder.getConstPtrAttr(builder.getUInt8PtrTy(),
- component.getOffsetToTop().getQuantity());
+ return getVTableIntegerOrNullComponent(component);
case VTableComponent::CK_RTTI:
- assert((mlir::isa<cir::GlobalViewAttr>(rtti) ||
- mlir::isa<cir::ConstPtrAttr>(rtti)) &&
- "expected GlobalViewAttr or ConstPtrAttr");
+ if (cgm.getLangOpts().RelativeCXXABIVTables) {
+ if (auto gv = mlir::dyn_cast<cir::GlobalViewAttr>(rtti)) {
+ rtti = cir::GlobalViewAttr::get(builder.getSInt32Ty(), gv.getSymbol(),
+ gv.getIndices());
+ } else {
+ // For null RTTI / special cases. Adjust if ConstPtrAttr has meaningful
+ // non-zero cases in your path.
+ rtti = builder.getI32IntegerAttr(0);
+ }
+ }
return rtti;
case VTableComponent::CK_FunctionPointer:
@@ -176,7 +211,6 @@ mlir::Attribute CIRGenVTables::getVTableComponent(
assert(!cir::MissingFeatures::cudaSupport());
auto getSpecialVirtFn = [&](StringRef name) -> cir::FuncOp {
- assert(!cir::MissingFeatures::vtableRelativeLayout());
if (cgm.getLangOpts().OpenMP && cgm.getLangOpts().OpenMPIsTargetDevice &&
cgm.getTriple().isNVPTX())
@@ -217,7 +251,7 @@ mlir::Attribute CIRGenVTables::getVTableComponent(
}
return cir::GlobalViewAttr::get(
- builder.getUInt8PtrTy(),
+ getVTableComponentType(),
mlir::FlatSymbolRefAttr::get(fnPtr.getSymNameAttr()));
}
}
@@ -244,10 +278,11 @@ void CIRGenVTables::createVTableInitializer(cir::GlobalOp &vtableOp,
size_t vtableEnd = vtableStart + layout.getVTableSize(vtableIndex);
llvm::SmallVector<mlir::Attribute> components;
components.reserve(vtableEnd - vtableStart);
- for (size_t componentIndex : llvm::seq(vtableStart, vtableEnd))
+ for (size_t componentIndex : llvm::seq(vtableStart, vtableEnd)) {
components.push_back(
getVTableComponent(layout, componentIndex, rtti, nextVTableThunkIndex,
addressPoint, vtableHasLocalLinkage));
+ }
// Create a ConstArrayAttr to hold the components.
auto arr = cir::ConstArrayAttr::get(
cir::ArrayType::get(componentType, components.size()),
@@ -263,6 +298,7 @@ void CIRGenVTables::createVTableInitializer(cir::GlobalOp &vtableOp,
auto vtableAttr = cir::VTableAttr::get(record.getType(), record.getMembers());
// Add the vtable initializer to the vtable global op.
+ // CHECKME: by @Elio
cgm.setInitializer(vtableOp, vtableAttr);
}
diff --git a/clang/lib/CIR/CodeGen/CIRGenVTables.h b/clang/lib/CIR/CodeGen/CIRGenVTables.h
index 1e4da7d8f945f..6011c1479fdb7 100644
--- a/clang/lib/CIR/CodeGen/CIRGenVTables.h
+++ b/clang/lib/CIR/CodeGen/CIRGenVTables.h
@@ -56,6 +56,9 @@ class CIRGenVTables {
mlir::Attribute rtti, unsigned &nextVTableThunkIndex,
unsigned vtableAddressPoint, bool vtableHasLocalLinkage);
+ mlir::Attribute
+ getVTableIntegerOrNullComponent(const VTableComponent &component);
+
mlir::Type getVTableComponentType();
public:
diff --git a/clang/lib/CIR/Dialect/IR/CIRAttrs.cpp b/clang/lib/CIR/Dialect/IR/CIRAttrs.cpp
index 270c55dfc4541..eda8bb1328e1c 100644
--- a/clang/lib/CIR/Dialect/IR/CIRAttrs.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRAttrs.cpp
@@ -700,7 +700,7 @@ LogicalResult cir::VTableAttr::verify(
return failure();
for (const auto &element : data.getAsRange<mlir::Attribute>()) {
- const auto &constArrayAttr = mlir::dyn_cast<cir::ConstArrayAttr>(element);
+ auto constArrayAttr = mlir::dyn_cast<cir::ConstArrayAttr>(element);
if (!constArrayAttr)
return emitError() << "expected constant array subtype";
@@ -708,16 +708,20 @@ LogicalResult cir::VTableAttr::verify(
auto arrayElts = mlir::cast<ArrayAttr>(constArrayAttr.getElts());
arrayElts.walkImmediateSubElements(
[&](mlir::Attribute attr) {
- if (mlir::isa<ConstPtrAttr, GlobalViewAttr>(attr))
+ if (mlir::isa<cir::ConstPtrAttr, cir::GlobalViewAttr,
+ mlir::IntegerAttr>(attr))
return;
- eltTypeCheck = emitError()
- << "expected GlobalViewAttr or ConstPtrAttr";
+ eltTypeCheck =
+ emitError()
+ << "expected GlobalViewAttr, ConstPtrAttr, or IntegerAttr";
},
[&](mlir::Type type) {});
+
if (eltTypeCheck.failed())
return eltTypeCheck;
}
+
return success();
}
More information about the cfe-commits
mailing list