Skip to content

Conversation

andykaylor
Copy link
Contributor

This adds verification for the initializer, if present, of any global passed to the cir.vtable.address_point op.

This adds verification for the initializer, if present, of any global
passed to the `cir.vtable.address_point` op.
@llvmbot llvmbot added clang Clang issues not falling into any other category ClangIR Anything related to the ClangIR project labels Aug 22, 2025
@llvmbot
Copy link
Member

llvmbot commented Aug 22, 2025

@llvm/pr-subscribers-clang

Author: Andy Kaylor (andykaylor)

Changes

This adds verification for the initializer, if present, of any global passed to the cir.vtable.address_point op.


Full diff: https://github.com/llvm/llvm-project/pull/155031.diff

3 Files Affected:

  • (modified) clang/include/clang/CIR/MissingFeatures.h (-1)
  • (modified) clang/lib/CIR/Dialect/IR/CIRDialect.cpp (+4-2)
  • (modified) clang/test/CIR/IR/invalid-vtable.cir (+11)
diff --git a/clang/include/clang/CIR/MissingFeatures.h b/clang/include/clang/CIR/MissingFeatures.h
index e2326b1031765..d7a2e49ec162a 100644
--- a/clang/include/clang/CIR/MissingFeatures.h
+++ b/clang/include/clang/CIR/MissingFeatures.h
@@ -273,7 +273,6 @@ struct MissingFeatures {
   static bool thunks() { return false; }
   static bool tryEmitAsConstant() { return false; }
   static bool typeChecks() { return false; }
-  static bool vtableInitializer() { return false; }
   static bool weakRefReference() { return false; }
   static bool writebacks() { return false; }
   static bool appleKext() { return false; }
diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
index b5d4be8da64ab..05a6a7f5eb144 100644
--- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
@@ -1460,14 +1460,16 @@ cir::VTableAddrPointOp::verifySymbolUses(SymbolTableCollection &symbolTable) {
 
   // Verify that the result type underlying pointer type matches the type of
   // the referenced cir.global or cir.func op.
-  auto op = symbolTable.lookupNearestSymbolFrom<GlobalOp>(*this, getNameAttr());
+  auto op = symbolTable.lookupNearestSymbolFrom<cir::GlobalOp>(*this, getNameAttr());
   if (!op)
     return emitOpError("'")
            << name << "' does not reference a valid cir.global";
   std::optional<mlir::Attribute> init = op.getInitialValue();
   if (!init)
     return success();
-  assert(!cir::MissingFeatures::vtableInitializer());
+  if (!isa<cir::VTableAttr>(*init))
+    return emitOpError("Expected #cir.vtable in initializer for global '")
+           << name << "'";
   return success();
 }
 
diff --git a/clang/test/CIR/IR/invalid-vtable.cir b/clang/test/CIR/IR/invalid-vtable.cir
index 60aa9b29e2677..41ddd4c2419be 100644
--- a/clang/test/CIR/IR/invalid-vtable.cir
+++ b/clang/test/CIR/IR/invalid-vtable.cir
@@ -10,6 +10,17 @@ cir.func @reference_unknown_vtable() {
 
 // -----
 
+!u8i = !cir.int<u, 8>
+!u32i = !cir.int<u, 32>
+cir.global linkonce_odr @_ZTT1D = #cir.const_array<[#cir.global_view<@_ZTV1D, [0 : i32, 3 : i32]> : !cir.ptr<!u8i>, #cir.global_view<@_ZTC1D0_1B, [0 : i32, 3 : i32]> : !cir.ptr<!u8i>]> : !cir.array<!cir.ptr<!u8i> x 2>
+cir.func @reference_unknown_vtable() {
+  // expected-error @below {{Expected #cir.vtable in initializer for global '_ZTT1D'}}
+  %0 = cir.vtable.address_point(@_ZTT1D, address_point = <index = 0, offset = 2>) : !cir.vptr
+  cir.return
+}
+
+// -----
+
 !rec_S = !cir.record<struct "S" {!cir.vptr}>
 !u8i = !cir.int<u, 8>
 !rec_anon_struct = !cir.record<struct {!cir.array<!cir.ptr<!u8i> x 4>}>

@llvmbot
Copy link
Member

llvmbot commented Aug 22, 2025

@llvm/pr-subscribers-clangir

Author: Andy Kaylor (andykaylor)

Changes

This adds verification for the initializer, if present, of any global passed to the cir.vtable.address_point op.


Full diff: https://github.com/llvm/llvm-project/pull/155031.diff

3 Files Affected:

  • (modified) clang/include/clang/CIR/MissingFeatures.h (-1)
  • (modified) clang/lib/CIR/Dialect/IR/CIRDialect.cpp (+4-2)
  • (modified) clang/test/CIR/IR/invalid-vtable.cir (+11)
diff --git a/clang/include/clang/CIR/MissingFeatures.h b/clang/include/clang/CIR/MissingFeatures.h
index e2326b1031765..d7a2e49ec162a 100644
--- a/clang/include/clang/CIR/MissingFeatures.h
+++ b/clang/include/clang/CIR/MissingFeatures.h
@@ -273,7 +273,6 @@ struct MissingFeatures {
   static bool thunks() { return false; }
   static bool tryEmitAsConstant() { return false; }
   static bool typeChecks() { return false; }
-  static bool vtableInitializer() { return false; }
   static bool weakRefReference() { return false; }
   static bool writebacks() { return false; }
   static bool appleKext() { return false; }
diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
index b5d4be8da64ab..05a6a7f5eb144 100644
--- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
@@ -1460,14 +1460,16 @@ cir::VTableAddrPointOp::verifySymbolUses(SymbolTableCollection &symbolTable) {
 
   // Verify that the result type underlying pointer type matches the type of
   // the referenced cir.global or cir.func op.
-  auto op = symbolTable.lookupNearestSymbolFrom<GlobalOp>(*this, getNameAttr());
+  auto op = symbolTable.lookupNearestSymbolFrom<cir::GlobalOp>(*this, getNameAttr());
   if (!op)
     return emitOpError("'")
            << name << "' does not reference a valid cir.global";
   std::optional<mlir::Attribute> init = op.getInitialValue();
   if (!init)
     return success();
-  assert(!cir::MissingFeatures::vtableInitializer());
+  if (!isa<cir::VTableAttr>(*init))
+    return emitOpError("Expected #cir.vtable in initializer for global '")
+           << name << "'";
   return success();
 }
 
diff --git a/clang/test/CIR/IR/invalid-vtable.cir b/clang/test/CIR/IR/invalid-vtable.cir
index 60aa9b29e2677..41ddd4c2419be 100644
--- a/clang/test/CIR/IR/invalid-vtable.cir
+++ b/clang/test/CIR/IR/invalid-vtable.cir
@@ -10,6 +10,17 @@ cir.func @reference_unknown_vtable() {
 
 // -----
 
+!u8i = !cir.int<u, 8>
+!u32i = !cir.int<u, 32>
+cir.global linkonce_odr @_ZTT1D = #cir.const_array<[#cir.global_view<@_ZTV1D, [0 : i32, 3 : i32]> : !cir.ptr<!u8i>, #cir.global_view<@_ZTC1D0_1B, [0 : i32, 3 : i32]> : !cir.ptr<!u8i>]> : !cir.array<!cir.ptr<!u8i> x 2>
+cir.func @reference_unknown_vtable() {
+  // expected-error @below {{Expected #cir.vtable in initializer for global '_ZTT1D'}}
+  %0 = cir.vtable.address_point(@_ZTT1D, address_point = <index = 0, offset = 2>) : !cir.vptr
+  cir.return
+}
+
+// -----
+
 !rec_S = !cir.record<struct "S" {!cir.vptr}>
 !u8i = !cir.int<u, 8>
 !rec_anon_struct = !cir.record<struct {!cir.array<!cir.ptr<!u8i> x 4>}>

Copy link

github-actions bot commented Aug 22, 2025

✅ With the latest revision this PR passed the C/C++ code formatter.

@andykaylor andykaylor merged commit 085d0b0 into llvm:main Aug 22, 2025
9 checks passed
@andykaylor andykaylor deleted the cir-vtable-verify branch August 22, 2025 22:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang Clang issues not falling into any other category ClangIR Anything related to the ClangIR project
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants