Commit e863204c47

LemonBoy <thatlemon@gmail.com>
2021-05-04 19:29:25
zig fmt: Fix edge case in inline asm parsing
The presence of a trailing comma in the single and only input/output declaration confused the parser and made zig fmt discard any element placed after the comma.
1 parent 70a9a3a
Changed files (2)
lib/std/zig/ast.zig
@@ -1979,20 +1979,26 @@ pub const Tree = struct {
             // asm ("foo" :: [_] "" (y) : "a", "b");
             const last_input = result.inputs[result.inputs.len - 1];
             const rparen = tree.lastToken(last_input);
-            if (token_tags[rparen + 1] == .colon and
-                token_tags[rparen + 2] == .string_literal)
+            var i = rparen + 1;
+            // Allow a (useless) comma right after the closing parenthesis.
+            if (token_tags[i] == .comma) i += 1;
+            if (token_tags[i] == .colon and
+                token_tags[i + 1] == .string_literal)
             {
-                result.first_clobber = rparen + 2;
+                result.first_clobber = i + 1;
             }
         } else {
             // asm ("foo" : [_] "" (x) :: "a", "b");
             const last_output = result.outputs[result.outputs.len - 1];
             const rparen = tree.lastToken(last_output);
-            if (token_tags[rparen + 1] == .colon and
-                token_tags[rparen + 2] == .colon and
-                token_tags[rparen + 3] == .string_literal)
+            var i = rparen + 1;
+            // Allow a (useless) comma right after the closing parenthesis.
+            if (token_tags[i] == .comma) i += 1;
+            if (token_tags[i] == .colon and
+                token_tags[i + 1] == .colon and
+                token_tags[i + 2] == .string_literal)
             {
-                result.first_clobber = rparen + 3;
+                result.first_clobber = i + 2;
             }
         }
 
lib/std/zig/parser_test.zig
@@ -4,6 +4,38 @@
 // The MIT license requires this copyright notice to be included in all copies
 // and substantial portions of the software.
 
+test "zig fmt: preserves clobbers in inline asm with stray comma" {
+    try testTransform(
+        \\fn foo() void {
+        \\    asm volatile (""
+        \\        : [_] "" (-> type),
+        \\        :
+        \\        : "clobber"
+        \\    );
+        \\    asm volatile (""
+        \\        :
+        \\        : [_] "" (type),
+        \\        : "clobber"
+        \\    );
+        \\}
+        \\
+    ,
+        \\fn foo() void {
+        \\    asm volatile (""
+        \\        : [_] "" (-> type)
+        \\        :
+        \\        : "clobber"
+        \\    );
+        \\    asm volatile (""
+        \\        :
+        \\        : [_] "" (type)
+        \\        : "clobber"
+        \\    );
+        \\}
+        \\
+    );
+}
+
 test "zig fmt: respect line breaks in struct field value declaration" {
     try testCanonical(
         \\const Foo = struct {