@@ -469,6 +469,7 @@ pub fn translate(
469
469
context .decl_table .deinit (gpa );
470
470
context .alias_list .deinit ();
471
471
context .global_names .deinit (gpa );
472
+ context .weak_global_names .deinit (gpa );
472
473
context .opaque_demotes .deinit (gpa );
473
474
context .unnamed_typedefs .deinit (gpa );
474
475
context .typedefs .deinit (gpa );
@@ -610,7 +611,9 @@ fn transDecl(c: *Context, scope: *Scope, decl: NodeIndex) !void {
610
611
= > {
611
612
try transVarDecl (c , decl );
612
613
},
613
- .static_assert = > try warn (c , & c .global_scope .base , c .tokenIndex (decl ) orelse 0 , "ignoring _Static_assert declaration" , .{}),
614
+ .static_assert = > {
615
+ try transStaticAssert (c , & c .global_scope .base , decl );
616
+ },
614
617
else = > unreachable ,
615
618
}
616
619
}
@@ -991,6 +994,40 @@ fn transEnumDecl(c: *Context, scope: *Scope, enum_decl: *const Type.Enum, field_
991
994
}
992
995
}
993
996
997
+ fn transStaticAssert (c : * Context , scope : * Scope , static_assert_node : NodeIndex ) Error ! void {
998
+ const node_data = c .tree .nodes .items (.data )[@intFromEnum (static_assert_node )];
999
+
1000
+ const condition = c .transExpr (node_data .bin .lhs , .used ) catch | err | switch (err ) {
1001
+ error .UnsupportedTranslation , error .UnsupportedType = > {
1002
+ return try warn (c , & c .global_scope .base , c .tokenIndex (node_data .bin .lhs ).? , "unable to translate _Static_assert condition" , .{});
1003
+ },
1004
+ error .OutOfMemory = > | e | return e ,
1005
+ };
1006
+
1007
+ // generate @compileError message that matches C compiler output
1008
+ const diagnostic = if (node_data .bin .rhs != .none ) str : {
1009
+ // Aro guarantees this to be a string literal.
1010
+ const str_val = c .tree .value_map .get (node_data .bin .rhs ).? ;
1011
+ const str_ty = c .tree .nodes .items (.ty )[@intFromEnum (node_data .bin .rhs )];
1012
+
1013
+ const bytes = c .comp .interner .get (str_val .ref ()).bytes ;
1014
+ var buf = std .ArrayList (u8 ).init (c .gpa );
1015
+ defer buf .deinit ();
1016
+
1017
+ try buf .appendSlice ("\" static assertion failed \\ " );
1018
+
1019
+ try buf .ensureUnusedCapacity (bytes .len );
1020
+ try aro .Value .printString (bytes , str_ty , c .comp , buf .writer ());
1021
+ _ = buf .pop (); // printString adds a terminating " so we need to remove it
1022
+ try buf .appendSlice ("\\ \"\" " );
1023
+
1024
+ break :str try ZigTag .string_literal .create (c .arena , try c .arena .dupe (u8 , buf .items ));
1025
+ } else try ZigTag .string_literal .create (c .arena , "\" static assertion failed\" " );
1026
+
1027
+ const assert_node = try ZigTag .static_assert .create (c .arena , .{ .lhs = condition , .rhs = diagnostic });
1028
+ try scope .appendNode (assert_node );
1029
+ }
1030
+
994
1031
fn getTypeStr (c : * Context , ty : Type ) ! []const u8 {
995
1032
var buf : std .ArrayListUnmanaged (u8 ) = .empty ;
996
1033
defer buf .deinit (c .gpa );
@@ -1316,16 +1353,21 @@ fn transFnType(
1316
1353
return ZigNode .initPayload (& payload .base );
1317
1354
}
1318
1355
1319
- fn transStmt (c : * Context , node : NodeIndex ) TransError ! ZigNode {
1320
- _ = c ;
1321
- _ = node ;
1322
- return error .UnsupportedTranslation ;
1356
+ fn transStmt (c : * Context , scope : * Scope , stmt : NodeIndex ) TransError ! ZigNode {
1357
+ const node_tags = c .tree .nodes .items (.tag );
1358
+ switch (node_tags [@intFromEnum (stmt )]) {
1359
+ .static_assert = > {
1360
+ try transStaticAssert (c , scope , stmt );
1361
+ return ZigTag .declaration .init ();
1362
+ },
1363
+ else = > return fail (c , error .UnsupportedTranslation , c .tokenIndex (stmt ).? , "TODO implement translation of stmt {s}" , .{@tagName (node_tags [@intFromEnum (stmt )])}),
1364
+ }
1323
1365
}
1324
1366
1325
1367
fn transCompoundStmtInline (c : * Context , compound : NodeIndex , block : * Scope.Block ) TransError ! void {
1326
1368
const stmts = c .tree .childNodes (compound );
1327
1369
for (stmts ) | stmt | {
1328
- const result = try transStmt (c , stmt );
1370
+ const result = try transStmt (c , & block . base , stmt );
1329
1371
switch (result .tag ()) {
1330
1372
.declaration , .empty_block = > {},
1331
1373
else = > try block .statements .append (result ),
0 commit comments