translate-c: Use canonical type of field for flexible array definition

This prevents incorrectly casting an ElaboratedType to ArrayType
if the flexible field is a typedef'ed zero-length array

Fixes #16838
This commit is contained in:
Evan Haas 2023-08-15 22:37:58 -07:00
parent bdf5739c0a
commit 49cb1683ff
2 changed files with 20 additions and 1 deletions

View File

@ -965,6 +965,7 @@ fn buildFlexibleArrayFn(
field_decl: *const clang.FieldDecl,
) TypeError!Node {
const field_qt = field_decl.getType();
const field_qt_canon = qualTypeCanon(field_qt);
const u8_type = try Tag.type.create(c.arena, "u8");
const self_param_name = "self";
@ -979,7 +980,7 @@ fn buildFlexibleArrayFn(
.is_noalias = false,
};
const array_type = @as(*const clang.ArrayType, @ptrCast(field_qt.getTypePtr()));
const array_type = @as(*const clang.ArrayType, @ptrCast(field_qt_canon));
const element_qt = array_type.getElementType();
const element_type = try transQualType(c, scope, element_qt, field_decl.getLocation());

View File

@ -1554,6 +1554,24 @@ pub fn addCases(cases: *tests.RunTranslatedCContext) void {
\\}
, "");
cases.add("Flexible array with typedefed flexible item, issue #16838",
\\#include <stdlib.h>
\\#include <assert.h>
\\typedef int MARKER[0];
\\typedef struct { int x; MARKER y; } Flexible;
\\#define SIZE 10
\\int main(void) {
\\ Flexible *flex = malloc(sizeof(Flexible) + SIZE * sizeof(int));
\\ for (int i = 0; i < SIZE; i++) {
\\ flex->y[i] = i;
\\ }
\\ for (int i = 0; i < SIZE; i++) {
\\ assert(flex->y[i] == i);
\\ }
\\ return 0;
\\}
, "");
cases.add("enum with value that fits in c_uint but not c_int, issue #8003",
\\#include <stdlib.h>
\\enum my_enum {