Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix Issue 23999 - literal suffixes dont mix well with template instan… #15339

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 39 additions & 16 deletions compiler/src/dmd/lexer.d
Original file line number Diff line number Diff line change
Expand Up @@ -1964,7 +1964,7 @@ class Lexer
/***************************************
* Get postfix of string literal.
*/
private void stringPostfix(Token* t) pure @nogc
private void stringPostfix(Token* t)
{
switch (*p)
{
Expand All @@ -1973,6 +1973,13 @@ class Lexer
case 'd':
t.postfix = *p;
p++;
// disallow e.g. `@r"_"dtype var;`
if (!Ccompile && isalpha(*p))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's already in not Ccompile land.

{
const loc = loc();
error(loc, "identifier character cannot follow string `%c` postfix without whitespace",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd say "invalid suffix character %c", because other syntax is not an issue.

p[-1]);
}
break;
default:
t.postfix = 0;
Expand Down Expand Up @@ -2187,6 +2194,7 @@ class Lexer
FLAGS flags = (base == 10) ? FLAGS.decimal : FLAGS.none;
// Parse trailing 'u', 'U', 'l' or 'L' in any combination
const psuffix = p;
LIntegerSuffix:
while (1)
{
FLAGS f;
Expand All @@ -2195,26 +2203,31 @@ class Lexer
case 'U':
case 'u':
f = FLAGS.unsigned;
goto L1;
break;
case 'l':
f = FLAGS.long_;
error("lower case integer suffix 'l' is not allowed. Please use 'L' instead");
goto L1;
goto case;
case 'L':
f = FLAGS.long_;
L1:
p++;
if ((flags & f) && !err)
break;
default:
// disallow e.g. `Foo!5Luvar;`
if (!Ccompile && flags >= FLAGS.unsigned && isalpha(*p))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't need Ccompile check or flags check

{
error("repeated integer suffix `%c`", p[-1]);
err = true;
const loc = loc();
error(loc, "identifier character cannot follow integer `%c` suffix without whitespace",
p[-1]);
}
flags = cast(FLAGS)(flags | f);
continue;
default:
break;
break LIntegerSuffix;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this loop seems more complicated than necessary

}
break;
p++;
if ((flags & f) && !err)
{
error("repeated integer suffix `%c`", p[-1]);
err = true;
}
flags = cast(FLAGS)(flags | f);
continue;
}
if (base == 8 && n >= 8)
{
Expand Down Expand Up @@ -2591,6 +2604,7 @@ class Lexer
imaginary = true;
}

bool gotSuffix = false;
switch (*p)
{
case 'F':
Expand All @@ -2604,7 +2618,7 @@ class Lexer
if (isWellformedString && !isOutOfRange)
isOutOfRange = Port.isFloat64LiteralOutOfRange(sbufptr);
result = TOK.float64Literal;
break;
goto LcheckI;
case 'l':
if (!Ccompile)
error("use 'L' suffix instead of 'l'");
Expand All @@ -2616,13 +2630,22 @@ class Lexer
result = TOK.float80Literal;
break;
}

gotSuffix = true;
LcheckI:
if ((*p == 'i' || *p == 'I') && !Ccompile)
{
if (*p == 'I')
error("use 'i' suffix instead of 'I'");
p++;
imaginary = true;
gotSuffix = true;
}
// disallow e.g. `Foo!5fvar;`
if (!Ccompile && gotSuffix && isalpha(*p))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

don't think it would be a problem if Ccompile was true

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

don't think gotSuffix is needed, just check for invalid suffix alpha

{
const loc = loc();
error(loc, "identifier character cannot follow float `%c` suffix without whitespace",
p[-1]);
}

if (imaginary)
Expand Down
24 changes: 24 additions & 0 deletions compiler/test/fail_compilation/templatesingleparam.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*
REQUIRED_ARGS: -vcolumns
TEST_OUTPUT:
---
fail_compilation/templatesingleparam.d(17,14): Error: identifier character cannot follow string `c` postfix without whitespace
fail_compilation/templatesingleparam.d(18,10): Error: identifier character cannot follow integer `U` suffix without whitespace
fail_compilation/templatesingleparam.d(22,6): Error: identifier character cannot follow string `d` postfix without whitespace
fail_compilation/templatesingleparam.d(23,4): Error: identifier character cannot follow float `f` suffix without whitespace
---
*/
class Foo(alias str) {
enum STR = str;
}

class Bar {
Foo!q{foo}bb; // OK
Foo!q{foo}cc;
Foo!2LUNGS;
}

@`_`int i; // OK
@`_`dint di;
@2flong fi;
@0xFeedObject obj; // not caught