mirror of
https://github.com/dlang/dmd.git
synced 2025-04-26 13:10:12 +03:00
Fix aliasing function type returning a Type with TypeSuffixes (#15805)
Fix Issue 24206 - Can't alias a function type that returns a type with a TypeSuffix Add isTypeSuffix() function. This also means a function type with a TypeCtor is now deprecated, just like a function pointer type with a TypeCtor. This gives a better error message and simplifies the code.
This commit is contained in:
parent
84ca093464
commit
57e36ee22d
5 changed files with 56 additions and 46 deletions
|
@ -4878,30 +4878,11 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
|
|||
AST.Declaration v;
|
||||
AST.Dsymbol s;
|
||||
|
||||
// try to parse function type:
|
||||
// TypeCtors? BasicType ( Parameters ) MemberFunctionAttributes
|
||||
bool attributesAppended;
|
||||
const StorageClass funcStc = parseTypeCtor();
|
||||
Token* tlu = &token;
|
||||
Token* tk;
|
||||
if (token.value != TOK.function_ &&
|
||||
token.value != TOK.delegate_ &&
|
||||
isBasicType(&tlu) && tlu &&
|
||||
tlu.value == TOK.leftParenthesis)
|
||||
{
|
||||
AST.Type tret = parseBasicType();
|
||||
auto parameterList = parseParameterList(null);
|
||||
|
||||
parseAttributes();
|
||||
if (udas)
|
||||
error("user-defined attributes not allowed for `alias` declarations");
|
||||
|
||||
attributesAppended = true;
|
||||
storage_class = appendStorageClass(storage_class, funcStc);
|
||||
AST.Type tf = new AST.TypeFunction(parameterList, tret, link, storage_class);
|
||||
v = new AST.AliasDeclaration(loc, ident, tf);
|
||||
}
|
||||
else if (token.value == TOK.function_ ||
|
||||
// function literal?
|
||||
if (token.value == TOK.function_ ||
|
||||
token.value == TOK.delegate_ ||
|
||||
token.value == TOK.leftParenthesis &&
|
||||
skipAttributes(peekPastParen(&token), &tk) &&
|
||||
|
@ -4911,10 +4892,10 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
|
|||
token.value == TOK.ref_ && peekNext() == TOK.leftParenthesis &&
|
||||
skipAttributes(peekPastParen(peek(&token)), &tk) &&
|
||||
(tk.value == TOK.goesTo || tk.value == TOK.leftCurly) ||
|
||||
token.value == TOK.auto_ && peekNext() == TOK.ref_ &&
|
||||
peekNext2() == TOK.leftParenthesis &&
|
||||
skipAttributes(peekPastParen(peek(peek(&token))), &tk) &&
|
||||
(tk.value == TOK.goesTo || tk.value == TOK.leftCurly)
|
||||
token.value == TOK.auto_ &&
|
||||
(peekNext() == TOK.leftParenthesis || // for better error
|
||||
peekNext() == TOK.ref_ &&
|
||||
peekNext2() == TOK.leftParenthesis)
|
||||
)
|
||||
{
|
||||
// function (parameters) { statements... }
|
||||
|
@ -4955,21 +4936,46 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
|
|||
}
|
||||
else
|
||||
{
|
||||
parseAttributes();
|
||||
// type
|
||||
parseAttributes();
|
||||
if (udas)
|
||||
error("user-defined attributes not allowed for `alias` declarations");
|
||||
|
||||
auto t = parseType();
|
||||
auto t = parseBasicType();
|
||||
t = parseTypeSuffixes(t);
|
||||
if (token.value == TOK.identifier)
|
||||
{
|
||||
error("unexpected identifier `%s` after `%s`",
|
||||
token.ident.toChars(), t.toChars());
|
||||
nextToken();
|
||||
}
|
||||
else if (token.value == TOK.leftParenthesis)
|
||||
{
|
||||
// function type:
|
||||
// StorageClasses Type ( Parameters ) MemberFunctionAttributes
|
||||
auto parameterList = parseParameterList(null);
|
||||
udas = null;
|
||||
parseStorageClasses(storage_class, link, setAlignment, ealign, udas, linkloc);
|
||||
if (udas)
|
||||
error("user-defined attributes not allowed for `alias` declarations");
|
||||
|
||||
attributesAppended = true;
|
||||
// Note: method types can have a TypeCtor attribute
|
||||
storage_class = appendStorageClass(storage_class, funcStc);
|
||||
t = new AST.TypeFunction(parameterList, t, link, storage_class);
|
||||
}
|
||||
|
||||
// Disallow meaningless storage classes on type aliases
|
||||
if (storage_class)
|
||||
{
|
||||
// Don't raise errors for STC that are part of a function/delegate type, e.g.
|
||||
// `alias F = ref pure nothrow @nogc @safe int function();`
|
||||
auto tp = t.isTypePointer;
|
||||
const isFuncType = (tp && tp.next.isTypeFunction) || t.isTypeDelegate;
|
||||
const remStc = isFuncType ? (storage_class & ~STC.FUNCATTR) : storage_class;
|
||||
const remStc = t.isTypeFunction ?
|
||||
storage_class & ~(STC.FUNCATTR | STC.TYPECTOR) : {
|
||||
auto tp = t.isTypePointer;
|
||||
const isFuncType = (tp && tp.next.isTypeFunction) || t.isTypeDelegate;
|
||||
return isFuncType ? (storage_class & ~STC.FUNCATTR) : storage_class;
|
||||
}();
|
||||
|
||||
if (remStc)
|
||||
{
|
||||
|
@ -7217,6 +7223,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
|
|||
return false;
|
||||
}
|
||||
|
||||
// pt = test token. If found, pt is set to the token after BasicType
|
||||
private bool isBasicType(Token** pt)
|
||||
{
|
||||
// This code parallels parseBasicType()
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
// function type aliases
|
||||
module issue16020;
|
||||
|
||||
alias F1 = const(int)(); const(int) f1(){return 42;}
|
||||
|
@ -36,4 +37,8 @@ alias Specialized = FunTemplate!int;
|
|||
alias Compared = void(int);
|
||||
static assert(is(Specialized == Compared));
|
||||
|
||||
void main() {}
|
||||
// type suffixes
|
||||
alias FT = const(int)*();
|
||||
static assert(is(FT* == const(int)* function()));
|
||||
alias FT2 = int*[2]() pure;
|
||||
static assert(is(FT2* == int*[2] function() pure));
|
||||
|
|
|
@ -1,16 +1,12 @@
|
|||
/+ TEST_OUTPUT:
|
||||
---
|
||||
fail_compilation/fail21243.d(16): Error: found `(` when expecting `ref` and function literal following `auto`
|
||||
fail_compilation/fail21243.d(16): Error: semicolon expected following auto declaration, not `int`
|
||||
fail_compilation/fail21243.d(16): Error: semicolon needed to end declaration of `x` instead of `)`
|
||||
fail_compilation/fail21243.d(16): Error: declaration expected, not `)`
|
||||
fail_compilation/fail21243.d(17): Error: `auto` can only be used as part of `auto ref` for function literal return values
|
||||
fail_compilation/fail21243.d(18): Error: basic type expected, not `(`
|
||||
fail_compilation/fail21243.d(18): Error: function declaration without return type. (Note that constructors are always named `this`)
|
||||
fail_compilation/fail21243.d(18): Deprecation: storage class `auto` has no effect in type aliases
|
||||
fail_compilation/fail21243.d(18): Error: semicolon expected to close `alias` declaration, not `=>`
|
||||
fail_compilation/fail21243.d(18): Error: declaration expected, not `=>`
|
||||
fail_compilation/fail21243.d(19): Error: `auto` can only be used as part of `auto ref` for function literal return values
|
||||
fail_compilation/fail21243.d(12): Error: found `(` when expecting `ref` and function literal following `auto`
|
||||
fail_compilation/fail21243.d(12): Error: semicolon expected following auto declaration, not `int`
|
||||
fail_compilation/fail21243.d(12): Error: semicolon needed to end declaration of `x` instead of `)`
|
||||
fail_compilation/fail21243.d(12): Error: declaration expected, not `)`
|
||||
fail_compilation/fail21243.d(13): Error: `auto` can only be used as part of `auto ref` for function literal return values
|
||||
fail_compilation/fail21243.d(14): Error: `auto` can only be used as part of `auto ref` for function literal return values
|
||||
fail_compilation/fail21243.d(15): Error: `auto` can only be used as part of `auto ref` for function literal return values
|
||||
---
|
||||
+/
|
||||
auto a = auto (int x) => x;
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
/*
|
||||
TEST_OUTPUT:
|
||||
---
|
||||
fail_compilation/issue16020.d(12): Error: user-defined attributes not allowed for `alias` declarations
|
||||
fail_compilation/issue16020.d(13): Error: semicolon expected to close `alias` declaration, not `(`
|
||||
fail_compilation/issue16020.d(13): Error: declaration expected, not `(`
|
||||
fail_compilation/issue16020.d(13): Error: user-defined attributes not allowed for `alias` declarations
|
||||
fail_compilation/issue16020.d(14): Error: semicolon expected to close `alias` declaration, not `(`
|
||||
fail_compilation/issue16020.d(14): Error: declaration expected, not `(`
|
||||
fail_compilation/issue16020.d(15): Deprecation: storage class `final` has no effect in type aliases
|
||||
---
|
||||
*/
|
||||
module issue16020;
|
||||
|
@ -11,3 +12,4 @@ module issue16020;
|
|||
struct UDA{}
|
||||
alias Fun = @UDA void();
|
||||
alias FunTemplate = void(T)(T t);
|
||||
alias F2 = final int();
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
/*
|
||||
TEST_OUTPUT:
|
||||
---
|
||||
fail_compilation/test22048.d(10): Error: unexpected identifier `p` in declarator
|
||||
fail_compilation/test22048.d(10): Error: unexpected identifier `p` after `int`
|
||||
---
|
||||
*/
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue