llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clangir Author: Steffen Larsen (steffenlarsen) <details> <summary>Changes</summary> A context holds a single record per kind and name, so parsing a named record returns any earlier definition of that name. When the earlier definition was complete, the parser kept it and silently dropped the new body, so a global declared with a different layout was given the first one. Report the mismatch instead. Assisted-by: Claude Opus 5.5 --- Full diff: https://github.com/llvm/llvm-project/pull/230547.diff 2 Files Affected: - (modified) clang/lib/CIR/Dialect/IR/CIRTypes.cpp (+21-4) - (added) clang/test/CIR/IR/invalid-record-redefinition.cir (+63) ``````````diff diff --git a/clang/lib/CIR/Dialect/IR/CIRTypes.cpp b/clang/lib/CIR/Dialect/IR/CIRTypes.cpp index fe3f41a226e00..596ae844bc698 100644 --- a/clang/lib/CIR/Dialect/IR/CIRTypes.cpp +++ b/clang/lib/CIR/Dialect/IR/CIRTypes.cpp @@ -326,9 +326,17 @@ Type StructType::parse(mlir::AsmParser &parser) { is_class, kindsRef); if (!type) return {}; - if (auto structTy = mlir::dyn_cast<StructType>(type)) - if (structTy.isIncomplete()) + if (auto structTy = mlir::dyn_cast<StructType>(type)) { + if (structTy.isIncomplete()) { structTy.complete(membersRef, packed, kindsRef); + } else if (structTy.getMembers() != membersRef || + structTy.getPacked() != packed || + structTy.getMemberKinds() != kindsRef) { + parser.emitError(loc, "record '") + << name.getValue() << "' redefined with a different body"; + return {}; + } + } assert(!cir::MissingFeatures::astRecordDeclAttr()); } else { parser.emitError(loc, "anonymous records must be complete"); @@ -491,9 +499,18 @@ Type UnionType::parse(mlir::AsmParser &parser) { padding, kindsRef); if (!type) return {}; - if (auto unionTy = mlir::dyn_cast<UnionType>(type)) - if (unionTy.isIncomplete()) + if (auto unionTy = mlir::dyn_cast<UnionType>(type)) { + if (unionTy.isIncomplete()) { unionTy.complete(membersRef, packed, padding, kindsRef); + } else if (unionTy.getMembers() != membersRef || + unionTy.getPacked() != packed || + unionTy.getPadding() != padding || + unionTy.getMemberKinds() != kindsRef) { + parser.emitError(loc, "record '") + << name.getValue() << "' redefined with a different body"; + return {}; + } + } assert(!cir::MissingFeatures::astRecordDeclAttr()); } else { parser.emitError(loc, "anonymous records must be complete"); diff --git a/clang/test/CIR/IR/invalid-record-redefinition.cir b/clang/test/CIR/IR/invalid-record-redefinition.cir new file mode 100644 index 0000000000000..24e41fb3c35ff --- /dev/null +++ b/clang/test/CIR/IR/invalid-record-redefinition.cir @@ -0,0 +1,63 @@ +// RUN: cir-opt %s -verify-diagnostics -split-input-file + +// A context holds a single record per kind and name, so a second definition of +// a name must have the same body as the first. + +!s32i = !cir.int<s, 32> +module { + cir.global external @a = #cir.zero : !cir.struct<"S" {data !s32i}> + // expected-error @below {{record 'S' redefined with a different body}} + cir.global external @b = #cir.zero : !cir.struct<"S" {data !cir.double, data !s32i}> +} + +// ----- + +!s32i = !cir.int<s, 32> +module { + cir.global external @a = #cir.zero : !cir.struct<"S" {data !s32i}> + // expected-error @below {{record 'S' redefined with a different body}} + cir.global external @b = #cir.zero : !cir.struct<"S" packed {data !s32i}> +} + +// ----- + +!u8i = !cir.int<u, 8> +module { + cir.global external @a = #cir.zero : !cir.struct<"S" {data !u8i}> + // expected-error @below {{record 'S' redefined with a different body}} + cir.global external @b = #cir.zero : !cir.struct<"S" {pad !u8i}> +} + +// ----- + +!s32i = !cir.int<s, 32> +module { + cir.global external @a = #cir.zero : !cir.union<"U" {data !s32i}> + // expected-error @below {{record 'U' redefined with a different body}} + cir.global external @b = #cir.zero : !cir.union<"U" {data !s32i, data !cir.float}> +} + +// ----- + +!u8i = !cir.int<u, 8> +!s32i = !cir.int<s, 32> +module { + cir.global external @a = #cir.zero : !cir.union<"U" {data !s32i}> + // expected-error @below {{record 'U' redefined with a different body}} + cir.global external @b = #cir.zero : !cir.union<"U" {data !s32i}, padding = {!cir.array<!u8i x 4>}> +} + +// ----- + +// Still accepted: an identical redefinition, completing a record first seen +// incomplete, and a struct, a class and a union that share a name, which are +// distinct records. +!s32i = !cir.int<s, 32> +module { + cir.global external @a = #cir.zero : !cir.struct<"S" {data !s32i}> + cir.global external @b = #cir.zero : !cir.struct<"S" {data !s32i}> + cir.global external @p = #cir.ptr<null> : !cir.ptr<!cir.struct<"F" incomplete>> + cir.global external @f = #cir.zero : !cir.struct<"F" {data !s32i}> + cir.global external @c = #cir.zero : !cir.struct<class "S" {data !cir.double}> + cir.global external @u = #cir.zero : !cir.union<"S" {data !s32i, data !cir.float}> +} `````````` </details> https://github.com/llvm/llvm-project/pull/230547 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
