authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-05-27 16:43:21+03:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-05-29 12:07:29+03:00
log0274e2f1fd3b7a81344080d532cfd2d384427cd2
treef2e882f35401602799e46b76990a9e9403e3c909
parent36b4658752257a27b1d7db5a4396132784801997

translate-c: check variable types being demoted to opaque


2 files changed, 22 insertions(+), 3 deletions(-)

src/translate_c.zig+7-2
...@@ -793,6 +793,10 @@ fn visitVarDecl(c: *Context, var_decl: *const clang.VarDecl, mangled_name: ?[]co...@@ -793,6 +793,10 @@ fn visitVarDecl(c: *Context, var_decl: *const clang.VarDecl, mangled_name: ?[]co
793 var is_extern = storage_class == .Extern and !has_init;793 var is_extern = storage_class == .Extern and !has_init;
794 var is_export = !is_extern and storage_class != .Static;794 var is_export = !is_extern and storage_class != .Static;
795795
796 if (!is_extern and qualTypeWasDemotedToOpaque(c, qual_type)) {
797 return failDecl(c, var_decl_loc, var_name, "non-extern variable has opaque type", .{});
798 }
799
796 const type_node = transQualTypeMaybeInitialized(c, scope, qual_type, decl_init, var_decl_loc) catch |err| switch (err) {800 const type_node = transQualTypeMaybeInitialized(c, scope, qual_type, decl_init, var_decl_loc) catch |err| switch (err) {
797 error.UnsupportedTranslation, error.UnsupportedType => {801 error.UnsupportedTranslation, error.UnsupportedType => {
798 return failDecl(c, var_decl_loc, var_name, "unable to resolve variable type", .{});802 return failDecl(c, var_decl_loc, var_name, "unable to resolve variable type", .{});
...@@ -1839,6 +1843,7 @@ fn transDeclStmtOne(...@@ -1839,6 +1843,7 @@ fn transDeclStmtOne(
1839 .Var => {1843 .Var => {
1840 const var_decl = @ptrCast(*const clang.VarDecl, decl);1844 const var_decl = @ptrCast(*const clang.VarDecl, decl);
1841 const decl_init = var_decl.getInit();1845 const decl_init = var_decl.getInit();
1846 const loc = decl.getLocation();
18421847
1843 const qual_type = var_decl.getTypeSourceInfo_getType();1848 const qual_type = var_decl.getTypeSourceInfo_getType();
1844 const name = try c.str(@ptrCast(*const clang.NamedDecl, var_decl).getName_bytes_begin());1849 const name = try c.str(@ptrCast(*const clang.NamedDecl, var_decl).getName_bytes_begin());
...@@ -1848,12 +1853,12 @@ fn transDeclStmtOne(...@@ -1848,12 +1853,12 @@ fn transDeclStmtOne(
1848 // This is actually a global variable, put it in the global scope and reference it.1853 // This is actually a global variable, put it in the global scope and reference it.
1849 // `_ = mangled_name;`1854 // `_ = mangled_name;`
1850 return visitVarDecl(c, var_decl, mangled_name);1855 return visitVarDecl(c, var_decl, mangled_name);
1856 } else if (qualTypeWasDemotedToOpaque(c, qual_type)) {
1857 return fail(c, error.UnsupportedTranslation, loc, "local variable has opaque type", .{});
1851 }1858 }
18521859
1853 const is_static_local = var_decl.isStaticLocal();1860 const is_static_local = var_decl.isStaticLocal();
1854 const is_const = qual_type.isConstQualified();1861 const is_const = qual_type.isConstQualified();
1855
1856 const loc = decl.getLocation();
1857 const type_node = try transQualTypeMaybeInitialized(c, scope, qual_type, decl_init, loc);1862 const type_node = try transQualTypeMaybeInitialized(c, scope, qual_type, decl_init, loc);
18581863
1859 var init_node = if (decl_init) |expr|1864 var init_node = if (decl_init) |expr|
test/translate_c.zig+15-1
...@@ -6,6 +6,20 @@ const CrossTarget = std.zig.CrossTarget;...@@ -6,6 +6,20 @@ const CrossTarget = std.zig.CrossTarget;
6pub fn addCases(cases: *tests.TranslateCContext) void {6pub fn addCases(cases: *tests.TranslateCContext) void {
7 const default_enum_type = if (builtin.abi == .msvc) "c_int" else "c_uint";7 const default_enum_type = if (builtin.abi == .msvc) "c_int" else "c_uint";
88
9 cases.add("variables check for opaque demotion",
10 \\struct A {
11 \\ _Atomic int a;
12 \\} a;
13 \\int main(void) {
14 \\ struct A a;
15 \\}
16 , &[_][]const u8{
17 \\pub const struct_A = opaque {};
18 \\pub const a = @compileError("non-extern variable has opaque type");
19 ,
20 \\pub extern fn main() c_int;
21 });
22
9 cases.add("field access is grouped if necessary",23 cases.add("field access is grouped if necessary",
10 \\unsigned long foo(unsigned long x) {24 \\unsigned long foo(unsigned long x) {
11 \\ return ((union{unsigned long _x}){x})._x;25 \\ return ((union{unsigned long _x}){x})._x;
...@@ -3587,7 +3601,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -3587,7 +3601,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
3587 \\ struct my_struct S = {.a = 1, .b = 2};3601 \\ struct my_struct S = {.a = 1, .b = 2};
3588 \\}3602 \\}
3589 , &[_][]const u8{3603 , &[_][]const u8{
3590 \\warning: cannot initialize opaque type3604 \\warning: local variable has opaque type
3591 ,3605 ,
3592 \\warning: unable to translate function, demoted to extern3606 \\warning: unable to translate function, demoted to extern
3593 \\pub extern fn initialize() void;3607 \\pub extern fn initialize() void;