@@ -231,6 +231,7 @@ int parseExtAsmOperands(Parser)(Parser p, GccAsmStatement s)
231231 int numargs = 0 ;
232232
233233 if (p.token.value == TOK .colon ||
234+ p.token.value == TOK .colonColon ||
234235 p.token.value == TOK .semicolon ||
235236 p.token.value == TOK .endOfFile)
236237 return numargs;
@@ -252,7 +253,7 @@ int parseExtAsmOperands(Parser)(Parser p, GccAsmStatement s)
252253 }
253254 else
254255 {
255- p.eSink.error(p.token.loc, " expected identifier after `[`" );
256+ p.eSink.error(p.token.loc, " identifier expected after `[`" );
256257 goto Lerror;
257258 }
258259 // Look for closing `]`
@@ -331,6 +332,7 @@ Expressions* parseExtAsmClobbers(Parser)(Parser p)
331332 Expressions* clobbers;
332333
333334 if (p.token.value == TOK .colon ||
335+ p.token.value == TOK .colonColon ||
334336 p.token.value == TOK .semicolon ||
335337 p.token.value == TOK .endOfFile)
336338 return clobbers;
@@ -387,10 +389,6 @@ Identifiers* parseExtAsmGotoLabels(Parser)(Parser p)
387389{
388390 Identifiers* labels;
389391
390- if (p.token.value == TOK .semicolon ||
391- p.token.value == TOK .endOfFile)
392- return labels;
393-
394392 while (1 )
395393 {
396394 if (p.token.value == TOK .identifier)
@@ -408,7 +406,7 @@ Identifiers* parseExtAsmGotoLabels(Parser)(Parser p)
408406 }
409407 else
410408 {
411- p.eSink.error(p.token.loc, " expected identifier for goto label name, not `%s`" ,
409+ p.eSink.error(p.token.loc, " identifier expected for goto label name, not `%s`" ,
412410 p.token.toChars());
413411 goto Lerror;
414412 }
@@ -451,44 +449,55 @@ GccAsmStatement parseGccAsm(Parser)(Parser p, GccAsmStatement s)
451449 return s;
452450
453451 // No semicolon followed after instruction template, treat as extended asm.
454- if (p.token.value == TOK .semicolon || p.token.value == TOK .endOfFile)
455- goto Ldone;
452+ if (p.token.value == TOK .colon || p.token.value == TOK .colonColon)
453+ {
454+ bool inputs;
455+ bool clobbers;
456+ bool labels;
456457
457- // Look for outputs.
458- if (p.requireToken(TOK .colon))
459- s.outputargs = p.parseExtAsmOperands(s);
460- else
461- return s;
458+ // Look for outputs.
459+ if (p.token.value == TOK .colon)
460+ {
461+ // Skip over the `:` token.
462+ p.nextToken();
463+ // Parse the output operands.
464+ s.outputargs = p.parseExtAsmOperands(s);
465+ }
466+ else if (p.token.value == TOK .colonColon)
467+ inputs = true ;
462468
463- // Look for inputs.
464- if (p.token.value == TOK .colon)
465- {
466- // Skip over the `:` token.
467- p.nextToken();
468- p.parseExtAsmOperands(s);
469- }
470- else
471- goto Ldone;
469+ // Look for inputs.
470+ if (inputs || p.token.value == TOK .colon)
471+ {
472+ // Skip over the `:` or `::` token.
473+ p.nextToken();
474+ // Parse the input operands.
475+ p.parseExtAsmOperands(s);
476+ }
477+ else if (p.token.value == TOK .colonColon)
478+ clobbers = true ;
472479
473- // Look for clobbers.
474- if (p.token.value == TOK .colon)
475- {
476- // Skip over the `:` token.
477- p.nextToken();
478- s.clobbers = p.parseExtAsmClobbers();
479- }
480- else
481- goto Ldone;
480+ // Look for clobbers.
481+ if (clobbers || p.token.value == TOK .colon)
482+ {
483+ // Skip over the `:` or `::` token.
484+ p.nextToken();
485+ // Parse the clobbers.
486+ s.clobbers = p.parseExtAsmClobbers();
487+ }
488+ else if (p.token.value == TOK .colonColon)
489+ labels = true ;
482490
483- // Look for labels.
484- if (p.token.value == TOK .colon)
485- {
486- // Skip over the `:` token.
487- p.nextToken();
488- s.labels = p.parseExtAsmGotoLabels();
491+ // Look for labels.
492+ if (labels || p.token.value == TOK .colon)
493+ {
494+ // Skip over the `:` or `::` token.
495+ p.nextToken();
496+ // Parse the labels.
497+ s.labels = p.parseExtAsmGotoLabels();
498+ }
489499 }
490500
491- Ldone:
492501 if (p.token.value == TOK .endOfFile)
493502 assert (global.errors);
494503 else
@@ -624,6 +633,7 @@ unittest
624633 q{ asm { " " :: : " memory" ; } },
625634 q{ asm { " " : :: " memory" ; } },
626635 q{ asm { " " ::: " memory" ; } },
636+ q{ asm { " " :::: label; } },
627637 ];
628638
629639 immutable string [] failAsmTests = [
@@ -648,6 +658,12 @@ unittest
648658 q{ asm { " " , " " ;
649659 } },
650660
661+ // Identifier expected, not ';'
662+ q{ asm { " " : ::: ; } },
663+ q{ asm { " " :: :: ; } },
664+ q{ asm { " " ::: : ; } },
665+ q{ asm { " " :::: ; } },
666+
651667 // https://issues.dlang.org/show_bug.cgi?id=20593
652668 q{ asm { " instruction" : : " operand" 123 ; } },
653669
0 commit comments