Skip to content

Commit 018656e

Browse files
authored
Fix dlang#21298 - Missing string literal for gcc asm not always diagnosed (dlang#21305)
Modifies the parser to only accept CTFE computed strings when the expression is surrounded by parentheses, so that it doesn't try to parse TOK.colon (`:`) as an AssignExpression. Closes: dlang#21298
1 parent bdd4568 commit 018656e

1 file changed

Lines changed: 45 additions & 8 deletions

File tree

compiler/src/dmd/iasmgcc.d

Lines changed: 45 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ public Statement gccAsmSemantic(GccAsmStatement s, Scope* sc)
6969
s.insn = semanticString(sc, s.insn, "asm instruction template");
7070

7171
if (s.labels && s.outputargs)
72-
error(s.loc, "extended asm statements with labels cannot have output constraints");
72+
p.eSink.error(s.loc, "extended asm statements with labels cannot have output constraints");
7373

7474
// Analyse all input and output operands.
7575
if (s.args)
@@ -143,6 +143,35 @@ public void gccAsmSemantic(CAsmDeclaration ad, Scope* sc)
143143

144144
private:
145145

146+
/***********************************
147+
* Parse an expression that evaluates to a string.
148+
* Grammar:
149+
* | AsmStringExpr:
150+
* | StringLiteral
151+
* | ( AssignExpression )
152+
* Params:
153+
* p = parser state
154+
* Returns:
155+
* the parsed string expression
156+
*/
157+
Expression parseAsmString(Parser)(Parser p)
158+
{
159+
if (p.token.value == TOK.leftParenthesis)
160+
{
161+
p.nextToken();
162+
Expression insn = p.parseAssignExp();
163+
p.check(TOK.rightParenthesis);
164+
return insn;
165+
}
166+
else if (p.token.value != TOK.string_)
167+
{
168+
p.eSink.error(p.token.loc, "expected string literal or expression in parentheses");
169+
return ErrorExp.get();
170+
}
171+
172+
return p.parsePrimaryExp();
173+
}
174+
146175
/***********************************
147176
* Parse list of extended asm input or output operands.
148177
* Grammar:
@@ -202,7 +231,7 @@ int parseExtAsmOperands(Parser)(Parser p, GccAsmStatement s)
202231
if (p.token.value != TOK.leftParenthesis)
203232
{
204233
arg = p.parseAssignExp();
205-
error(arg.loc, "`%s` must be surrounded by parentheses", arg.toChars());
234+
p.eSink.error(arg.loc, "`%s` must be surrounded by parentheses", arg.toChars());
206235
}
207236
else
208237
{
@@ -352,13 +381,13 @@ Lerror:
352381
* | GotoAsmInstruction
353382
* |
354383
* | BasicAsmInstruction:
355-
* | AssignExpression
384+
* | AsmStringExpr
356385
* |
357386
* | ExtAsmInstruction:
358-
* | AssignExpression : Operands(opt) : Operands(opt) : Clobbers(opt)
387+
* | AsmStringExpr : Operands(opt) : Operands(opt) : Clobbers(opt)
359388
* |
360389
* | GotoAsmInstruction:
361-
* | AssignExpression : : Operands(opt) : Clobbers(opt) : GotoLabels(opt)
390+
* | AsmStringExpr : : Operands(opt) : Clobbers(opt) : GotoLabels(opt)
362391
* Params:
363392
* p = parser state
364393
* s = asm statement to parse
@@ -367,7 +396,10 @@ Lerror:
367396
*/
368397
GccAsmStatement parseGccAsm(Parser)(Parser p, GccAsmStatement s)
369398
{
370-
s.insn = p.parseAssignExp();
399+
s.insn = p.parseAsmString();
400+
if (s.insn.isErrorExp())
401+
return s;
402+
371403
if (p.token.value == TOK.semicolon || p.token.value == TOK.endOfFile)
372404
goto Ldone;
373405

@@ -519,11 +551,11 @@ unittest
519551
} },
520552

521553
// Any CTFE-able string allowed as instruction template.
522-
q{ asm { generateAsm();
554+
q{ asm { (generateAsm);
523555
} },
524556

525557
// Likewise mixins, permissible so long as the result is a string.
526-
q{ asm { mixin(`"repne"`, `~ "scasb"`);
558+
q{ asm { (mixin(`"repne"`, `~ "scasb"`));
527559
} },
528560

529561
// :: token tests
@@ -557,6 +589,11 @@ unittest
557589

558590
// https://issues.dlang.org/show_bug.cgi?id=20593
559591
q{ asm { "instruction" : : "operand" 123; } },
592+
593+
// https://github.com/dlang/dmd/issues/21298
594+
q{ asm { 1; } },
595+
q{ asm { int; } },
596+
q{ asm { : "=r" (i); } },
560597
];
561598

562599
foreach (test; passAsmTests)

0 commit comments

Comments
 (0)