https://github.com/andykaylor updated https://github.com/llvm/llvm-project/pull/178323
>From 6c8bc7cfce8defed49279405daba825f295d454f Mon Sep 17 00:00:00 2001 From: Andy Kaylor <[email protected]> Date: Thu, 4 Dec 2025 17:07:25 -0800 Subject: [PATCH 1/2] [CIR] Add handling for non-ODR use DeclRefLValues This upstreams the code to handle decl ref l-values for non-odr uses. --- clang/lib/CIR/CodeGen/CIRGenDecl.cpp | 61 ++++++++++ clang/lib/CIR/CodeGen/CIRGenExpr.cpp | 22 +++- clang/lib/CIR/CodeGen/CIRGenModule.h | 4 + clang/lib/CIR/CodeGen/CIRGenTypes.cpp | 15 +-- .../CIR/Dialect/Transforms/CXXABILowering.cpp | 30 +++++ clang/test/CIR/CodeGen/no-odr-use.cpp | 113 ++++++++++++++++++ 6 files changed, 234 insertions(+), 11 deletions(-) create mode 100644 clang/test/CIR/CodeGen/no-odr-use.cpp diff --git a/clang/lib/CIR/CodeGen/CIRGenDecl.cpp b/clang/lib/CIR/CodeGen/CIRGenDecl.cpp index 393633f686917..42a7d70677b61 100644 --- a/clang/lib/CIR/CodeGen/CIRGenDecl.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenDecl.cpp @@ -501,6 +501,67 @@ CIRGenModule::getOrCreateStaticVarDecl(const VarDecl &d, return gv; } +Address CIRGenModule::createUnnamedGlobalFrom(const VarDecl &d, + mlir::Attribute constAttr, + CharUnits align) { + auto functionName = [&](const DeclContext *dc) -> std::string { + if (const auto *fd = dyn_cast<FunctionDecl>(dc)) { + if (const auto *cc = dyn_cast<CXXConstructorDecl>(fd)) + return cc->getNameAsString(); + if (const auto *cd = dyn_cast<CXXDestructorDecl>(fd)) + return cd->getNameAsString(); + return std::string(getMangledName(fd)); + } else if (const auto *om = dyn_cast<ObjCMethodDecl>(dc)) { + return om->getNameAsString(); + } else if (isa<BlockDecl>(dc)) { + return "<block>"; + } else if (isa<CapturedDecl>(dc)) { + return "<captured>"; + } else { + llvm_unreachable("expected a function or method"); + } + }; + + // Form a simple per-variable cache of these values in case we find we + // want to reuse them. + cir::GlobalOp &cacheEntry = initializerConstants[&d]; + if (!cacheEntry || cacheEntry.getInitialValue() != constAttr) { + auto ty = mlir::cast<mlir::TypedAttr>(constAttr).getType(); + bool isConstant = true; + + std::string name; + if (d.hasGlobalStorage()) + name = getMangledName(&d).str() + ".const"; + else if (const DeclContext *dc = d.getParentFunctionOrMethod()) + name = ("__const." + functionName(dc) + "." + d.getName()).str(); + else + llvm_unreachable("local variable has no parent function or method"); + + assert(!cir::MissingFeatures::addressSpace()); + cir::GlobalOp gv = builder.createVersionedGlobal( + getModule(), getLoc(d.getLocation()), name, ty, isConstant, + cir::GlobalLinkageKind::PrivateLinkage); + // TODO(cir): infer visibility from linkage in global op builder. + gv.setVisibility(getMLIRVisibilityFromCIRLinkage( + cir::GlobalLinkageKind::PrivateLinkage)); + gv.setInitialValueAttr(constAttr); + gv.setAlignment(align.getAsAlign().value()); + // TODO(cir): Set unnamed address attribute when available in CIR + + cacheEntry = gv; + } else if (cacheEntry.getAlignment() < align.getQuantity()) { + cacheEntry.setAlignment(align.getAsAlign().value()); + } + + // Create a GetGlobalOp to get a pointer to the global + assert(!cir::MissingFeatures::addressSpace()); + mlir::Type eltTy = mlir::cast<mlir::TypedAttr>(constAttr).getType(); + auto ptrTy = builder.getPointerTo(cacheEntry.getSymType()); + mlir::Value globalPtr = cir::GetGlobalOp::create( + builder, getLoc(d.getLocation()), ptrTy, cacheEntry.getSymName()); + return Address(globalPtr, eltTy, align); +} + /// Add the initializer for 'd' to the global variable that has already been /// created for it. If the initializer has a different type than gv does, this /// may free gv and return a different one. Otherwise it just returns gv. diff --git a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp index 504f18e1a9f31..8bdf075aab695 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp @@ -883,8 +883,26 @@ LValue CIRGenFunction::emitDeclRefLValue(const DeclRefExpr *e) { if (e->isNonOdrUse() == NOUR_Constant && (vd->getType()->isReferenceType() || !canEmitSpuriousReferenceToVariable(*this, e, vd))) { - cgm.errorNYI(e->getSourceRange(), "emitDeclRefLValue: NonOdrUse"); - return LValue(); + vd->getAnyInitializer(vd); + mlir::Attribute val = ConstantEmitter(*this).emitAbstract( + e->getLocation(), *vd->evaluateValue(), vd->getType()); + assert(val && "failed to emit constant expression"); + + Address addr = Address::invalid(); + if (!vd->getType()->isReferenceType()) { + // Spill the constant value to a global. + addr = cgm.createUnnamedGlobalFrom(*vd, val, + getContext().getDeclAlign(vd)); + mlir::Type varTy = getTypes().convertTypeForMem(vd->getType()); + auto ptrTy = mlir::cast<cir::PointerType>(addr.getPointer().getType()); + if (ptrTy.getPointee() != varTy) { + addr = addr.withElementType(builder, varTy); + } + } else { + cgm.errorNYI(e->getSourceRange(), + "emitDeclRefLValue: non-odr reference type"); + } + return makeAddrLValue(addr, ty, AlignmentSource::Decl); } // Check for captured variables. diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.h b/clang/lib/CIR/CodeGen/CIRGenModule.h index 3c4f35bacc4f9..2f7020a54e607 100644 --- a/clang/lib/CIR/CodeGen/CIRGenModule.h +++ b/clang/lib/CIR/CodeGen/CIRGenModule.h @@ -147,6 +147,7 @@ class CIRGenModule : public CIRGenTypeCache { void handleCXXStaticMemberVarInstantiation(VarDecl *vd); llvm::DenseMap<const Decl *, cir::GlobalOp> staticLocalDeclMap; + llvm::DenseMap<const VarDecl *, cir::GlobalOp> initializerConstants; mlir::Operation *getGlobalValue(llvm::StringRef ref); @@ -161,6 +162,9 @@ class CIRGenModule : public CIRGenTypeCache { cir::GlobalOp getOrCreateStaticVarDecl(const VarDecl &d, cir::GlobalLinkageKind linkage); + Address createUnnamedGlobalFrom(const VarDecl &d, mlir::Attribute constAttr, + CharUnits align); + /// If the specified mangled name is not in the module, create and return an /// mlir::GlobalOp value cir::GlobalOp getOrCreateCIRGlobal(llvm::StringRef mangledName, mlir::Type ty, diff --git a/clang/lib/CIR/CodeGen/CIRGenTypes.cpp b/clang/lib/CIR/CodeGen/CIRGenTypes.cpp index 851119ee52096..bcbfadbac0347 100644 --- a/clang/lib/CIR/CodeGen/CIRGenTypes.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenTypes.cpp @@ -505,15 +505,12 @@ mlir::Type CIRGenTypes::convertType(QualType type) { case Type::ConstantArray: { const ConstantArrayType *arrTy = cast<ConstantArrayType>(ty); mlir::Type elemTy = convertTypeForMem(arrTy->getElementType()); - - // TODO(CIR): In LLVM, "lower arrays of undefined struct type to arrays of - // i8 just to have a concrete type" - if (!cir::isSized(elemTy)) { - cgm.errorNYI(SourceLocation(), "arrays of undefined struct type", type); - resultType = cgm.uInt32Ty; - break; - } - + // In classic codegen, arrays of unsized types which it assumes are "arrays + // of undefined struct type" are lowered to arrays of i8 "just to have a + // concrete type", but in CIR, we can get here with abstract types like + // !cir.method and !cir.data_member, so let's just create an array of the + // type we have and handle it during lowering if we still don't have a sized + // type. resultType = cir::ArrayType::get(elemTy, arrTy->getSize().getZExtValue()); break; } diff --git a/clang/lib/CIR/Dialect/Transforms/CXXABILowering.cpp b/clang/lib/CIR/Dialect/Transforms/CXXABILowering.cpp index 9d977af808ee0..9ddb71c64fde9 100644 --- a/clang/lib/CIR/Dialect/Transforms/CXXABILowering.cpp +++ b/clang/lib/CIR/Dialect/Transforms/CXXABILowering.cpp @@ -270,6 +270,28 @@ mlir::LogicalResult CIRGlobalOpABILowering::matchAndRewrite( mlir::cast_if_present<cir::MethodAttr>(op.getInitialValueAttr()); loweredInit = lowerModule->getCXXABI().lowerMethodConstant( init, layout, *getTypeConverter()); + } else if (auto arrTy = mlir::dyn_cast<cir::ArrayType>(ty)) { + cir::ConstArrayAttr init = + mlir::cast_if_present<cir::ConstArrayAttr>(op.getInitialValueAttr()); + assert(init && "array initial value must be a constant array"); + auto arrayElts = mlir::cast<ArrayAttr>(init.getElts()); + SmallVector<mlir::Attribute> loweredElements; + loweredElements.reserve(arrTy.getSize()); + for (const mlir::Attribute &attr : arrayElts) { + if (auto methodAttr = mlir::dyn_cast<cir::MethodAttr>(attr)) { + mlir::Attribute loweredElt = + lowerModule->getCXXABI().lowerMethodConstant(methodAttr, layout, + *getTypeConverter()); + loweredElements.push_back(loweredElt); + } else { + llvm_unreachable("array of data member lowering is NYI"); + } + } + auto loweredArrTy = + mlir::cast<cir::ArrayType>(getTypeConverter()->convertType(arrTy)); + loweredInit = cir::ConstArrayAttr::get( + loweredArrTy, + mlir::ArrayAttr::get(rewriter.getContext(), loweredElements)); } else { llvm_unreachable( "inputs to cir.global in ABI lowering must be data member or method"); @@ -363,6 +385,14 @@ static void prepareCXXABITypeConverter(mlir::TypeConverter &converter, return cir::PointerType::get(type.getContext(), loweredPointeeType, type.getAddrSpace()); }); + converter.addConversion([&](cir::ArrayType type) -> mlir::Type { + mlir::Type loweredElementType = + converter.convertType(type.getElementType()); + if (!loweredElementType) + return {}; + return cir::ArrayType::get(loweredElementType, type.getSize()); + }); + converter.addConversion([&](cir::DataMemberType type) -> mlir::Type { mlir::Type abiType = lowerModule.getCXXABI().lowerDataMemberType(type, converter); diff --git a/clang/test/CIR/CodeGen/no-odr-use.cpp b/clang/test/CIR/CodeGen/no-odr-use.cpp new file mode 100644 index 0000000000000..0f1feb8f1e86c --- /dev/null +++ b/clang/test/CIR/CodeGen/no-odr-use.cpp @@ -0,0 +1,113 @@ +// RUN: %clang_cc1 -std=c++11 -fclangir -emit-cir -o %t-cxx11.cir -triple x86_64-linux-gnu %s +// RUN: FileCheck %s --input-file=%t-cxx11.cir --check-prefixes=CIR,CIR-CXX11 +// RUN: %clang_cc1 -std=c++2a -fclangir -emit-cir -o %t-cxx2a.cir -triple x86_64-linux-gnu %s +// RUN: FileCheck %s --input-file=%t-cxx2a.cir --check-prefixes=CIR,CIR-CXX2A +// RUN: %clang_cc1 -std=c++11 -fclangir -emit-llvm -o %t-cxx11-cir.ll -triple x86_64-linux-gnu %s +// RUN: FileCheck %s --input-file=%t-cxx11-cir.ll --check-prefixes=LLVM,LLVM-CXX11 +// RUN: %clang_cc1 -std=c++2a -fclangir -emit-llvm -o %t-cxx2a-cir.ll -triple x86_64-linux-gnu %s +// RUN: FileCheck %s --input-file=%t-cxx2a-cir.ll --check-prefixes=LLVM,LLVM-CXX2A +// RUN: %clang_cc1 -std=c++11 -emit-llvm -o %t-cxx11.ll -triple x86_64-linux-gnu %s +// RUN: FileCheck %s --input-file=%t-cxx11.ll --check-prefixes=OGCG,OGCG-CXX11 +// RUN: %clang_cc1 -std=c++2a -emit-llvm -o %t-cxx2a.ll -triple x86_64-linux-gnu %s +// RUN: FileCheck %s --input-file=%t-cxx2a.ll --check-prefixes=OGCG,OGCG-CXX2A + +// CIR-DAG: cir.global "private" constant cir_private @__const._Z1fi.a = #cir.const_record<{#cir.int<1> : !s32i, #cir.const_array<[#cir.int<2> : !s32i, #cir.int<3> : !s32i]> : !cir.array<!s32i x 2>, #cir.const_array<[#cir.int<4> : !s32i, #cir.int<5> : !s32i, #cir.int<6> : !s32i]> : !cir.array<!s32i x 3>}> : !rec_A +// LLVM-DAG: @__const._Z1fi.a = private constant {{.*}} { i32 1, [2 x i32] [i32 2, i32 3], [3 x i32] [i32 4, i32 5, i32 6] } +// OGCG-DAG: @__const._Z1fi.a = private unnamed_addr constant {{.*}} { i32 1, [2 x i32] [i32 2, i32 3], [3 x i32] [i32 4, i32 5, i32 6] } + +// CIR-CXX11-DAG: cir.global "private" constant cir_private @_ZN7PR422765State1mE.const = #cir.const_array<[#cir.const_record<{#cir.global_view<@_ZN7PR422765State2f1Ev> : !s64i, #cir.int<0> : !s64i}> : !rec_anon_struct, #cir.const_record<{#cir.global_view<@_ZN7PR422765State2f2Ev> : !s64i, #cir.int<0> : !s64i}> : !rec_anon_struct]> : !cir.array<!rec_anon_struct x 2> +// LLVM-CXX11-DAG: @_ZN7PR422765State1mE.const = private constant [2 x { i64, i64 }] [{ {{.*}} @_ZN7PR422765State2f1Ev {{.*}}, i64 0 }, { {{.*}} @_ZN7PR422765State2f2Ev {{.*}}, i64 0 }] +// OGCG-CXX11-DAG: @_ZN7PR422765State1mE.const = private unnamed_addr constant [2 x { i64, i64 }] [{ {{.*}} @_ZN7PR422765State2f1Ev {{.*}}, i64 0 }, { {{.*}} @_ZN7PR422765State2f2Ev {{.*}}, i64 0 }] + +// CIR-CXX2A-DAG: cir.global constant linkonce_odr comdat @_ZN7PR422765State1mE = #cir.const_array<[#cir.const_record<{#cir.global_view<@_ZN7PR422765State2f1Ev> : !s64i, #cir.int<0> : !s64i}> : !rec_anon_struct, #cir.const_record<{#cir.global_view<@_ZN7PR422765State2f2Ev> : !s64i, #cir.int<0> : !s64i}> : !rec_anon_struct]> : !cir.array<!rec_anon_struct x 2> +// LLVM-CXX2A-DAG: @_ZN7PR422765State1mE = linkonce_odr constant [2 x { i64, i64 }] [{ {{.*}} @_ZN7PR422765State2f1Ev {{.*}}, i64 0 }, { {{.*}} @_ZN7PR422765State2f2Ev {{.*}}, i64 0 }], comdat +// OGCG-CXX2A-DAG: @_ZN7PR422765State1mE = linkonce_odr constant [2 x { i64, i64 }] [{ {{.*}} @_ZN7PR422765State2f1Ev {{.*}}, i64 0 }, { {{.*}} @_ZN7PR422765State2f2Ev {{.*}}, i64 0 }], comdat + +// In OGCG, f1() is emitted before the lambda. +// OGCG-LABEL: define{{.*}} i32 @_Z1fi( +// OGCG: call void {{.*}}memcpy{{.*}}({{.*}}, {{.*}} @__const._Z1fi.a +// OGCG: call{{.*}} i32 @"_ZZ1fiENK3$_0clEiM1Ai"(ptr {{.*}}, i32 {{.*}}, i64 0) + +struct A { int x, y[2]; int arr[3]; }; +int f(int i) { + constexpr A a = {1, 2, 3, 4, 5, 6}; + + // CIR-LABEL: cir.func {{.*}}@_ZZ1fiENK3$_0clEiM1Ai( + // LLVM-LABEL: define {{.*}}@"_ZZ1fiENK3$_0clEiM1Ai"( + // OGCG-LABEL: define {{.*}}@"_ZZ1fiENK3$_0clEiM1Ai"( + return [] (int n, int A::*p) { + // CIR: cir.ternary + // LLVM: br i1 + // OGCG: br i1 + return (n >= 0 + // CIR: %[[A:.*]] = cir.get_global @__const._Z1fi.a : !cir.ptr<!rec_A> + // CIR: %[[ARR:.*]] = cir.get_member %[[A]][2] {name = "arr"} : !cir.ptr<!rec_A> -> !cir.ptr<!cir.array<!s32i x 3>> + // CIR: cir.get_element %[[ARR]][%{{.*}} : !s32i] : !cir.ptr<!cir.array<!s32i x 3>> -> !cir.ptr<!s32i> + // LLVM: getelementptr [3 x i32], ptr getelementptr inbounds nuw (i8, ptr @__const._Z1fi.a, i64 12), i32 0, i64 %{{.*}} + // OGCG: getelementptr inbounds [3 x i32], ptr getelementptr inbounds nuw ({{.*}} @__const._Z1fi.a, i32 0, i32 2), i64 0, i64 %{{.*}} + ? a.arr[n] + // CIR: cir.ternary + // LLVM: br i1 + // OGCG: br i1 + : (n == -1 + // CIR: %[[A:.*]] = cir.get_global @__const._Z1fi.a : !cir.ptr<!rec_A> + // CIR: %[[N:.*]] = cir.load{{.*}} %{{.*}} : !cir.ptr<!s64i>, !s64i + // CIR: %[[A_BYTE_PTR:.*]] = cir.cast bitcast %[[A]] : !cir.ptr<!rec_A> -> !cir.ptr<!s8i> + // CIR: cir.ptr_stride %[[A_BYTE_PTR]], %[[N]] : (!cir.ptr<!s8i>, !s64i) -> !cir.ptr<!s8i> + + // LLVM: getelementptr i8, ptr @__const._Z1fi.a, i64 %{{.*}} + // LLVM: load i32 + + // OGCG: getelementptr inbounds i8, ptr @__const._Z1fi.a, i64 %{{.*}} + // OGCG: load i32 + ? a.*p + // CIR: %[[TWO:.*]] = cir.const #cir.int<2> : !s32i + // CIR: %[[N:.*]] = cir.load{{.*}} %{{.*}} : !cir.ptr<!s32i>, !s32i + // CIR: %[[SUB:.*]] = cir.binop(sub, %[[TWO]], %[[N]]) nsw : !s32i + // CIR: %[[A:.*]] = cir.get_global @__const._Z1fi.a : !cir.ptr<!rec_A> + // CIR: %[[Y:.*]] = cir.get_member %[[A]][1] {name = "y"} : !cir.ptr<!rec_A> -> !cir.ptr<!cir.array<!s32i x 2>> + // CIR: cir.get_element %[[Y]][%[[SUB]] : !s32i] : !cir.ptr<!cir.array<!s32i x 2>> -> !cir.ptr<!s32i> + + // LLVM: getelementptr [2 x i32], ptr getelementptr inbounds nuw ({{.*}} @__const._Z1fi.a, i64 4), i32 0, i64 %{{.*}} + // LLVM: load i32 + + // OGCG: getelementptr inbounds [2 x i32], ptr getelementptr inbounds nuw ({{.*}} @__const._Z1fi.a, i32 0, i32 1), i64 0, i64 %{{.*}} + // OGCG: load i32 + : a.y[2 - n])); + }(i, &A::x); +} + +// With CIR, f1() is emitted after the lambda. +// CIR-LABEL: cir.func {{.*}} @_Z1fi( +// CIR: %[[A_INIT:.*]] = cir.const #cir.const_record<{#cir.int<1> : !s32i, #cir.const_array<[#cir.int<2> : !s32i, #cir.int<3> : !s32i]> : !cir.array<!s32i x 2>, #cir.const_array<[#cir.int<4> : !s32i, #cir.int<5> : !s32i, #cir.int<6> : !s32i]> : !cir.array<!s32i x 3>}> : !rec_A +// CIR: cir.store{{.*}} %[[A_INIT]], %{{.*}} +// CIR: %[[ZERO:.*]] = cir.const #cir.int<0> : !s64i +// CIR: cir.call @_ZZ1fiENK3$_0clEiM1Ai({{.*}}, {{.*}}, %[[ZERO]]) + +// LLVM-LABEL: define{{.*}} i32 @_Z1fi( +// LLVM: store %struct.A { i32 1, [2 x i32] [i32 2, i32 3], [3 x i32] [i32 4, i32 5, i32 6] }, ptr %{{.*}} +// LLVM: call i32 @"_ZZ1fiENK3$_0clEiM1Ai"(ptr %{{.*}}, i32 %{{.*}}, i64 0) + +namespace PR42276 { + class State { + void syncDirtyObjects(); + void f1(), f2(); + using l = void (State::*)(); + static constexpr l m[]{&State::f1, &State::f2}; + }; + // CIR-LABEL: cir.func {{.*}} @_ZN7PR422765State16syncDirtyObjectsEv( + // LLVM-LABEL: define{{.*}} void @_ZN7PR422765State16syncDirtyObjectsEv( + // OGCG-LABEL: define{{.*}} void @_ZN7PR422765State16syncDirtyObjectsEv( + void State::syncDirtyObjects() { + for (int i = 0; i < sizeof(m) / sizeof(m[0]); ++i) + // CIR-CXX11: %[[M:.*]] = cir.get_global @_ZN7PR422765State1mE.const : !cir.ptr<!cir.array<!rec_anon_struct x 2>> + // CIR-CXX2A: %[[M:.*]] = cir.get_global @_ZN7PR422765State1mE : !cir.ptr<!cir.array<!rec_anon_struct x 2>> + // CIR: %[[M_I:.*]] = cir.get_element %[[M]][%{{.*}} : !s32i] : !cir.ptr<!cir.array<!rec_anon_struct x 2>> -> !cir.ptr<!rec_anon_struct> + + // LLVM-CXX11: getelementptr [2 x { i64, i64 }], ptr @_ZN7PR422765State1mE.const, i32 0, i64 %{{.*}} + // LLVM-CXX2A: getelementptr [2 x { i64, i64 }], ptr @_ZN7PR422765State1mE, i32 0, i64 %{{.*}} + // OGCG-CXX11: getelementptr inbounds [2 x { i64, i64 }], ptr @_ZN7PR422765State1mE.const, i64 0, i64 %{{.*}} + // OGCG-CXX2A: getelementptr inbounds [2 x { i64, i64 }], ptr @_ZN7PR422765State1mE, i64 0, i64 %{{.*}} + (this->*m[i])(); + } +} >From 64ad72424ddfb23006d0729d0943dd640e6a1f19 Mon Sep 17 00:00:00 2001 From: Andy Kaylor <[email protected]> Date: Wed, 28 Jan 2026 15:47:54 -0800 Subject: [PATCH 2/2] Address review feedback --- clang/lib/CIR/CodeGen/CIRGenTypes.cpp | 5 ++--- clang/lib/CIR/Dialect/Transforms/CXXABILowering.cpp | 4 +--- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/clang/lib/CIR/CodeGen/CIRGenTypes.cpp b/clang/lib/CIR/CodeGen/CIRGenTypes.cpp index bcbfadbac0347..e6ce39cf9571f 100644 --- a/clang/lib/CIR/CodeGen/CIRGenTypes.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenTypes.cpp @@ -508,9 +508,8 @@ mlir::Type CIRGenTypes::convertType(QualType type) { // In classic codegen, arrays of unsized types which it assumes are "arrays // of undefined struct type" are lowered to arrays of i8 "just to have a // concrete type", but in CIR, we can get here with abstract types like - // !cir.method and !cir.data_member, so let's just create an array of the - // type we have and handle it during lowering if we still don't have a sized - // type. + // !cir.method and !cir.data_member, so we just create an array of the type + // and handle it during lowering if we still don't have a sized type. resultType = cir::ArrayType::get(elemTy, arrTy->getSize().getZExtValue()); break; } diff --git a/clang/lib/CIR/Dialect/Transforms/CXXABILowering.cpp b/clang/lib/CIR/Dialect/Transforms/CXXABILowering.cpp index 9ddb71c64fde9..f0e473a6574c7 100644 --- a/clang/lib/CIR/Dialect/Transforms/CXXABILowering.cpp +++ b/clang/lib/CIR/Dialect/Transforms/CXXABILowering.cpp @@ -271,9 +271,7 @@ mlir::LogicalResult CIRGlobalOpABILowering::matchAndRewrite( loweredInit = lowerModule->getCXXABI().lowerMethodConstant( init, layout, *getTypeConverter()); } else if (auto arrTy = mlir::dyn_cast<cir::ArrayType>(ty)) { - cir::ConstArrayAttr init = - mlir::cast_if_present<cir::ConstArrayAttr>(op.getInitialValueAttr()); - assert(init && "array initial value must be a constant array"); + auto init = mlir::cast<cir::ConstArrayAttr>(op.getInitialValueAttr()); auto arrayElts = mlir::cast<ArrayAttr>(init.getElts()); SmallVector<mlir::Attribute> loweredElements; loweredElements.reserve(arrTy.getSize()); _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
