mirror of
https://github.com/dlang/dmd.git
synced 2025-04-27 21:51:03 +03:00
Require adjacent auto ref
keywords
This commit is contained in:
parent
dfcee8d88b
commit
ae2dc11619
5 changed files with 49 additions and 9 deletions
18
changelog/dmd.auto-ref-adjacent.dd
Normal file
18
changelog/dmd.auto-ref-adjacent.dd
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
`auto ref` variables must have adjacent keywords `auto` and `ref`
|
||||||
|
|
||||||
|
It's now deprecated to declare `auto ref` parameters without putting those two keywords next to eachother.
|
||||||
|
This way it's clear that `auto ref` semantics are intended, rather than `ref` and `auto` semantics separately.
|
||||||
|
For the newly introduced `ref` local / global variables, it's an error immediately.
|
||||||
|
|
||||||
|
---
|
||||||
|
void t()(ref const auto int x) // Deprecation
|
||||||
|
{
|
||||||
|
ref auto y = x; // Error
|
||||||
|
}
|
||||||
|
|
||||||
|
// Correction:
|
||||||
|
void t()(auto ref const int x)
|
||||||
|
{
|
||||||
|
auto ref y = x;
|
||||||
|
}
|
||||||
|
---
|
|
@ -616,7 +616,13 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
|
||||||
dsym.storage_class |= ad.storage_class & STC.TYPECTOR;
|
dsym.storage_class |= ad.storage_class & STC.TYPECTOR;
|
||||||
|
|
||||||
if ((dsym.storage_class & STC.auto_) && (dsym.storage_class & STC.ref_))
|
if ((dsym.storage_class & STC.auto_) && (dsym.storage_class & STC.ref_))
|
||||||
|
{
|
||||||
|
if (!(dsym.storage_class & STC.autoref))
|
||||||
|
{
|
||||||
|
.error(dsym.loc, "%s `%s` - `auto ref` variable must have `auto` and `ref` adjacent", dsym.kind, dsym.toChars());
|
||||||
dsym.storage_class |= STC.autoref;
|
dsym.storage_class |= STC.autoref;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* If auto type inference, do the inference
|
/* If auto type inference, do the inference
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -651,6 +651,8 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
|
||||||
|
|
||||||
case TOK.auto_:
|
case TOK.auto_:
|
||||||
stc = STC.auto_;
|
stc = STC.auto_;
|
||||||
|
if (peekNext() == TOK.ref_)
|
||||||
|
stc |= STC.autoref;
|
||||||
goto Lstc;
|
goto Lstc;
|
||||||
|
|
||||||
case TOK.scope_:
|
case TOK.scope_:
|
||||||
|
@ -2935,6 +2937,8 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
|
||||||
|
|
||||||
case TOK.auto_:
|
case TOK.auto_:
|
||||||
stc = STC.auto_;
|
stc = STC.auto_;
|
||||||
|
if (peekNext() == TOK.ref_)
|
||||||
|
stc |= STC.autoref;
|
||||||
goto L2;
|
goto L2;
|
||||||
|
|
||||||
case TOK.return_:
|
case TOK.return_:
|
||||||
|
@ -2952,8 +2956,10 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
|
||||||
// if stcx is not a power of 2
|
// if stcx is not a power of 2
|
||||||
if (stcx & (stcx - 1) && !(stcx == (STC.in_ | STC.ref_)))
|
if (stcx & (stcx - 1) && !(stcx == (STC.in_ | STC.ref_)))
|
||||||
error("incompatible parameter storage classes");
|
error("incompatible parameter storage classes");
|
||||||
//if ((storageClass & STC.scope_) && (storageClass & (STC.ref_ | STC.out_)))
|
|
||||||
//error("scope cannot be ref or out");
|
// Deprecated in 2.111
|
||||||
|
if ((storageClass & STC.auto_) && (storageClass & STC.ref_) && !(storageClass & STC.autoref))
|
||||||
|
deprecation("`auto` and `ref` storage classes should be adjacent");
|
||||||
|
|
||||||
const tv = peekNext();
|
const tv = peekNext();
|
||||||
Loc loc;
|
Loc loc;
|
||||||
|
@ -4259,6 +4265,8 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
|
||||||
|
|
||||||
case TOK.auto_:
|
case TOK.auto_:
|
||||||
stc = STC.auto_;
|
stc = STC.auto_;
|
||||||
|
if (peekNext() == TOK.ref_)
|
||||||
|
stc |= STC.autoref;
|
||||||
goto L1;
|
goto L1;
|
||||||
|
|
||||||
case TOK.scope_:
|
case TOK.scope_:
|
||||||
|
@ -5079,7 +5087,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
|
||||||
{
|
{
|
||||||
// function auto ref (parameters) { statements... }
|
// function auto ref (parameters) { statements... }
|
||||||
// delegate auto ref (parameters) { statements... }
|
// delegate auto ref (parameters) { statements... }
|
||||||
stc = STC.auto_ | STC.ref_;
|
stc = STC.auto_ | STC.ref_ | STC.autoref;
|
||||||
nextToken();
|
nextToken();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -5121,7 +5129,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
|
||||||
{
|
{
|
||||||
// auto ref (parameters) => expression
|
// auto ref (parameters) => expression
|
||||||
// auto ref (parameters) { statements... }
|
// auto ref (parameters) { statements... }
|
||||||
stc = STC.auto_ | STC.ref_;
|
stc = STC.auto_ | STC.ref_ | STC.autoref;
|
||||||
nextToken();
|
nextToken();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -5678,6 +5686,8 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
|
||||||
|
|
||||||
case TOK.auto_:
|
case TOK.auto_:
|
||||||
stc = STC.auto_;
|
stc = STC.auto_;
|
||||||
|
if (peekNext() == TOK.ref_)
|
||||||
|
stc |= STC.autoref;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TOK.const_:
|
case TOK.const_:
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
/* REQUIRED_ARGS: -verrors=0
|
/* REQUIRED_ARGS: -verrors=0
|
||||||
TEST_OUTPUT:
|
TEST_OUTPUT:
|
||||||
---
|
---
|
||||||
|
fail_compilation/diag9679.d(93): Deprecation: `auto` and `ref` storage classes should be adjacent
|
||||||
|
fail_compilation/diag9679.d(93): Deprecation: `auto` and `ref` storage classes should be adjacent
|
||||||
fail_compilation/diag9679.d(15): Error: rvalue `1` cannot be assigned to `ref n`
|
fail_compilation/diag9679.d(15): Error: rvalue `1` cannot be assigned to `ref n`
|
||||||
fail_compilation/diag9679.d(16): Error: variable `diag9679.main.n` - storage class `auto` has no effect if type is not inferred, did you mean `scope`?
|
fail_compilation/diag9679.d(16): Error: variable `diag9679.main.n` - storage class `auto` has no effect if type is not inferred, did you mean `scope`?
|
||||||
fail_compilation/diag9679.d(17): Error: variable `diag9679.main.S.a` - field declarations cannot be `ref`
|
fail_compilation/diag9679.d(17): Error: variable `diag9679.main.S.a` - field declarations cannot be `ref`
|
||||||
|
@ -8,8 +10,6 @@ fail_compilation/diag9679.d(24): Error: returning `r` escapes a reference to loc
|
||||||
---
|
---
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
if (ref n = 1) {}
|
if (ref n = 1) {}
|
||||||
|
@ -56,11 +56,11 @@ fail_compilation/diag9679.d(77): Error: type `immutable(int)` cannot be assigned
|
||||||
fail_compilation/diag9679.d(84): Error: returning `x` escapes a reference to local variable `x`
|
fail_compilation/diag9679.d(84): Error: returning `x` escapes a reference to local variable `x`
|
||||||
fail_compilation/diag9679.d(89): Error: variable `diag9679.test9.x` - void initializer not allowed for `ref` variable
|
fail_compilation/diag9679.d(89): Error: variable `diag9679.test9.x` - void initializer not allowed for `ref` variable
|
||||||
fail_compilation/diag9679.d(90): Error: variable `diag9679.test9.y` - void initializer not allowed for `ref` variable
|
fail_compilation/diag9679.d(90): Error: variable `diag9679.test9.y` - void initializer not allowed for `ref` variable
|
||||||
|
fail_compilation/diag9679.d(96): Error: variable `x` - `auto ref` variable must have `auto` and `ref` adjacent
|
||||||
---
|
---
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void test5()
|
void test5()
|
||||||
{
|
{
|
||||||
ref int r5;
|
ref int r5;
|
||||||
|
@ -89,3 +89,9 @@ void test9()
|
||||||
ref int x = void;
|
ref int x = void;
|
||||||
auto ref int y = void;
|
auto ref int y = void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void testKeywordOrder()(ref auto int x, auto const ref float y) {}
|
||||||
|
void testKeywordOrder()
|
||||||
|
{
|
||||||
|
ref auto int x = 3;
|
||||||
|
}
|
||||||
|
|
|
@ -1699,7 +1699,7 @@ template forward(args...)
|
||||||
{
|
{
|
||||||
x_ = forward!x;
|
x_ = forward!x;
|
||||||
}
|
}
|
||||||
this()(auto const ref X x)
|
this()(auto ref const X x)
|
||||||
{
|
{
|
||||||
x_ = forward!x;
|
x_ = forward!x;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue