llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang @llvm/pr-subscribers-clangir Author: Henrich Lauko (xlauko) <details> <summary>Changes</summary> !cir.void has no data layout, so a record or array that holds one has none either. The verifiers accepted such types, and the first size query crashed. CallConvLowering hit a DataLayout fatal error on a union argument, and LowerToLLVM asserted in LLVMStructType::setBody. The record and array verifiers now reject void, so no consumer has to guard against it. CallConvLowering still accepts void as a parameter type, which the x86_64 classifier ignores. Assisted-by: Claude Code (Claude Opus 5.5) --- Full diff: https://github.com/llvm/llvm-project/pull/233898.diff 4 Files Affected: - (modified) clang/include/clang/CIR/Dialect/IR/CIRTypeConstraints.td (+4) - (modified) clang/include/clang/CIR/Dialect/IR/CIRTypes.td (+1-1) - (modified) clang/lib/CIR/Dialect/IR/CIRTypes.cpp (+17) - (added) clang/test/CIR/IR/invalid-void-member.cir (+31) ``````````diff diff --git a/clang/include/clang/CIR/Dialect/IR/CIRTypeConstraints.td b/clang/include/clang/CIR/Dialect/IR/CIRTypeConstraints.td index 97d7b30236b82..d294f6a9a0371 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIRTypeConstraints.td +++ b/clang/include/clang/CIR/Dialect/IR/CIRTypeConstraints.td @@ -281,6 +281,10 @@ class CIR_PtrToAnyOf<list<Type> types, string summary = ""> def CIR_AnyVoidType : CIR_TypeBase<"::cir::VoidType", "void type">, BuildableType<"$_builder.getType<" # cppType # ">()">; +// Void has no layout, so neither does an array of it. +def CIR_ArrayElementType + : Type<Neg<CIR_AnyVoidType.predicate>, "any type except void">; + // Void pointer type constraints def CIR_VoidPtrType : CIR_PtrTo<CIR_AnyVoidType, "void type">; diff --git a/clang/include/clang/CIR/Dialect/IR/CIRTypes.td b/clang/include/clang/CIR/Dialect/IR/CIRTypes.td index 366a4669c3a56..9cdb493a569be 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIRTypes.td +++ b/clang/include/clang/CIR/Dialect/IR/CIRTypes.td @@ -456,7 +456,7 @@ def CIR_ArrayType : CIR_Type<"Array", "array", [ `!cir.array` represents C/C++ constant arrays. }]; - let parameters = (ins "mlir::Type":$elementType, "uint64_t":$size); + let parameters = (ins CIR_ArrayElementType:$elementType, "uint64_t":$size); let builders = [ TypeBuilderWithInferredContext<(ins diff --git a/clang/lib/CIR/Dialect/IR/CIRTypes.cpp b/clang/lib/CIR/Dialect/IR/CIRTypes.cpp index ecdd5fd8584d0..4ccad854c7b46 100644 --- a/clang/lib/CIR/Dialect/IR/CIRTypes.cpp +++ b/clang/lib/CIR/Dialect/IR/CIRTypes.cpp @@ -171,6 +171,17 @@ verifyRecordMemberKinds(function_ref<mlir::InFlightDiagnostic()> emitError, return mlir::success(); } +/// A void member has no layout, so a record holding one has none either. +static mlir::LogicalResult +verifyRecordMemberTypes(function_ref<mlir::InFlightDiagnostic()> emitError, + llvm::ArrayRef<mlir::Type> members) { + for (auto [idx, memberTy] : llvm::enumerate(members)) + if (mlir::isa<cir::VoidType>(memberTy)) + return emitError() << "record member at index " << idx + << " cannot be void"; + return mlir::success(); +} + /// The keywords that spell a member kind. A union's tail-padding slot probes /// for one of these to reject it, since that slot is not a member. static const llvm::StringRef memberKindMarks[] = {"data", "pad", "empty", @@ -349,6 +360,8 @@ mlir::LogicalResult StructType::verify( bool packed, llvm::ArrayRef<RecordMemberKind> member_kinds, bool is_class) { if (name && name.getValue().empty()) return emitError() << "identified records cannot have an empty name"; + if (failed(verifyRecordMemberTypes(emitError, members))) + return mlir::failure(); return verifyRecordMemberKinds(emitError, members.size(), member_kinds); } @@ -524,6 +537,10 @@ UnionType::verify(function_ref<mlir::InFlightDiagnostic()> emitError, // padding slot. if (llvm::is_contained(member_kinds, RecordMemberKind::Pad)) return emitError() << "a union member cannot be marked pad"; + if (failed(verifyRecordMemberTypes(emitError, members))) + return mlir::failure(); + if (mlir::isa_and_nonnull<cir::VoidType>(padding)) + return emitError() << "union padding cannot be void"; // Every variant starts at offset zero, so a bit-field variant is an access // unit of its own. There is no run for a zero-width bit-field to end, so a // variant always has storage. diff --git a/clang/test/CIR/IR/invalid-void-member.cir b/clang/test/CIR/IR/invalid-void-member.cir new file mode 100644 index 0000000000000..e5eb295a3efa1 --- /dev/null +++ b/clang/test/CIR/IR/invalid-void-member.cir @@ -0,0 +1,31 @@ +// RUN: cir-opt %s -verify-diagnostics -split-input-file + +// Void has no layout, so it cannot be a member, element or padding. + +!s32i = !cir.int<s, 32> +// expected-error @below {{record member at index 1 cannot be void}} +!rec_S = !cir.struct<"S" {data !s32i, data !cir.void}> + +module {} + +// ----- + +// expected-error @below {{record member at index 0 cannot be void}} +!rec_U = !cir.union<"U" {data !cir.void}> + +module {} + +// ----- + +!s32i = !cir.int<s, 32> +// expected-error @below {{union padding cannot be void}} +!rec_U = !cir.union<"U" {data !s32i}, padding = {!cir.void}> + +module {} + +// ----- + +// expected-error @below {{failed to verify 'elementType': any type except void}} +!arr = !cir.array<!cir.void x 4> + +module {} `````````` </details> https://github.com/llvm/llvm-project/pull/233898 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
