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

Add @saferSystem #20606

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
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
3 changes: 3 additions & 0 deletions compiler/src/dmd/astbase.d
Original file line number Diff line number Diff line change
Expand Up @@ -3989,6 +3989,8 @@
this.trust = TRUST.default_;
if (stc & STC.safe)
this.trust = TRUST.safe;
else if (stc & STC.saferSystem)
this.trust = TRUST.saferSystem;

Check warning on line 3993 in compiler/src/dmd/astbase.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/astbase.d#L3992-L3993

Added lines #L3992 - L3993 were not covered by tests
else if (stc & STC.system)
this.trust = TRUST.system;
else if (stc & STC.trusted)
Expand Down Expand Up @@ -6920,6 +6922,7 @@
SCstring(STC.property, "@property"),
SCstring(STC.safe, "@safe"),
SCstring(STC.trusted, "@trusted"),
SCstring(STC.saferSystem, "@saferSystem"),
SCstring(STC.system, "@system"),
SCstring(STC.disable, "@disable"),
SCstring(STC.future, "@__future"),
Expand Down
62 changes: 32 additions & 30 deletions compiler/src/dmd/astenums.d
Original file line number Diff line number Diff line change
Expand Up @@ -96,31 +96,32 @@ enum STC : ulong // transfer changes to declaration.h
gshared = 0x4_0000_0000, /// accessible from multiple threads, but not typed as `shared`
wild = 0x8_0000_0000, /// for wild type constructor

property = 0x10_0000_0000, /// `@property`
safe = 0x20_0000_0000, /// `@safe`
trusted = 0x40_0000_0000, /// `@trusted`
system = 0x80_0000_0000, /// `@system`

ctfe = 0x100_0000_0000, /// can be used in CTFE, even if it is static
disable = 0x200_0000_0000, /// for functions that are not callable
result = 0x400_0000_0000, /// for result variables passed to out contracts
nodefaultctor = 0x800_0000_0000, /// must be set inside constructor

temp = 0x1000_0000_0000, /// temporary variable
rvalue = 0x2000_0000_0000, /// force rvalue for variables
nogc = 0x4000_0000_0000, /// `@nogc`
autoref = 0x8000_0000_0000, /// Mark for the already deduced `auto ref` parameter

inference = 0x1_0000_0000_0000, /// do attribute inference
exptemp = 0x2_0000_0000_0000, /// temporary variable that has lifetime restricted to an expression
future = 0x4_0000_0000_0000, /// introducing new base class function
local = 0x8_0000_0000_0000, /// do not forward (see dmd.dsymbol.ForwardingScopeDsymbol).

live = 0x10_0000_0000_0000, /// function `@live` attribute
register = 0x20_0000_0000_0000, /// `register` storage class (ImportC)
volatile_ = 0x40_0000_0000_0000, /// destined for volatile in the back end

safeGroup = STC.safe | STC.trusted | STC.system,
property = 0x010_0000_0000, /// `@property`
safe = 0x020_0000_0000, /// `@safe`
trusted = 0x040_0000_0000, /// `@trusted`
saferSystem = 0x080_0000_0000, /// `@saferSystem`
system = 0x100_0000_0000, /// `@system`

ctfe = 0x1000_0000_0000, /// can be used in CTFE, even if it is static
disable = 0x2000_0000_0000, /// for functions that are not callable
result = 0x4000_0000_0000, /// for result variables passed to out contracts
nodefaultctor = 0x8000_0000_0000, /// must be set inside constructor

temp = 0x1_0000_0000_0000, /// temporary variable
rvalue = 0x2_0000_0000_0000, /// force rvalue for variables
nogc = 0x4_0000_0000_0000, /// `@nogc`
autoref = 0x8_0000_0000_0000, /// Mark for the already deduced `auto ref` parameter

inference = 0x10_0000_0000_0000, /// do attribute inference
exptemp = 0x20_0000_0000_0000, /// temporary variable that has lifetime restricted to an expression
future = 0x40_0000_0000_0000, /// introducing new base class function
local = 0x80_0000_0000_0000, /// do not forward (see dmd.dsymbol.ForwardingScopeDsymbol).

live = 0x100_0000_0000_0000, /// function `@live` attribute
register = 0x200_0000_0000_0000, /// `register` storage class (ImportC)
volatile_ = 0x400_0000_0000_0000, /// destined for volatile in the back end

safeGroup = STC.safe | STC.trusted | STC.saferSystem | STC.system,
IOR = STC.constscoperef | STC.in_ | STC.ref_ | STC.out_,
TYPECTOR = (STC.const_ | STC.immutable_ | STC.shared_ | STC.wild),
FUNCATTR = (STC.ref_ | STC.nothrow_ | STC.nogc | STC.pure_ | STC.property | STC.live |
Expand All @@ -139,7 +140,7 @@ enum STC : ulong // transfer changes to declaration.h
flowThruAggregate = STC.safeGroup, /// for an AggregateDeclaration
flowThruFunction = ~(STC.auto_ | STC.scope_ | STC.static_ | STC.extern_ | STC.abstract_ | STC.deprecated_ | STC.override_ |
STC.TYPECTOR | STC.final_ | STC.tls | STC.gshared | STC.ref_ | STC.return_ | STC.property |
STC.nothrow_ | STC.pure_ | STC.safe | STC.trusted | STC.system), /// for a FuncDeclaration
STC.nothrow_ | STC.pure_ | STC.safe | STC.trusted | STC.saferSystem | STC.system), /// for a FuncDeclaration

}

Expand Down Expand Up @@ -301,10 +302,11 @@ enum ThreeState : ubyte

enum TRUST : ubyte
{
default_ = 0,
system = 1, // @system (same as TRUST.default)
trusted = 2, // @trusted
safe = 3, // @safe
default_ = 0,
system = 1, // @system (same as TRUST.default_ unless feature "safer" is enabled)
saferSystem = 2, // @saferSystem (same as TRUST.default_ if feature "safer" is enabled)
trusted = 3, // @trusted
safe = 4, // @safe
}

enum PURE : ubyte
Expand Down
2 changes: 2 additions & 0 deletions compiler/src/dmd/clone.d
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@
auto tf = f.type.isTypeFunction();
if (tf.trust == TRUST.safe)
s2 |= STC.safe;
else if (tf.trust == TRUST.saferSystem)
s2 |= STC.system;

Check warning on line 64 in compiler/src/dmd/clone.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/clone.d#L64

Added line #L64 was not covered by tests
else if (tf.trust == TRUST.system)
s2 |= STC.system;
else if (tf.trust == TRUST.trusted)
Expand Down
5 changes: 4 additions & 1 deletion compiler/src/dmd/expressionsem.d
Original file line number Diff line number Diff line change
Expand Up @@ -2301,8 +2301,11 @@
if (!loc.isValid()) // e.g. implicitly generated dtor
loc = sc.func.loc;

immutable msg = (f.isSaferD())
? "`@safe` %s `%s` cannot call `@saferSystem` %s `%s`"

Check warning on line 2305 in compiler/src/dmd/expressionsem.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/expressionsem.d#L2305

Added line #L2305 was not covered by tests
: "`@safe` %s `%s` cannot call `@system` %s `%s`";
const prettyChars = f.toPrettyChars();
error(loc, "`@safe` %s `%s` cannot call `@system` %s `%s`",
error(loc, msg.ptr,
sc.func.kind(), sc.func.toPrettyChars(), f.kind(),
prettyChars);
if (!f.isDtorDeclaration)
Expand Down
123 changes: 62 additions & 61 deletions compiler/src/dmd/frontend.h
Original file line number Diff line number Diff line change
Expand Up @@ -5306,67 +5306,68 @@ enum class MODFlags

enum class STC : uint64_t
{
undefined_ = 0LLU,
static_ = 1LLU,
extern_ = 2LLU,
const_ = 4LLU,
final_ = 8LLU,
abstract_ = 16LLU,
parameter = 32LLU,
field = 64LLU,
override_ = 128LLU,
auto_ = 256LLU,
synchronized_ = 512LLU,
deprecated_ = 1024LLU,
in_ = 2048LLU,
out_ = 4096LLU,
lazy_ = 8192LLU,
foreach_ = 16384LLU,
variadic = 32768LLU,
constscoperef = 65536LLU,
templateparameter = 131072LLU,
ref_ = 262144LLU,
scope_ = 524288LLU,
scopeinferred = 2097152LLU,
return_ = 4194304LLU,
returnScope = 8388608LLU,
returninferred = 16777216LLU,
immutable_ = 33554432LLU,
manifest = 134217728LLU,
nodtor = 268435456LLU,
nothrow_ = 536870912LLU,
pure_ = 1073741824LLU,
tls = 2147483648LLU,
alias_ = 4294967296LLU,
shared_ = 8589934592LLU,
gshared = 17179869184LLU,
wild = 34359738368LLU,
property = 68719476736LLU,
safe = 137438953472LLU,
trusted = 274877906944LLU,
system = 549755813888LLU,
ctfe = 1099511627776LLU,
disable = 2199023255552LLU,
result = 4398046511104LLU,
nodefaultctor = 8796093022208LLU,
temp = 17592186044416LLU,
rvalue = 35184372088832LLU,
nogc = 70368744177664LLU,
autoref = 140737488355328LLU,
inference = 281474976710656LLU,
exptemp = 562949953421312LLU,
future = 1125899906842624LLU,
local = 2251799813685248LLU,
live = 4503599627370496LLU,
register_ = 9007199254740992LLU,
volatile_ = 18014398509481984LLU,
safeGroup = 962072674304LLU,
IOR = 333824LLU,
TYPECTOR = 42983227396LLU,
FUNCATTR = 4575000774574080LLU,
visibleStorageClasses = 7954966262857631LLU,
flowThruAggregate = 962072674304LLU,
flowThruFunction = 18446742978991225440LLU,
undefined_ = 0LLU
static_ = 1LLU
extern_ = 2LLU
const_ = 4LLU
final_ = 8LLU
abstract_ = 16LLU
parameter = 32LLU
field = 64LLU
override_ = 128LLU
auto_ = 256LLU
synchronized_ = 512LLU
deprecated_ = 1024LLU
in_ = 2048LLU
out_ = 4096LLU
lazy_ = 8192LLU
foreach_ = 16384LLU
variadic = 32768LLU
constscoperef = 65536LLU
templateparameter = 131072LLU
ref_ = 262144LLU
scope_ = 524288LLU
scopeinferred = 2097152LLU
return_ = 4194304LLU
returnScope = 8388608LLU
returninferred = 16777216LLU
immutable_ = 33554432LLU
manifest = 134217728LLU
nodtor = 268435456LLU
nothrow_ = 536870912LLU
pure_ = 1073741824LLU
tls = 2147483648LLU
alias_ = 4294967296LLU
shared_ = 8589934592LLU
gshared = 17179869184LLU
wild = 34359738368LLU
property = 68719476736LLU
safe = 137438953472LLU
trusted = 274877906944LLU
saferSystem = 549755813888LLU
system = 1099511627776LLU
ctfe = 17592186044416LLU
disable = 35184372088832LLU
result = 70368744177664LLU
nodefaultctor = 140737488355328LLU
temp = 281474976710656LLU
rvalue = 562949953421312LLU
nogc = 1125899906842624LLU
autoref = 2251799813685248LLU
inference = 4503599627370496LLU
exptemp = 9007199254740992LLU
future = 18014398509481984LLU
local = 36028797018963968LLU
live = 72057594037927936LLU
register_ = 144115188075855872LLU
volatile_ = 288230376151711744LLU
safeGroup = 2061584302080LLU
IOR = 333824LLU
TYPECTOR = 42983227396LLU
FUNCATTR = 73185625859424256LLU
visibleStorageClasses = 127264072504459167LLU
flowThruAggregate = 2061584302080LLU
flowThruFunction = 18446741879479597664LLU
};

struct ASTCodegen final
Expand Down
2 changes: 2 additions & 0 deletions compiler/src/dmd/funcsem.d
Original file line number Diff line number Diff line change
Expand Up @@ -373,6 +373,8 @@
sc.stc &= ~STC.safeGroup;
if (tf.trust == TRUST.safe)
sc.stc |= STC.safe;
else if (tf.trust == TRUST.saferSystem)
sc.stc |= STC.saferSystem;

Check warning on line 377 in compiler/src/dmd/funcsem.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/funcsem.d#L377

Added line #L377 was not covered by tests
else if (tf.trust == TRUST.system)
sc.stc |= STC.system;
else if (tf.trust == TRUST.trusted)
Expand Down
1 change: 1 addition & 0 deletions compiler/src/dmd/hdrgen.d
Original file line number Diff line number Diff line change
Expand Up @@ -3268,6 +3268,7 @@ string stcToString(ref StorageClass stc) @safe
SCstring(STC.property, "@property"),
SCstring(STC.safe, "@safe"),
SCstring(STC.trusted, "@trusted"),
SCstring(STC.saferSystem, "@saferSystem"),
SCstring(STC.system, "@system"),
SCstring(STC.disable, "@disable"),
SCstring(STC.future, "@__future"),
Expand Down
1 change: 1 addition & 0 deletions compiler/src/dmd/id.d
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,7 @@ immutable Msgtable[] msgtable =
{ "nogc" },
{ "live" },
{ "safe" },
{ "saferSystem" },
{ "trusted" },
{ "system" },
{ "disable" },
Expand Down
7 changes: 4 additions & 3 deletions compiler/src/dmd/json.d
Original file line number Diff line number Diff line change
Expand Up @@ -290,9 +290,10 @@
// Should not be printed
//property(name, "default");
break;
case TRUST.system: return property(name, "system");
case TRUST.trusted: return property(name, "trusted");
case TRUST.safe: return property(name, "safe");
case TRUST.system: return property(name, "system");
case TRUST.saferSystem: return property(name, "saferSystem");
case TRUST.trusted: return property(name, "trusted");
case TRUST.safe: return property(name, "safe");

Check warning on line 296 in compiler/src/dmd/json.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/json.d#L293-L296

Added lines #L293 - L296 were not covered by tests
}
}

Expand Down
5 changes: 5 additions & 0 deletions compiler/src/dmd/mtype.d
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,8 @@
return null;
case TRUST.system:
return "@system";
case TRUST.saferSystem:
return "@saferSystem";
case TRUST.trusted:
return "@trusted";
case TRUST.safe:
Expand All @@ -225,6 +227,7 @@
{
assert(trustToString(TRUST.default_) == "");
assert(trustToString(TRUST.system) == "@system");
assert(trustToString(TRUST.saferSystem) == "@saferSystem");
assert(trustToString(TRUST.trusted) == "@trusted");
assert(trustToString(TRUST.safe) == "@safe");
}
Expand Down Expand Up @@ -2538,6 +2541,8 @@
this.trust = TRUST.default_;
if (stc & STC.safe)
this.trust = TRUST.safe;
else if (stc & STC.saferSystem)
this.trust = TRUST.saferSystem;

Check warning on line 2545 in compiler/src/dmd/mtype.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/mtype.d#L2545

Added line #L2545 was not covered by tests
else if (stc & STC.system)
this.trust = TRUST.system;
else if (stc & STC.trusted)
Expand Down
7 changes: 4 additions & 3 deletions compiler/src/dmd/mtype.h
Original file line number Diff line number Diff line change
Expand Up @@ -469,9 +469,10 @@ enum RET
enum class TRUST : unsigned char
{
default_ = 0,
system = 1, // @system (same as TRUSTdefault)
trusted = 2, // @trusted
safe = 3 // @safe
system = 1, // @system (same as TRUST.default_ unless feature "safer" is enabled)
saferSystem = 2, // @saferSystem (same as TRUST.default_ if feature "safer" is enabled)
trusted = 3, // @trusted
safe = 4 // @safe
};

enum TRUSTformat
Expand Down
17 changes: 9 additions & 8 deletions compiler/src/dmd/parse.d
Original file line number Diff line number Diff line change
Expand Up @@ -9636,14 +9636,15 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
*/
static StorageClass isBuiltinAtAttribute(Identifier ident)
{
return (ident == Id.property) ? STC.property :
(ident == Id.nogc) ? STC.nogc :
(ident == Id.safe) ? STC.safe :
(ident == Id.trusted) ? STC.trusted :
(ident == Id.system) ? STC.system :
(ident == Id.live) ? STC.live :
(ident == Id.future) ? STC.future :
(ident == Id.disable) ? STC.disable :
return (ident == Id.property) ? STC.property :
(ident == Id.nogc) ? STC.nogc :
(ident == Id.safe) ? STC.safe :
(ident == Id.saferSystem) ? STC.saferSystem :
(ident == Id.trusted) ? STC.trusted :
(ident == Id.system) ? STC.system :
(ident == Id.live) ? STC.live :
(ident == Id.future) ? STC.future :
(ident == Id.disable) ? STC.disable :
0;
}

Expand Down
5 changes: 3 additions & 2 deletions compiler/src/dmd/safe.d
Original file line number Diff line number Diff line change
Expand Up @@ -323,8 +323,9 @@ bool checkUnsafeDotExp(Scope* sc, Expression e, Identifier id, int flag)
*/
bool isSaferD(FuncDeclaration fd)
{
return fd.type.toTypeFunction().trust == TRUST.default_ &&
global.params.safer == FeatureState.enabled;
return fd.type.toTypeFunction().trust == TRUST.saferSystem ||
(fd.type.toTypeFunction().trust == TRUST.default_ &&
global.params.safer == FeatureState.enabled);
}

bool isSafe(FuncDeclaration fd)
Expand Down
2 changes: 2 additions & 0 deletions compiler/src/dmd/typesem.d
Original file line number Diff line number Diff line change
Expand Up @@ -2234,6 +2234,8 @@
{
if (sc.stc & STC.safe)
tf.trust = TRUST.safe;
else if (sc.stc & STC.saferSystem)
tf.trust = TRUST.saferSystem;

Check warning on line 2238 in compiler/src/dmd/typesem.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/typesem.d#L2238

Added line #L2238 was not covered by tests
else if (sc.stc & STC.system)
tf.trust = TRUST.system;
else if (sc.stc & STC.trusted)
Expand Down
18 changes: 18 additions & 0 deletions compiler/test/fail_compilation/safer_attrib.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/*
TEST_OUTPUT:
---
fail_compilation/safer_attrib.d(10): Error: `void` initializers for pointers not allowed in safe functions
---
*/

void test1() @saferSystem
{
int* p = void;
}

void foo3() { }

void test2()
{
foo3(); // should not be an error
}
Loading
Loading