https://github.com/bcardosolopes updated 
https://github.com/llvm/llvm-project/pull/227520

>From d67d4804f3b98f14732dc268bdacf94d855abd3e Mon Sep 17 00:00:00 2001
From: Bruno Cardoso Lopes <[email protected]>
Date: Tue, 29 Sep 2026 16:45:07 -0700
Subject: [PATCH 1/2] [CIR] Emit inbounds and inrange for vtable address points
 in initializers

Classic codegen emits `inbounds inrange(...)` for vtable address points in
global initializers (VTT entries and the vptr of a constant-initialized
object). CIR never emitted any flags for #cir.global_view. It only got
inbounds and nuw when LLVM's constant folder inferred them, which stopped
for a while with c68a4ca2a920
(https://github.com/llvm/llvm-project/pull/226904) until #227651 restored
the folding. It never got inrange.

Emit the flags in CIR instead of relying on the folder:

- Add an `address_point` flag to #cir.global_view, spelled
  `#cir.global_view<@vtable, [vtable index, slot], address_point>`.
- Set it where CIRGen builds VTT entries and constant vptrs, and keep it
  when CIRGen and CXXABILowering rebuild the attribute.
- When lowering to LLVM, make an address point `inbounds`, with an
  `inrange` covering the one vtable in the group that it points into. The
  bounds come from the vtable global's type, so they also work when the
  vtable is only declared.

VTT and vptr initializers now match classic codegen, except that the folder
also adds `nuw` (valid for these non-negative offsets). Classic codegen
does not fold these constants, so it does not add it.
---
 .../include/clang/CIR/Dialect/IR/CIRAttrs.td  | 20 +++++++----
 clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp  |  6 ++--
 clang/lib/CIR/CodeGen/CIRGenModule.cpp        |  8 +++--
 clang/lib/CIR/CodeGen/CIRGenVTables.cpp       |  6 ++--
 clang/lib/CIR/Dialect/IR/CIRAttrs.cpp         | 18 ++++++++++
 .../CIR/Dialect/Transforms/CXXABILowering.cpp |  5 +--
 .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 27 ++++++++++++--
 clang/test/CIR/CodeGen/global-ptr-init.cpp    | 17 +++++++--
 clang/test/CIR/CodeGen/vtt.cpp                | 28 +++++++--------
 clang/test/CIR/CodeGenCXX/base-layout.cpp     |  4 +--
 clang/test/CIR/CodeGenCXX/vtable-linkage.cpp  |  4 +--
 .../test/CIR/IR/global-view-address-point.cir | 35 +++++++++++++++++++
 12 files changed, 140 insertions(+), 38 deletions(-)
 create mode 100644 clang/test/CIR/IR/global-view-address-point.cir

diff --git a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td 
b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
index 358412b75fc05..64b8016971c76 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
@@ -1033,28 +1033,35 @@ def CIR_GlobalViewAttr : 
CIR_ValueLikeAttr<"GlobalView", "global_view"> {
       int b;
     };
     ```
+    `address_point` marks a vtable address point: `symbol` is a vtable and
+    `indices` are the vtable within the group and the address point within
+    it. As in classic codegen, it lowers to an `inbounds` GEP whose `inrange`
+    spans that one vtable.
+
     VTT for B in CIR:
     ```
     cir.global linkonce_odr @_ZTT1B = #cir.const_array<[
-              #cir.global_view<@_ZTV1B, [0 : i32, 3 : i32]> : !cir.ptr<!u8i>]>
-                   : !cir.array<!cir.ptr<!u8i> x 1>
+              #cir.global_view<@_ZTV1B, [0 : i32, 3 : i32], address_point>
+                   : !cir.ptr<!u8i>]> : !cir.array<!cir.ptr<!u8i> x 1>
     ```
     VTT for B in LLVM IR:
     ```
     @_ZTT1B = linkonce_odr global [1 x ptr] [ptr getelementptr inbounds
-              ({ [3 x ptr] }, ptr @_ZTV1B, i32 0, i32 0, i32 3)], align 8
+              inrange(-24, 0) (i8, ptr @_ZTV1B, i64 24)], align 8
     ```
   }];
 
   let parameters = (ins AttributeSelfTypeParameter<"">:$type,
                         "mlir::FlatSymbolRefAttr":$symbol,
-                        OptionalParameter<"mlir::ArrayAttr">:$indices);
+                        OptionalParameter<"mlir::ArrayAttr">:$indices,
+                        DefaultValuedParameter<"bool", 
"false">:$address_point);
 
   let builders = [
     AttrBuilderWithInferredContext<(ins "mlir::Type":$type,
                                         "mlir::FlatSymbolRefAttr":$symbol,
-                                        CArg<"mlir::ArrayAttr", 
"{}">:$indices), [{
-      return $_get(type.getContext(), type, symbol, indices);
+                                        CArg<"mlir::ArrayAttr", "{}">:$indices,
+                                        CArg<"bool", "false">:$addressPoint), 
[{
+      return $_get(type.getContext(), type, symbol, indices, addressPoint);
     }]>
   ];
 
@@ -1063,6 +1070,7 @@ def CIR_GlobalViewAttr : CIR_ValueLikeAttr<"GlobalView", 
"global_view"> {
     `<`
       $symbol
       (`,` $indices^)?
+      `` custom<GlobalViewAddressPoint>($address_point)
     `>`
   }];
 }
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp 
b/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp
index 46aabba5b567a..ba2feb8bc6ff2 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp
@@ -333,9 +333,9 @@ mlir::Attribute buildRecordHelper(ConstantEmitter &emitter,
       mlir::ArrayAttr indices = builder.getArrayAttr(
           {builder.getI32IntegerAttr(apOp.getAddressPoint().getIndex()),
            builder.getI32IntegerAttr(apOp.getAddressPoint().getOffset())});
-      elements[0] =
-          cir::GlobalViewAttr::get(cir::VPtrType::get(builder.getContext()),
-                                   apOp.getNameAttr(), indices);
+      elements[0] = cir::GlobalViewAttr::get(
+          cir::VPtrType::get(builder.getContext()), apOp.getNameAttr(), 
indices,
+          /*addressPoint=*/true);
     }
 
     for (auto [idx, base] : llvm::enumerate(cxxrd->bases())) {
diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.cpp 
b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
index 06914ea698d61..fe2201ac44940 100644
--- a/clang/lib/CIR/CodeGen/CIRGenModule.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
@@ -1123,8 +1123,12 @@ static mlir::Attribute createNewGlobalView(CIRGenModule 
&cgm,
   else if (isa<cir::ArrayType>(oldTy))
     newPtrTy = cast<cir::PointerType>(attr.getType());
 
-  if (newPtrTy)
-    return bld.getGlobalViewAttr(newPtrTy, newGlob, newInds);
+  if (newPtrTy) {
+    cir::GlobalViewAttr view =
+        bld.getGlobalViewAttr(newPtrTy, newGlob, newInds);
+    return cir::GlobalViewAttr::get(view.getType(), view.getSymbol(),
+                                    view.getIndices(), attr.getAddressPoint());
+  }
 
   // This may be unreachable in practice, but keep it as errorNYI while CIR
   // is still under development.
diff --git a/clang/lib/CIR/CodeGen/CIRGenVTables.cpp 
b/clang/lib/CIR/CodeGen/CIRGenVTables.cpp
index 123246f3b3d3f..4c9ee965bebec 100644
--- a/clang/lib/CIR/CodeGen/CIRGenVTables.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenVTables.cpp
@@ -499,8 +499,10 @@ void CIRGenVTables::emitVTTDefinition(cir::GlobalOp vttOp,
     };
 
     auto indicesAttr = mlir::ArrayAttr::get(mlirContext, indices);
-    cir::GlobalViewAttr init = cgm.getBuilder().getGlobalViewAttr(
-        cgm.getBuilder().getUInt8PtrTy(), vtable, indicesAttr);
+    auto init = cir::GlobalViewAttr::get(
+        cgm.getBuilder().getUInt8PtrTy(),
+        mlir::FlatSymbolRefAttr::get(vtable.getSymNameAttr()), indicesAttr,
+        /*addressPoint=*/true);
 
     vttComponents.push_back(init);
   }
diff --git a/clang/lib/CIR/Dialect/IR/CIRAttrs.cpp 
b/clang/lib/CIR/Dialect/IR/CIRAttrs.cpp
index 2649ed1449739..388de73108bee 100644
--- a/clang/lib/CIR/Dialect/IR/CIRAttrs.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRAttrs.cpp
@@ -57,6 +57,11 @@ parseDataMemberPath(mlir::AsmParser &parser,
 static void printDataMemberPath(mlir::AsmPrinter &p,
                                 mlir::DenseI32ArrayAttr memberPath);
 
+static mlir::ParseResult parseGlobalViewAddressPoint(mlir::AsmParser &parser,
+                                                     bool &addressPoint);
+
+static void printGlobalViewAddressPoint(mlir::AsmPrinter &p, bool 
addressPoint);
+
 #define GET_ATTRDEF_CLASSES
 #include "clang/CIR/Dialect/IR/CIROpsAttributes.cpp.inc"
 
@@ -353,6 +358,19 @@ static void printDataMemberPath(AsmPrinter &p,
     p.printStrippedAttrOrType(memberPath);
 }
 
+static ParseResult parseGlobalViewAddressPoint(AsmParser &parser,
+                                               bool &addressPoint) {
+  addressPoint = parser.parseOptionalComma().succeeded();
+  if (addressPoint)
+    return parser.parseKeyword("address_point");
+  return success();
+}
+
+static void printGlobalViewAddressPoint(AsmPrinter &p, bool addressPoint) {
+  if (addressPoint)
+    p << ", address_point";
+}
+
 
//===----------------------------------------------------------------------===//
 // IntAttr definitions
 
//===----------------------------------------------------------------------===//
diff --git a/clang/lib/CIR/Dialect/Transforms/CXXABILowering.cpp 
b/clang/lib/CIR/Dialect/Transforms/CXXABILowering.cpp
index 9a0e40bd4f506..750366bfa78c2 100644
--- a/clang/lib/CIR/Dialect/Transforms/CXXABILowering.cpp
+++ b/clang/lib/CIR/Dialect/Transforms/CXXABILowering.cpp
@@ -210,7 +210,8 @@ mlir::Attribute rewriteAttribute(const mlir::TypeConverter 
&tc,
         return cir::GlobalViewAttr::get(
             tc.convertType(gva.getType()), gva.getSymbol(),
             mlir::cast<mlir::ArrayAttr>(
-                rewriteAttribute(tc, ctx, gva.getIndices())));
+                rewriteAttribute(tc, ctx, gva.getIndices())),
+            gva.getAddressPoint());
       })
       .Case<cir::GlobalOffsetAttr>([&tc](cir::GlobalOffsetAttr goa) {
         return cir::GlobalOffsetAttr::get(tc.convertType(goa.getType()),
@@ -504,7 +505,7 @@ static mlir::TypedAttr lowerInitialValue(const LowerModule 
*lowerModule,
 
     if (auto gva = mlir::dyn_cast_if_present<cir::GlobalViewAttr>(initVal))
       return cir::GlobalViewAttr::get(convertedTy, gva.getSymbol(),
-                                      gva.getIndices());
+                                      gva.getIndices(), gva.getAddressPoint());
 
     if (auto goa = mlir::dyn_cast_if_present<cir::GlobalOffsetAttr>(initVal))
       return cir::GlobalOffsetAttr::get(convertedTy, goa.getSymbol(),
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp 
b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index 007b673419056..57e8dc534633e 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -1018,9 +1018,30 @@ mlir::Value 
CIRAttrToValue::visitCirAttr(cir::GlobalViewAttr globalAttr) {
     }
     mlir::Type resTy = addrOp.getType();
     mlir::Type eltTy = converter->convertType(sourceType);
-    addrOp = mlir::LLVM::GEPOp::create(rewriter, parentOp->getLoc(), resTy,
-                                       eltTy, addrOp, indices,
-                                       mlir::LLVM::GEPNoWrapFlags::none);
+    auto gep = mlir::LLVM::GEPOp::create(rewriter, parentOp->getLoc(), resTy,
+                                         eltTy, addrOp, indices,
+                                         mlir::LLVM::GEPNoWrapFlags::none);
+    if (globalAttr.getAddressPoint()) {
+      // Like classic codegen, a vtable address point is inbounds, and only the
+      // one vtable of the group it points into can be accessed through it.
+      auto indices =
+          globalAttr.getIndices().getAsValueRange<mlir::IntegerAttr>();
+      assert(llvm::range_size(indices) == 2 &&
+             "address point takes a vtable index and a slot index");
+      auto vtableTy = mlir::cast<mlir::LLVM::LLVMArrayType>(
+          mlir::cast<mlir::LLVM::LLVMStructType>(eltTy)
+              .getBody()[(*indices.begin()).getZExtValue()]);
+      mlir::DataLayout layout(parentOp->getParentOfType<mlir::ModuleOp>());
+      int64_t slotSize = layout.getTypeSize(vtableTy.getElementType());
+      int64_t offset = (*std::next(indices.begin())).getSExtValue() * slotSize;
+      int64_t size = vtableTy.getNumElements() * slotSize;
+      unsigned indexBits = *layout.getTypeIndexBitwidth(
+          mlir::cast<mlir::LLVM::LLVMPointerType>(addrOp.getType()));
+      gep.setNoWrapFlags(mlir::LLVM::GEPNoWrapFlags::inbounds);
+      gep.setInrangeAttr(mlir::LLVM::ConstantRangeAttr::get(
+          rewriter.getContext(), indexBits, -offset, size - offset));
+    }
+    addrOp = gep;
   }
 
   return castGlobalAddrToType(addrOp, globalAttr.getType(), sourceType,
diff --git a/clang/test/CIR/CodeGen/global-ptr-init.cpp 
b/clang/test/CIR/CodeGen/global-ptr-init.cpp
index 9a9824881a98c..4704dde5fbec9 100644
--- a/clang/test/CIR/CodeGen/global-ptr-init.cpp
+++ b/clang/test/CIR/CodeGen/global-ptr-init.cpp
@@ -11,6 +11,19 @@ struct B {
 };
 B x;
 
-// CIR: cir.global external @x = #cir.const_record<{#cir.global_view<@_ZTV1B, 
[0 : i32, 2 : i32]> : !cir.vptr}> : !rec_B
-// LLVM: @x = global %struct.B { ptr getelementptr inbounds nuw (i8, ptr 
@_ZTV1B, i64 16) }, align 8
+// CIR: cir.global external @x = #cir.const_record<{#cir.global_view<@_ZTV1B, 
[0 : i32, 2 : i32], address_point> : !cir.vptr}> : !rec_B
+// LLVM: @x = global %struct.B { ptr getelementptr inbounds nuw inrange(-16, 
24) (i8, ptr @_ZTV1B, i64 16) }, align 8
 // OGCG: @x = global %struct.B { ptr getelementptr inbounds inrange(-16, 24) 
(i8, ptr @_ZTV1B, i64 16) }, align 8
+
+// The vtable is only declared here: the inrange bound still comes from its 
type.
+struct K {
+  virtual void f();
+};
+K k;
+
+// CIR: cir.global "private" constant external @_ZTV1K : !rec_anon_struct
+// CIR: cir.global external @k = #cir.const_record<{#cir.global_view<@_ZTV1K, 
[0 : i32, 2 : i32], address_point> : !cir.vptr}> : !rec_K
+// LLVM: @_ZTV1K = external constant { [3 x ptr] }, align 8
+// OGCG: @_ZTV1K = external constant { [3 x ptr] }, align 8
+// LLVM: @k = global %struct.K { ptr getelementptr inbounds nuw inrange(-16, 
8) (i8, ptr @_ZTV1K, i64 16) }, align 8
+// OGCG: @k = global %struct.K { ptr getelementptr inbounds inrange(-16, 8) 
(i8, ptr @_ZTV1K, i64 16) }, align 8
diff --git a/clang/test/CIR/CodeGen/vtt.cpp b/clang/test/CIR/CodeGen/vtt.cpp
index 6bd87bf75b7d8..e2100609d0601 100644
--- a/clang/test/CIR/CodeGen/vtt.cpp
+++ b/clang/test/CIR/CodeGen/vtt.cpp
@@ -107,23 +107,23 @@ void D::y() {}
 // VTT for D
 
 // CIR-COMMON:      cir.global{{.*}} @_ZTT1D = #cir.const_array<[
-// CIR-COMMON-SAME:   #cir.global_view<@_ZTV1D, [0 : i32, 3 : i32]> : 
!cir.ptr<!u8i>,
-// CIR-COMMON-SAME:   #cir.global_view<@_ZTC1D0_1B, [0 : i32, 3 : i32]> : 
!cir.ptr<!u8i>,
-// CIR-COMMON-SAME:   #cir.global_view<@_ZTC1D0_1B, [1 : i32, 3 : i32]> : 
!cir.ptr<!u8i>,
-// CIR-COMMON-SAME:   #cir.global_view<@_ZTC1D16_1C, [0 : i32, 3 : i32]> : 
!cir.ptr<!u8i>,
-// CIR-COMMON-SAME:   #cir.global_view<@_ZTC1D16_1C, [1 : i32, 3 : i32]> : 
!cir.ptr<!u8i>,
-// CIR-COMMON-SAME:   #cir.global_view<@_ZTV1D, [2 : i32, 3 : i32]> : 
!cir.ptr<!u8i>,
-// CIR-COMMON-SAME:   #cir.global_view<@_ZTV1D, [1 : i32, 3 : i32]> : 
!cir.ptr<!u8i>
+// CIR-COMMON-SAME:   #cir.global_view<@_ZTV1D, [0 : i32, 3 : i32], 
address_point> : !cir.ptr<!u8i>,
+// CIR-COMMON-SAME:   #cir.global_view<@_ZTC1D0_1B, [0 : i32, 3 : i32], 
address_point> : !cir.ptr<!u8i>,
+// CIR-COMMON-SAME:   #cir.global_view<@_ZTC1D0_1B, [1 : i32, 3 : i32], 
address_point> : !cir.ptr<!u8i>,
+// CIR-COMMON-SAME:   #cir.global_view<@_ZTC1D16_1C, [0 : i32, 3 : i32], 
address_point> : !cir.ptr<!u8i>,
+// CIR-COMMON-SAME:   #cir.global_view<@_ZTC1D16_1C, [1 : i32, 3 : i32], 
address_point> : !cir.ptr<!u8i>,
+// CIR-COMMON-SAME:   #cir.global_view<@_ZTV1D, [2 : i32, 3 : i32], 
address_point> : !cir.ptr<!u8i>,
+// CIR-COMMON-SAME:   #cir.global_view<@_ZTV1D, [1 : i32, 3 : i32], 
address_point> : !cir.ptr<!u8i>
 // CIR-COMMON-SAME: ]> : !cir.array<!cir.ptr<!u8i> x 7> align(8)
 
 // LLVM-COMMON:      @_ZTT1D = constant [7 x ptr] [
-// LLVM-COMMON-SAME:   ptr getelementptr inbounds nuw (i8, ptr @_ZTV1D, i64 
24),
-// LLVM-COMMON-SAME:   ptr getelementptr inbounds nuw (i8, ptr @_ZTC1D0_1B, 
i64 24),
-// LLVM-COMMON-SAME:   ptr getelementptr inbounds nuw (i8, ptr @_ZTC1D0_1B, 
i64 56),
-// LLVM-COMMON-SAME:   ptr getelementptr inbounds nuw (i8, ptr @_ZTC1D16_1C, 
i64 24),
-// LLVM-COMMON-SAME:   ptr getelementptr inbounds nuw (i8, ptr @_ZTC1D16_1C, 
i64 56),
-// LLVM-COMMON-SAME:   ptr getelementptr inbounds nuw (i8, ptr @_ZTV1D, i64 
96),
-// LLVM-COMMON-SAME:   ptr getelementptr inbounds nuw (i8, ptr @_ZTV1D, i64 64)
+// LLVM-COMMON-SAME:   ptr getelementptr inbounds nuw inrange(-24, 16) (i8, 
ptr @_ZTV1D, i64 24),
+// LLVM-COMMON-SAME:   ptr getelementptr inbounds nuw inrange(-24, 8) (i8, ptr 
@_ZTC1D0_1B, i64 24),
+// LLVM-COMMON-SAME:   ptr getelementptr inbounds nuw inrange(-24, 8) (i8, ptr 
@_ZTC1D0_1B, i64 56),
+// LLVM-COMMON-SAME:   ptr getelementptr inbounds nuw inrange(-24, 8) (i8, ptr 
@_ZTC1D16_1C, i64 24),
+// LLVM-COMMON-SAME:   ptr getelementptr inbounds nuw inrange(-24, 8) (i8, ptr 
@_ZTC1D16_1C, i64 56),
+// LLVM-COMMON-SAME:   ptr getelementptr inbounds nuw inrange(-24, 8) (i8, ptr 
@_ZTV1D, i64 96),
+// LLVM-COMMON-SAME:   ptr getelementptr inbounds nuw inrange(-24, 8) (i8, ptr 
@_ZTV1D, i64 64)
 // LLVM-COMMON-SAME: ], align 8
 
 // OGCG-COMMON:      @_ZTT1D = unnamed_addr constant [7 x ptr] [
diff --git a/clang/test/CIR/CodeGenCXX/base-layout.cpp 
b/clang/test/CIR/CodeGenCXX/base-layout.cpp
index dc80ef1dbb8dd..5c814a2ef48c6 100644
--- a/clang/test/CIR/CodeGenCXX/base-layout.cpp
+++ b/clang/test/CIR/CodeGenCXX/base-layout.cpp
@@ -14,8 +14,8 @@ struct B : V1, V2 {};
 struct D : V3, B {};
 
 constinit D d{};
-// CIR: cir.global external @d = 
#cir.const_record<{#cir.const_record<{#cir.global_view<@_ZTV1D, [0 : i32, 2 : 
i32]> : !cir.vptr}> : !rec_V3, 
#cir.const_record<{#cir.const_record<{#cir.global_view<@_ZTV1D, [1 : i32, 2 : 
i32]> : !cir.vptr}> : !rec_V1, #cir.const_record<{#cir.global_view<@_ZTV1D, [2 
: i32, 2 : i32]> : !cir.vptr}> : !rec_V2}> : !rec_B}> : !rec_D
-// LLVM: @d = global %struct.D { %struct.V3 { ptr getelementptr inbounds nuw 
(i8, ptr @_ZTV1D, i64 16) }, %struct.B { %struct.V1 { ptr getelementptr 
inbounds nuw (i8, ptr @_ZTV1D, i64 40) }, %struct.V2 { ptr getelementptr 
inbounds nuw (i8, ptr @_ZTV1D, i64 64) } } }
+// CIR: cir.global external @d = 
#cir.const_record<{#cir.const_record<{#cir.global_view<@_ZTV1D, [0 : i32, 2 : 
i32], address_point> : !cir.vptr}> : !rec_V3, 
#cir.const_record<{#cir.const_record<{#cir.global_view<@_ZTV1D, [1 : i32, 2 : 
i32], address_point> : !cir.vptr}> : !rec_V1, 
#cir.const_record<{#cir.global_view<@_ZTV1D, [2 : i32, 2 : i32], address_point> 
: !cir.vptr}> : !rec_V2}> : !rec_B}> : !rec_D
+// LLVM: @d = global %struct.D { %struct.V3 { ptr getelementptr inbounds nuw 
inrange(-16, 8) (i8, ptr @_ZTV1D, i64 16) }, %struct.B { %struct.V1 { ptr 
getelementptr inbounds nuw inrange(-16, 8) (i8, ptr @_ZTV1D, i64 40) }, 
%struct.V2 { ptr getelementptr inbounds nuw inrange(-16, 8) (i8, ptr @_ZTV1D, 
i64 64) } } }
 // OGCG: @d = global { ptr, ptr, ptr } { ptr getelementptr inbounds 
inrange(-16, 8) (i8, ptr @_ZTV1D, i64 16), ptr getelementptr inbounds 
inrange(-16, 8) (i8, ptr @_ZTV1D, i64 40), ptr getelementptr inbounds 
inrange(-16, 8) (i8, ptr @_ZTV1D, i64 64) }
 
 
diff --git a/clang/test/CIR/CodeGenCXX/vtable-linkage.cpp 
b/clang/test/CIR/CodeGenCXX/vtable-linkage.cpp
index cdef1dbeb086a..45320352010ff 100644
--- a/clang/test/CIR/CodeGenCXX/vtable-linkage.cpp
+++ b/clang/test/CIR/CodeGenCXX/vtable-linkage.cpp
@@ -117,11 +117,11 @@ void use_F() {
 // CIR-DAG: cir.global "private" constant linkonce_odr comdat @_ZTV1C = 
#cir.vtable<{#cir.const_array<[#cir.ptr<null> : !cir.ptr<!u8i>, #cir.ptr<null> 
: !cir.ptr<!u8i>, #cir.ptr<null> : !cir.ptr<!u8i>, #cir.global_view<@_ZTI1C> : 
!cir.ptr<!u8i>, #cir.global_view<@_ZN1C1fEv> : !cir.ptr<!u8i>]> : 
!cir.array<!cir.ptr<!u8i> x 5>}> : !{{.*}}align(8)
 // CIR-DAG: cir.global constant linkonce_odr comdat @_ZTS1C = 
#cir.const_array<"1C" : !cir.array<!s8i x 2>, trailing_zeros> : !cir.array<!s8i 
x 3> align(1)
 // CIR-DAG: cir.global constant linkonce_odr comdat @_ZTI1C = 
#cir.typeinfo<{#cir.global_view<@_ZTVN10__cxxabiv121__vmi_class_type_infoE, [2 
: i32]> : !cir.ptr<!u8i>, #cir.global_view<@_ZTS1C> : !cir.ptr<!u8i>, 
#cir.int<0> : !u32i, #cir.int<1> : !u32i, #cir.global_view<@_ZTI1B> : 
!cir.ptr<!u8i>, #cir.int<-8189> : !s64i}> : !{{.*}}align(8)
-// CIR-DAG: cir.global constant linkonce_odr comdat @_ZTT1C = 
#cir.const_array<[#cir.global_view<@_ZTV1C, [0 : i32, 4 : i32]> : 
!cir.ptr<!u8i>, #cir.global_view<@_ZTV1C, [0 : i32, 4 : i32]> : 
!cir.ptr<!u8i>]> : !cir.array<!cir.ptr<!u8i> x 2> align(8)
+// CIR-DAG: cir.global constant linkonce_odr comdat @_ZTT1C = 
#cir.const_array<[#cir.global_view<@_ZTV1C, [0 : i32, 4 : i32], address_point> 
: !cir.ptr<!u8i>, #cir.global_view<@_ZTV1C, [0 : i32, 4 : i32], address_point> 
: !cir.ptr<!u8i>]> : !cir.array<!cir.ptr<!u8i> x 2> align(8)
 // LLVM-DAG: @_ZTV1C = linkonce_odr constant { [5 x ptr] } { [5 x ptr] [ptr 
null, ptr null, ptr null, ptr @_ZTI1C, ptr @_ZN1C1fEv] }, comdat, align 8
 // LLVM-DAG: @_ZTS1C = linkonce_odr constant [{{[0-9]}} x i8] c"1C\00", 
comdat, align 1
 // LLVM-DAG: @_ZTI1C = linkonce_odr constant { ptr, ptr, i32, i32, ptr, i64 } 
{ ptr getelementptr{{.*}}({{.*}}, ptr 
@_ZTVN10__cxxabiv121__vmi_class_type_infoE, i64 {{.*}}), ptr @_ZTS1C, i32 0, 
i32 1, ptr @_ZTI1B, i64 -8189 }, comdat
-// LLVM-DAG: @_ZTT1C = linkonce_odr{{.*}} constant [2 x ptr] [ptr 
getelementptr inbounds{{.*}}({{.*}}, ptr @_ZTV1C, {{.*}}, ptr getelementptr 
inbounds {{.*}}({{.*}}, ptr @_ZTV1C{{.*}})]
+// LLVM-DAG: @_ZTT1C = linkonce_odr{{.*}} constant [2 x ptr] [ptr 
getelementptr inbounds {{(nuw )?}}inrange(-32, 8) (i8, ptr @_ZTV1C, i64 32), 
ptr getelementptr inbounds {{(nuw )?}}inrange(-32, 8) (i8, ptr @_ZTV1C, i64 32)]
 
 // D has a key function that is defined in this translation unit so its vtable 
is
 // defined in the translation unit.
diff --git a/clang/test/CIR/IR/global-view-address-point.cir 
b/clang/test/CIR/IR/global-view-address-point.cir
new file mode 100644
index 0000000000000..0faecab15dd1a
--- /dev/null
+++ b/clang/test/CIR/IR/global-view-address-point.cir
@@ -0,0 +1,35 @@
+// RUN: cir-opt %s --verify-roundtrip | FileCheck %s
+// RUN: cir-opt %s -cir-to-llvm | FileCheck %s -check-prefix=MLIR
+// RUN: cir-translate %s -cir-to-llvmir --disable-cc-lowering | FileCheck %s 
-check-prefix=LLVM
+
+!u8i = !cir.int<u, 8>
+!rec_anon_struct = !cir.struct<{data !cir.array<!cir.ptr<!u8i> x 5>, data 
!cir.array<!cir.ptr<!u8i> x 4>}>
+!rec_B = !cir.struct<"B" {data !cir.vptr}>
+module attributes {cir.triple = "x86_64-unknown-linux-gnu"} {
+  cir.global "private" constant external @_ZTV1D : !rec_anon_struct
+
+  // CHECK: #cir.global_view<@_ZTV1D, [0 : i32, 3 : i32], address_point> : 
!cir.ptr<!u8i>
+  // CHECK: #cir.global_view<@_ZTV1D, [1 : i32, 2 : i32], address_point> : 
!cir.ptr<!u8i>
+  // CHECK: #cir.global_view<@_ZTV1D, [1 : i32, 2 : i32]> : !cir.ptr<!u8i>
+  cir.global external @vtt = #cir.const_array<[
+    #cir.global_view<@_ZTV1D, [0 : i32, 3 : i32], address_point> : 
!cir.ptr<!u8i>,
+    #cir.global_view<@_ZTV1D, [1 : i32, 2 : i32], address_point> : 
!cir.ptr<!u8i>,
+    #cir.global_view<@_ZTV1D, [1 : i32, 2 : i32]> : !cir.ptr<!u8i>
+  ]> : !cir.array<!cir.ptr<!u8i> x 3>
+
+  // CHECK: #cir.global_view<@_ZTV1D, [0 : i32, 3 : i32], address_point> : 
!cir.vptr
+  cir.global external @b = #cir.const_record<{#cir.global_view<@_ZTV1D, [0 : 
i32, 3 : i32], address_point> : !cir.vptr}> : !rec_B
+}
+
+// An address point is inbounds and can only reach the vtable it points into.
+
+// MLIR: llvm.getelementptr inbounds inrange <i64, -24, 16> %{{.*}}[0, 0, 3]
+// MLIR: llvm.getelementptr inbounds inrange <i64, -16, 16> %{{.*}}[0, 1, 2]
+// MLIR: llvm.getelementptr %{{.*}}[0, 1, 2]
+// MLIR: llvm.getelementptr inbounds inrange <i64, -24, 16> %{{.*}}[0, 0, 3]
+
+// LLVM: @vtt = global [3 x ptr] [
+// LLVM-SAME: ptr getelementptr inbounds nuw inrange(-24, 16) (i8, ptr 
@_ZTV1D, i64 24),
+// LLVM-SAME: ptr getelementptr inbounds nuw inrange(-16, 16) (i8, ptr 
@_ZTV1D, i64 56),
+// LLVM-SAME: ptr getelementptr inbounds nuw (i8, ptr @_ZTV1D, i64 56)]
+// LLVM: @b = global %struct.B { ptr getelementptr inbounds nuw inrange(-24, 
16) (i8, ptr @_ZTV1D, i64 24) }

>From 23621d812c64df3c5caf3c70e1ae54883d03e845 Mon Sep 17 00:00:00 2001
From: Bruno Cardoso Lopes <[email protected]>
Date: Wed, 7 Oct 2026 18:55:47 -0700
Subject: [PATCH 2/2] [CIR] Address review on vtable address points

Take the address point through getGlobalViewAttr instead of rebuilding
the attribute around an intermediate, and print it with a declarative
optional group rather than custom parse/print code. The spelling is now
`, address_point true`, matching the trivial-bool precedent.

Assisted-by: Muse Code (Muse).
---
 .../clang/CIR/Dialect/Builder/CIRBaseBuilder.h | 10 ++++++----
 clang/include/clang/CIR/Dialect/IR/CIRAttrs.td |  2 +-
 clang/lib/CIR/CodeGen/CIRGenModule.cpp         |  9 +++------
 clang/lib/CIR/CodeGen/CIRGenVTables.cpp        |  7 +++----
 clang/lib/CIR/Dialect/IR/CIRAttrs.cpp          | 18 ------------------
 clang/test/CIR/CodeGen/global-ptr-init.cpp     |  4 ++--
 clang/test/CIR/CodeGen/vtt.cpp                 | 14 +++++++-------
 clang/test/CIR/CodeGenCXX/base-layout.cpp      |  2 +-
 clang/test/CIR/CodeGenCXX/vtable-linkage.cpp   |  2 +-
 .../test/CIR/IR/global-view-address-point.cir  | 12 ++++++------
 10 files changed, 30 insertions(+), 50 deletions(-)

diff --git a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h 
b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
index 36d583cfe9fbe..2ee3fcb7cf209 100644
--- a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
+++ b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
@@ -472,21 +472,23 @@ class CIRBaseBuilderTy : public mlir::OpBuilder {
   /// Get constant address of a global variable as an MLIR attribute.
   cir::GlobalViewAttr getGlobalViewAttr(cir::PointerType type,
                                         cir::GlobalOp globalOp,
-                                        mlir::ArrayAttr indices = {}) {
+                                        mlir::ArrayAttr indices = {},
+                                        bool addressPoint = false) {
     auto symbol = mlir::FlatSymbolRefAttr::get(globalOp.getSymNameAttr());
-    return cir::GlobalViewAttr::get(type, symbol, indices);
+    return cir::GlobalViewAttr::get(type, symbol, indices, addressPoint);
   }
 
   /// Get constant address of a global variable as an MLIR attribute.
   /// This overload converts raw int64_t indices to an ArrayAttr.
   cir::GlobalViewAttr getGlobalViewAttr(cir::PointerType type,
                                         cir::GlobalOp globalOp,
-                                        llvm::ArrayRef<int64_t> indices) {
+                                        llvm::ArrayRef<int64_t> indices,
+                                        bool addressPoint = false) {
     llvm::SmallVector<mlir::Attribute> attrs;
     for (int64_t ind : indices)
       attrs.push_back(getI64IntegerAttr(ind));
     mlir::ArrayAttr arAttr = mlir::ArrayAttr::get(getContext(), attrs);
-    return getGlobalViewAttr(type, globalOp, arAttr);
+    return getGlobalViewAttr(type, globalOp, arAttr, addressPoint);
   }
 
   cir::GetGlobalOp createGetGlobal(mlir::Location loc, cir::GlobalOp global,
diff --git a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td 
b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
index 64b8016971c76..4ccdc83f310fb 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
@@ -1070,7 +1070,7 @@ def CIR_GlobalViewAttr : CIR_ValueLikeAttr<"GlobalView", 
"global_view"> {
     `<`
       $symbol
       (`,` $indices^)?
-      `` custom<GlobalViewAddressPoint>($address_point)
+      (`,` `address_point` $address_point^)?
     `>`
   }];
 }
diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.cpp 
b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
index fe2201ac44940..39c3ede7b1074 100644
--- a/clang/lib/CIR/CodeGen/CIRGenModule.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
@@ -1123,12 +1123,9 @@ static mlir::Attribute createNewGlobalView(CIRGenModule 
&cgm,
   else if (isa<cir::ArrayType>(oldTy))
     newPtrTy = cast<cir::PointerType>(attr.getType());
 
-  if (newPtrTy) {
-    cir::GlobalViewAttr view =
-        bld.getGlobalViewAttr(newPtrTy, newGlob, newInds);
-    return cir::GlobalViewAttr::get(view.getType(), view.getSymbol(),
-                                    view.getIndices(), attr.getAddressPoint());
-  }
+  if (newPtrTy)
+    return bld.getGlobalViewAttr(newPtrTy, newGlob, newInds,
+                                 attr.getAddressPoint());
 
   // This may be unreachable in practice, but keep it as errorNYI while CIR
   // is still under development.
diff --git a/clang/lib/CIR/CodeGen/CIRGenVTables.cpp 
b/clang/lib/CIR/CodeGen/CIRGenVTables.cpp
index 4c9ee965bebec..921ae7b6cd144 100644
--- a/clang/lib/CIR/CodeGen/CIRGenVTables.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenVTables.cpp
@@ -499,10 +499,9 @@ void CIRGenVTables::emitVTTDefinition(cir::GlobalOp vttOp,
     };
 
     auto indicesAttr = mlir::ArrayAttr::get(mlirContext, indices);
-    auto init = cir::GlobalViewAttr::get(
-        cgm.getBuilder().getUInt8PtrTy(),
-        mlir::FlatSymbolRefAttr::get(vtable.getSymNameAttr()), indicesAttr,
-        /*addressPoint=*/true);
+    CIRGenBuilderTy &bld = cgm.getBuilder();
+    auto init = bld.getGlobalViewAttr(bld.getUInt8PtrTy(), vtable, indicesAttr,
+                                      /*addressPoint=*/true);
 
     vttComponents.push_back(init);
   }
diff --git a/clang/lib/CIR/Dialect/IR/CIRAttrs.cpp 
b/clang/lib/CIR/Dialect/IR/CIRAttrs.cpp
index 388de73108bee..2649ed1449739 100644
--- a/clang/lib/CIR/Dialect/IR/CIRAttrs.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRAttrs.cpp
@@ -57,11 +57,6 @@ parseDataMemberPath(mlir::AsmParser &parser,
 static void printDataMemberPath(mlir::AsmPrinter &p,
                                 mlir::DenseI32ArrayAttr memberPath);
 
-static mlir::ParseResult parseGlobalViewAddressPoint(mlir::AsmParser &parser,
-                                                     bool &addressPoint);
-
-static void printGlobalViewAddressPoint(mlir::AsmPrinter &p, bool 
addressPoint);
-
 #define GET_ATTRDEF_CLASSES
 #include "clang/CIR/Dialect/IR/CIROpsAttributes.cpp.inc"
 
@@ -358,19 +353,6 @@ static void printDataMemberPath(AsmPrinter &p,
     p.printStrippedAttrOrType(memberPath);
 }
 
-static ParseResult parseGlobalViewAddressPoint(AsmParser &parser,
-                                               bool &addressPoint) {
-  addressPoint = parser.parseOptionalComma().succeeded();
-  if (addressPoint)
-    return parser.parseKeyword("address_point");
-  return success();
-}
-
-static void printGlobalViewAddressPoint(AsmPrinter &p, bool addressPoint) {
-  if (addressPoint)
-    p << ", address_point";
-}
-
 
//===----------------------------------------------------------------------===//
 // IntAttr definitions
 
//===----------------------------------------------------------------------===//
diff --git a/clang/test/CIR/CodeGen/global-ptr-init.cpp 
b/clang/test/CIR/CodeGen/global-ptr-init.cpp
index 4704dde5fbec9..b2e9b3e2a5e20 100644
--- a/clang/test/CIR/CodeGen/global-ptr-init.cpp
+++ b/clang/test/CIR/CodeGen/global-ptr-init.cpp
@@ -11,7 +11,7 @@ struct B {
 };
 B x;
 
-// CIR: cir.global external @x = #cir.const_record<{#cir.global_view<@_ZTV1B, 
[0 : i32, 2 : i32], address_point> : !cir.vptr}> : !rec_B
+// CIR: cir.global external @x = #cir.const_record<{#cir.global_view<@_ZTV1B, 
[0 : i32, 2 : i32], address_point true> : !cir.vptr}> : !rec_B
 // LLVM: @x = global %struct.B { ptr getelementptr inbounds nuw inrange(-16, 
24) (i8, ptr @_ZTV1B, i64 16) }, align 8
 // OGCG: @x = global %struct.B { ptr getelementptr inbounds inrange(-16, 24) 
(i8, ptr @_ZTV1B, i64 16) }, align 8
 
@@ -22,7 +22,7 @@ struct K {
 K k;
 
 // CIR: cir.global "private" constant external @_ZTV1K : !rec_anon_struct
-// CIR: cir.global external @k = #cir.const_record<{#cir.global_view<@_ZTV1K, 
[0 : i32, 2 : i32], address_point> : !cir.vptr}> : !rec_K
+// CIR: cir.global external @k = #cir.const_record<{#cir.global_view<@_ZTV1K, 
[0 : i32, 2 : i32], address_point true> : !cir.vptr}> : !rec_K
 // LLVM: @_ZTV1K = external constant { [3 x ptr] }, align 8
 // OGCG: @_ZTV1K = external constant { [3 x ptr] }, align 8
 // LLVM: @k = global %struct.K { ptr getelementptr inbounds nuw inrange(-16, 
8) (i8, ptr @_ZTV1K, i64 16) }, align 8
diff --git a/clang/test/CIR/CodeGen/vtt.cpp b/clang/test/CIR/CodeGen/vtt.cpp
index e2100609d0601..0a150f18b75ac 100644
--- a/clang/test/CIR/CodeGen/vtt.cpp
+++ b/clang/test/CIR/CodeGen/vtt.cpp
@@ -107,13 +107,13 @@ void D::y() {}
 // VTT for D
 
 // CIR-COMMON:      cir.global{{.*}} @_ZTT1D = #cir.const_array<[
-// CIR-COMMON-SAME:   #cir.global_view<@_ZTV1D, [0 : i32, 3 : i32], 
address_point> : !cir.ptr<!u8i>,
-// CIR-COMMON-SAME:   #cir.global_view<@_ZTC1D0_1B, [0 : i32, 3 : i32], 
address_point> : !cir.ptr<!u8i>,
-// CIR-COMMON-SAME:   #cir.global_view<@_ZTC1D0_1B, [1 : i32, 3 : i32], 
address_point> : !cir.ptr<!u8i>,
-// CIR-COMMON-SAME:   #cir.global_view<@_ZTC1D16_1C, [0 : i32, 3 : i32], 
address_point> : !cir.ptr<!u8i>,
-// CIR-COMMON-SAME:   #cir.global_view<@_ZTC1D16_1C, [1 : i32, 3 : i32], 
address_point> : !cir.ptr<!u8i>,
-// CIR-COMMON-SAME:   #cir.global_view<@_ZTV1D, [2 : i32, 3 : i32], 
address_point> : !cir.ptr<!u8i>,
-// CIR-COMMON-SAME:   #cir.global_view<@_ZTV1D, [1 : i32, 3 : i32], 
address_point> : !cir.ptr<!u8i>
+// CIR-COMMON-SAME:   #cir.global_view<@_ZTV1D, [0 : i32, 3 : i32], 
address_point true> : !cir.ptr<!u8i>,
+// CIR-COMMON-SAME:   #cir.global_view<@_ZTC1D0_1B, [0 : i32, 3 : i32], 
address_point true> : !cir.ptr<!u8i>,
+// CIR-COMMON-SAME:   #cir.global_view<@_ZTC1D0_1B, [1 : i32, 3 : i32], 
address_point true> : !cir.ptr<!u8i>,
+// CIR-COMMON-SAME:   #cir.global_view<@_ZTC1D16_1C, [0 : i32, 3 : i32], 
address_point true> : !cir.ptr<!u8i>,
+// CIR-COMMON-SAME:   #cir.global_view<@_ZTC1D16_1C, [1 : i32, 3 : i32], 
address_point true> : !cir.ptr<!u8i>,
+// CIR-COMMON-SAME:   #cir.global_view<@_ZTV1D, [2 : i32, 3 : i32], 
address_point true> : !cir.ptr<!u8i>,
+// CIR-COMMON-SAME:   #cir.global_view<@_ZTV1D, [1 : i32, 3 : i32], 
address_point true> : !cir.ptr<!u8i>
 // CIR-COMMON-SAME: ]> : !cir.array<!cir.ptr<!u8i> x 7> align(8)
 
 // LLVM-COMMON:      @_ZTT1D = constant [7 x ptr] [
diff --git a/clang/test/CIR/CodeGenCXX/base-layout.cpp 
b/clang/test/CIR/CodeGenCXX/base-layout.cpp
index 5c814a2ef48c6..b9e1b841a2f09 100644
--- a/clang/test/CIR/CodeGenCXX/base-layout.cpp
+++ b/clang/test/CIR/CodeGenCXX/base-layout.cpp
@@ -14,7 +14,7 @@ struct B : V1, V2 {};
 struct D : V3, B {};
 
 constinit D d{};
-// CIR: cir.global external @d = 
#cir.const_record<{#cir.const_record<{#cir.global_view<@_ZTV1D, [0 : i32, 2 : 
i32], address_point> : !cir.vptr}> : !rec_V3, 
#cir.const_record<{#cir.const_record<{#cir.global_view<@_ZTV1D, [1 : i32, 2 : 
i32], address_point> : !cir.vptr}> : !rec_V1, 
#cir.const_record<{#cir.global_view<@_ZTV1D, [2 : i32, 2 : i32], address_point> 
: !cir.vptr}> : !rec_V2}> : !rec_B}> : !rec_D
+// CIR: cir.global external @d = 
#cir.const_record<{#cir.const_record<{#cir.global_view<@_ZTV1D, [0 : i32, 2 : 
i32], address_point true> : !cir.vptr}> : !rec_V3, 
#cir.const_record<{#cir.const_record<{#cir.global_view<@_ZTV1D, [1 : i32, 2 : 
i32], address_point true> : !cir.vptr}> : !rec_V1, 
#cir.const_record<{#cir.global_view<@_ZTV1D, [2 : i32, 2 : i32], address_point 
true> : !cir.vptr}> : !rec_V2}> : !rec_B}> : !rec_D
 // LLVM: @d = global %struct.D { %struct.V3 { ptr getelementptr inbounds nuw 
inrange(-16, 8) (i8, ptr @_ZTV1D, i64 16) }, %struct.B { %struct.V1 { ptr 
getelementptr inbounds nuw inrange(-16, 8) (i8, ptr @_ZTV1D, i64 40) }, 
%struct.V2 { ptr getelementptr inbounds nuw inrange(-16, 8) (i8, ptr @_ZTV1D, 
i64 64) } } }
 // OGCG: @d = global { ptr, ptr, ptr } { ptr getelementptr inbounds 
inrange(-16, 8) (i8, ptr @_ZTV1D, i64 16), ptr getelementptr inbounds 
inrange(-16, 8) (i8, ptr @_ZTV1D, i64 40), ptr getelementptr inbounds 
inrange(-16, 8) (i8, ptr @_ZTV1D, i64 64) }
 
diff --git a/clang/test/CIR/CodeGenCXX/vtable-linkage.cpp 
b/clang/test/CIR/CodeGenCXX/vtable-linkage.cpp
index 45320352010ff..ece1a9675761a 100644
--- a/clang/test/CIR/CodeGenCXX/vtable-linkage.cpp
+++ b/clang/test/CIR/CodeGenCXX/vtable-linkage.cpp
@@ -117,7 +117,7 @@ void use_F() {
 // CIR-DAG: cir.global "private" constant linkonce_odr comdat @_ZTV1C = 
#cir.vtable<{#cir.const_array<[#cir.ptr<null> : !cir.ptr<!u8i>, #cir.ptr<null> 
: !cir.ptr<!u8i>, #cir.ptr<null> : !cir.ptr<!u8i>, #cir.global_view<@_ZTI1C> : 
!cir.ptr<!u8i>, #cir.global_view<@_ZN1C1fEv> : !cir.ptr<!u8i>]> : 
!cir.array<!cir.ptr<!u8i> x 5>}> : !{{.*}}align(8)
 // CIR-DAG: cir.global constant linkonce_odr comdat @_ZTS1C = 
#cir.const_array<"1C" : !cir.array<!s8i x 2>, trailing_zeros> : !cir.array<!s8i 
x 3> align(1)
 // CIR-DAG: cir.global constant linkonce_odr comdat @_ZTI1C = 
#cir.typeinfo<{#cir.global_view<@_ZTVN10__cxxabiv121__vmi_class_type_infoE, [2 
: i32]> : !cir.ptr<!u8i>, #cir.global_view<@_ZTS1C> : !cir.ptr<!u8i>, 
#cir.int<0> : !u32i, #cir.int<1> : !u32i, #cir.global_view<@_ZTI1B> : 
!cir.ptr<!u8i>, #cir.int<-8189> : !s64i}> : !{{.*}}align(8)
-// CIR-DAG: cir.global constant linkonce_odr comdat @_ZTT1C = 
#cir.const_array<[#cir.global_view<@_ZTV1C, [0 : i32, 4 : i32], address_point> 
: !cir.ptr<!u8i>, #cir.global_view<@_ZTV1C, [0 : i32, 4 : i32], address_point> 
: !cir.ptr<!u8i>]> : !cir.array<!cir.ptr<!u8i> x 2> align(8)
+// CIR-DAG: cir.global constant linkonce_odr comdat @_ZTT1C = 
#cir.const_array<[#cir.global_view<@_ZTV1C, [0 : i32, 4 : i32], address_point 
true> : !cir.ptr<!u8i>, #cir.global_view<@_ZTV1C, [0 : i32, 4 : i32], 
address_point true> : !cir.ptr<!u8i>]> : !cir.array<!cir.ptr<!u8i> x 2> align(8)
 // LLVM-DAG: @_ZTV1C = linkonce_odr constant { [5 x ptr] } { [5 x ptr] [ptr 
null, ptr null, ptr null, ptr @_ZTI1C, ptr @_ZN1C1fEv] }, comdat, align 8
 // LLVM-DAG: @_ZTS1C = linkonce_odr constant [{{[0-9]}} x i8] c"1C\00", 
comdat, align 1
 // LLVM-DAG: @_ZTI1C = linkonce_odr constant { ptr, ptr, i32, i32, ptr, i64 } 
{ ptr getelementptr{{.*}}({{.*}}, ptr 
@_ZTVN10__cxxabiv121__vmi_class_type_infoE, i64 {{.*}}), ptr @_ZTS1C, i32 0, 
i32 1, ptr @_ZTI1B, i64 -8189 }, comdat
diff --git a/clang/test/CIR/IR/global-view-address-point.cir 
b/clang/test/CIR/IR/global-view-address-point.cir
index 0faecab15dd1a..15cbf4cf0b688 100644
--- a/clang/test/CIR/IR/global-view-address-point.cir
+++ b/clang/test/CIR/IR/global-view-address-point.cir
@@ -8,17 +8,17 @@
 module attributes {cir.triple = "x86_64-unknown-linux-gnu"} {
   cir.global "private" constant external @_ZTV1D : !rec_anon_struct
 
-  // CHECK: #cir.global_view<@_ZTV1D, [0 : i32, 3 : i32], address_point> : 
!cir.ptr<!u8i>
-  // CHECK: #cir.global_view<@_ZTV1D, [1 : i32, 2 : i32], address_point> : 
!cir.ptr<!u8i>
+  // CHECK: #cir.global_view<@_ZTV1D, [0 : i32, 3 : i32], address_point true> 
: !cir.ptr<!u8i>
+  // CHECK: #cir.global_view<@_ZTV1D, [1 : i32, 2 : i32], address_point true> 
: !cir.ptr<!u8i>
   // CHECK: #cir.global_view<@_ZTV1D, [1 : i32, 2 : i32]> : !cir.ptr<!u8i>
   cir.global external @vtt = #cir.const_array<[
-    #cir.global_view<@_ZTV1D, [0 : i32, 3 : i32], address_point> : 
!cir.ptr<!u8i>,
-    #cir.global_view<@_ZTV1D, [1 : i32, 2 : i32], address_point> : 
!cir.ptr<!u8i>,
+    #cir.global_view<@_ZTV1D, [0 : i32, 3 : i32], address_point true> : 
!cir.ptr<!u8i>,
+    #cir.global_view<@_ZTV1D, [1 : i32, 2 : i32], address_point true> : 
!cir.ptr<!u8i>,
     #cir.global_view<@_ZTV1D, [1 : i32, 2 : i32]> : !cir.ptr<!u8i>
   ]> : !cir.array<!cir.ptr<!u8i> x 3>
 
-  // CHECK: #cir.global_view<@_ZTV1D, [0 : i32, 3 : i32], address_point> : 
!cir.vptr
-  cir.global external @b = #cir.const_record<{#cir.global_view<@_ZTV1D, [0 : 
i32, 3 : i32], address_point> : !cir.vptr}> : !rec_B
+  // CHECK: #cir.global_view<@_ZTV1D, [0 : i32, 3 : i32], address_point true> 
: !cir.vptr
+  cir.global external @b = #cir.const_record<{#cir.global_view<@_ZTV1D, [0 : 
i32, 3 : i32], address_point true> : !cir.vptr}> : !rec_B
 }
 
 // An address point is inbounds and can only reach the vtable it points into.

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to