Commit 49cb1683ff

Evan Haas <evan@lagerdata.com>
2023-08-16 07:37:58
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
1 parent bdf5739
Changed files (2)
src/translate_c.zig
@@ -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());
 
test/run_translated_c.zig
@@ -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 {