8000 [CIR][IR] Relax get_member verifier for incomplete types (#269) · llvm/clangir@a2bfdbb · GitHub
[go: up one dir, main page]

Skip to content

Commit a2bfdbb

Browse files
gitoleglanza
authored andcommitted
[CIR][IR] Relax get_member verifier for incomplete types (#269)
This is a suggestion to relax the existing verification even more than we did it in PR #257. Here we also skip verification if a field on the given index is also of incomplete type - and we can not compare it with the result type of the operation. Now the next code fails with type mismatch error: ``` typedef struct Node { struct Node* next; } NodeStru; void foo(NodeStru* a) { a->next = 0; } ``` because the result type is kind of full and the type of field is not (for the reasons discussed in #256). Basically, the problem is in the `GetMemberOp` result type generated as following (via `CIRGenTypes::convertType`) `!cir.ptr<!cir.struct<struct "Node" {!cir.ptr<!cir.struct<struct "Node" incomplete #cir.record.decl.ast>>} #cir.record.decl.ast>>` where the field type at index differs from the record type - compare with `!cir.ptr<!cir.struct<struct "Node" incomplete #cir.record.decl.ast>>` We just slightly relax the previous solution in #257 - and the compilation won't fail in the case of recursive types. Well, if there are some other thoughts?
1 parent c47ec75 commit a2bfdbb

File tree

2 files changed

+28
-3
lines changed

2 files changed

+28
-3
lines changed

clang/lib/CIR/Dialect/IR/CIRDialect.cpp

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2412,6 +2412,14 @@ LogicalResult MemCpyOp::verify() {
24122412
return mlir::success();
24132413
}
24142414

2415+
static bool isIncompleteType(mlir::Type typ) {
2416+
if (auto ptr = typ.dyn_cast<PointerType>())
2417+
return isIncompleteType(ptr.getPointee());
2418+
else if (auto rec = typ.dyn_cast<StructType>())
2419+
return !rec.getBody();
2420+
return false;
2421+
}
2422+
24152423
//===----------------------------------------------------------------------===//
24162424
// GetMemberOp Definitions
24172425
//===----------------------------------------------------------------------===//
@@ -2424,16 +2432,20 @@ LogicalResult GetMemberOp::verify() {
24242432

24252433
// FIXME: currently we bypass typechecking of incomplete types due to errors
24262434
// in the codegen process. This should be removed once the codegen is fixed.
2427-
if (!recordTy.getBody())
2435+
if (isIncompleteType(recordTy))
24282436
return mlir::success();
24292437

24302438
if (recordTy.getMembers().size() <= getIndex())
24312439
return emitError() << "member index out of bounds";
24322440

24332441
// FIXME(cir): member type check is disabled for classes as the codegen for
24342442
// these still need to be patched.
2435-
if (!recordTy.isClass() &&
2436-
recordTy.getMembers()[getIndex()] != getResultTy().getPointee())
2443+
// Also we bypass the typechecking for the fields of incomplete types.
2444+
bool shouldSkipMemberTypeMismatch =
2445+
recordTy.isClass() || isIncompleteType(recordTy.getMembers()[getIndex()]);
2446+
2447+
if (!shouldSkipMemberTypeMismatch
2448+
&& recordTy.getMembers()[getIndex()] != getResultTy().getPointee())
24372449
return emitError() << "member type mismatch";
24382450

24392451
return mlir::success();

clang/test/CIR/CodeGen/struct.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,18 @@ struct Foo {
1212
struct Bar z;
1313
};
1414

15+
// Recursive type
16+
typedef struct Node {
17+
struct Node* next;
18+
} NodeStru;
19+
1520
void baz(void) {
1621
struct Bar b;
1722
struct Foo f;
1823
}
1924

25+
// CHECK-DAG: !ty_22Node22 = !cir.struct<struct "Node" incomplete #cir.record.decl.ast>
26+
// CHECK-DAG: !ty_22Node221 = !cir.struct<struct "Node" {!cir.ptr<!ty_22Node22>} #cir.record.decl.ast>
2027
// CHECK-DAG: !ty_22Bar22 = !cir.struct<struct "Bar" {!s32i, !s8i}>
2128
// CHECK-DAG: !ty_22Foo22 = !cir.struct<struct "Foo" {!s32i, !s8i, !ty_22Bar22}>
2229
// CHECK-DAG: module {{.*}} {
@@ -78,3 +85,9 @@ struct Bar shouldGenerateAndAccessStructArrays(void) {
7885
// CHECK-DAG: %[[#DARR:]] = cir.cast(array_to_ptrdecay, %{{.+}} : !cir.ptr<!cir.array<!ty_22Bar22 x 1>>), !cir.ptr<!ty_22Bar22>
7986
// CHECK-DAG: %[[#ELT:]] = cir.ptr_stride(%[[#DARR]] : !cir.ptr<!ty_22Bar22>, %[[#STRIDE]] : !s32i), !cir.ptr<!ty_22Bar22>
8087
// CHECK-DAG: cir.copy %[[#ELT]] to %{{.+}} : !cir.ptr<!ty_22Bar22>
88+
89+
// CHECK-DAG: cir.func @useRecursiveType
90+
// CHECK-DAG: cir.get_member {{%.}}[0] {name = "next"} : !cir.ptr<!ty_22Node221> -> !cir.ptr<!cir.ptr<!ty_22Node221>>
91+
void useRecursiveType(NodeStru* a) {
92+
a->next = 0;
93+
}

0 commit comments

Comments
 (0)
0