fix Issue 23145 - Stack allocation of scope new variables defeats @safe (#14175)

This commit is contained in:
Walter Bright 2023-02-08 23:29:07 -08:00 committed by GitHub
parent f1b70f41f7
commit 74e40179b5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 103 additions and 42 deletions

View file

@ -1065,7 +1065,7 @@ private DtorDeclaration buildWindowsCppDtor(AggregateDeclaration ad, DtorDeclara
{
auto cldec = ad.isClassDeclaration();
if (!cldec || cldec.cppDtorVtblIndex == -1) // scalar deleting dtor not built for non-virtual dtors
return dtor;
return dtor; // perhaps also do this if STC.scope_ is set
// generate deleting C++ destructor corresponding to:
// void* C::~C(int del)
@ -1077,8 +1077,9 @@ private DtorDeclaration buildWindowsCppDtor(AggregateDeclaration ad, DtorDeclara
Parameter delparam = new Parameter(STC.undefined_, Type.tuns32, Identifier.idPool("del"), new IntegerExp(dtor.loc, 0, Type.tuns32), null);
Parameters* params = new Parameters;
params.push(delparam);
auto ftype = new TypeFunction(ParameterList(params), Type.tvoidptr, LINK.cpp, dtor.storage_class);
auto func = new DtorDeclaration(dtor.loc, dtor.loc, dtor.storage_class, Id.cppdtor);
const stc = dtor.storage_class & ~STC.scope_; // because we add the `return this;` later
auto ftype = new TypeFunction(ParameterList(params), Type.tvoidptr, LINK.cpp, stc);
auto func = new DtorDeclaration(dtor.loc, dtor.loc, stc, Id.cppdtor);
func.type = ftype;
// Always generate the function with body, because it is not exported from DLLs.

View file

@ -1090,9 +1090,26 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
ex = (cast(AssignExp)ex).e2;
if (auto ne = ex.isNewExp())
{
// See if initializer is a NewExp that can be allocated on the stack
/* See if initializer is a NewExp that can be allocated on the stack.
*/
if (dsym.type.toBasetype().ty == Tclass)
{
/* Unsafe to allocate on stack if constructor is not `scope` because the `this` can leak.
* https://issues.dlang.org/show_bug.cgi?id=23145
*/
if (ne.member && !(ne.member.storage_class & STC.scope_))
{
if (sc.func.isSafe())
{
// @@@DEPRECATED_2.112@@@
deprecation(dsym.loc,
"`scope` allocation of `%s` requires that constructor be annotated with `scope`",
dsym.toChars());
deprecationSupplemental(ne.member.loc, "is the location of the constructor");
}
else
sc.func.setUnsafe();
}
ne.onstack = 1;
dsym.onstack = true;
}
@ -4199,8 +4216,8 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
override void visit(DtorDeclaration dd)
{
//printf("DtorDeclaration::semantic() %s\n", toChars());
//printf("ident: %s, %s, %p, %p\n", ident.toChars(), Id.dtor.toChars(), ident, Id.dtor);
//printf("DtorDeclaration::semantic() %s\n", dd.toChars());
//printf("ident: %s, %s, %p, %p\n", dd.ident.toChars(), Id.dtor.toChars(), dd.ident, Id.dtor);
if (dd.semanticRun >= PASS.semanticdone)
return;
if (dd._scope)
@ -5342,7 +5359,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
// is less strict (e.g. `preview=dtorfields` might introduce a call to a less qualified dtor)
auto ctor = new CtorDeclaration(cldec.loc, Loc.initial, 0, tf);
ctor.storage_class |= STC.inference;
ctor.storage_class |= STC.inference | (fd.storage_class & STC.scope_);
ctor.isGenerated = true;
ctor.fbody = new CompoundStatement(Loc.initial, new Statements());

View file

@ -2320,6 +2320,7 @@ extern (C++) class FuncDeclaration : Declaration
* base.in();
* assert(false, "Logic error: " ~ thr.msg);
* }
* }
*/
foreach (fdv; foverrides)
@ -3861,7 +3862,7 @@ extern (C++) final class CtorDeclaration : FuncDeclaration
{
super(loc, endloc, Id.ctor, stc, type);
this.isCpCtor = isCpCtor;
//printf("CtorDeclaration(loc = %s) %s\n", loc.toChars(), toChars());
//printf("CtorDeclaration(loc = %s) %s %p\n", loc.toChars(), toChars(), this);
}
override CtorDeclaration syntaxCopy(Dsymbol s)

View file

@ -13,11 +13,14 @@
module dmd.nogc;
import core.stdc.stdio;
import dmd.aggregate;
import dmd.apply;
import dmd.astenums;
import dmd.declaration;
import dmd.dscope;
import dmd.errors;
import dmd.expression;
import dmd.func;
import dmd.globals;

View file

@ -0,0 +1,39 @@
/* TEST_OUTPUT:
---
compilable/test23145.d(117): Deprecation: `scope` allocation of `c` requires that constructor be annotated with `scope`
compilable/test23145.d(111): is the location of the constructor
compilable/test23145.d(124): Deprecation: `scope` allocation of `c` requires that constructor be annotated with `scope`
compilable/test23145.d(111): is the location of the constructor
---
*/
// https://issues.dlang.org/show_bug.cgi?id=23145
#line 100
class D
{
C c;
}
class C
{
D d;
int x=3;
this(int i) scope @safe @nogc;
this(D d) @safe @nogc;
}
C foo(D d)@nogc @safe
{
scope e = new C(1); // ok
scope c = new C(d); // deprecation
return c.d.c;
}
C bax(D d) @safe
{
scope e = new C(1); // ok
scope c = new C(d); // deprecation
return c.d.c;
}

View file

@ -67,13 +67,13 @@ int ax;
class A2
{
this()
this() scope
{
printf("A2.this()\n");
ax += 1;
}
~this()
~this() scope
{
printf("A2.~this()\n");
ax += 1000;
@ -102,12 +102,12 @@ class Parent3
class Child3 : Parent3
{
this(){
this() scope {
assert(status3==0);
status3=1;
}
~this(){
~this() scope {
assert(status3==1);
status3=2;
}

View file

@ -38,12 +38,12 @@ extern (C) int printf(scope const char*, ...);
extern (C++) class CppA
{
int num;
this(int num)
this(int num) scope
{
this.num = num;
}
~this()
~this() scope
{
printf("%d: CppA.~this\n", num);
}
@ -51,12 +51,12 @@ extern (C++) class CppA
extern (C++) class CppB : CppA
{
this(int num)
this(int num) scope
{
super(num);
}
~this()
~this() scope
{
printf("%d: CppB.~this\n", num);
}
@ -64,12 +64,12 @@ extern (C++) class CppB : CppA
extern (C++) class CppC : CppB
{
this(int num)
this(int num) scope
{
super(num);
}
~this()
~this() scope
{
printf("%d: CppC.~this\n", num);
}
@ -78,12 +78,12 @@ extern (C++) class CppC : CppB
extern (D) class DA
{
int num;
this(int num)
this(int num) scope
{
this.num = num;
}
~this()
~this() scope
{
printf("%d: DA.~this\n", num);
}
@ -91,12 +91,12 @@ extern (D) class DA
extern (D) class DB : DA
{
this(int num)
this(int num) scope
{
super(num);
}
~this()
~this() scope
{
printf("%d: DB.~this\n", num);
}
@ -104,12 +104,12 @@ extern (D) class DB : DA
extern (D) class DC : DB
{
this(int num)
this(int num) scope
{
super(num);
}
~this()
~this() scope
{
printf("%d: DC.~this\n", num);
}
@ -118,7 +118,7 @@ extern (D) class DC : DB
extern (C++) class CppNoDestruct
{
int num;
this(int num)
this(int num) scope
{
this.num = num;
}

View file

@ -82,13 +82,13 @@ int x5;
class Foo5
{
this ()
this () scope
{
printf ("Constructor\n");
assert(x5 == 0);
x5++;
}
~this ()
~this () scope
{
printf ("Destructor\n");
assert(x5 == 2);

View file

@ -4,7 +4,7 @@
string exp()
{
string s = "a = b + c * d + a;";
foreach (i; 0 .. 9)
foreach (i; 0 .. 8)
s = s ~ s;
return s;
}
@ -22,6 +22,6 @@ int main()
{
int a = test();
printf("a = %d\n", a);
assert(test() == 7169);
assert(test() == 3585);
return 0;
}

View file

@ -1322,22 +1322,22 @@ void test70()
class C71
{
static int cnt;
this() { printf("C()\n"); cnt++; }
~this() { printf("~C()\n"); cnt--; }
this() scope { printf("C()\n"); cnt++; }
~this() scope { printf("~C()\n"); cnt--; }
}
class D71
{
static int cnt;
this() { printf("D()\n"); cnt++; }
~this() { printf("~D()\n"); cnt--; }
this() scope { printf("D()\n"); cnt++; }
~this() scope { printf("~D()\n"); cnt--; }
}
class E71
{
static int cnt;
this() { printf("E()\n"); cnt++; }
~this() { printf("~E()\n"); cnt--; }
this() scope { printf("E()\n"); cnt++; }
~this() scope { printf("~E()\n"); cnt--; }
}
void test71()

View file

@ -786,8 +786,8 @@ void test42()
int x44;
class A44 {
this() { printf("A44 ctor\n"); x44 += 1; }
~this() { printf("A44 dtor\n"); x44 += 0x100; }
this() scope { printf("A44 ctor\n"); x44 += 1; }
~this() scope { printf("A44 dtor\n"); x44 += 0x100; }
}
class B44 : A44 { }

View file

@ -494,7 +494,7 @@ void test23()
int status24;
class C24{
this(){
this() scope {
assert(status24==0);
status24+=2;
}

View file

@ -1324,7 +1324,7 @@ extern(C++)
class Cpp15589Derived : Cpp15589Base
{
public:
this();
this() scope;
final ~this();
int b;
}
@ -1334,7 +1334,7 @@ extern(C++)
public:
void beforeDtor();
this();
this() scope;
~this();
void afterDtor();
@ -1344,7 +1344,7 @@ extern(C++)
class Cpp15589DerivedVirtual : Cpp15589BaseVirtual
{
public:
this();
this() scope;
~this();
override void afterDtor();
@ -1355,7 +1355,7 @@ extern(C++)
class Cpp15589IntroducingVirtual : Cpp15589Base
{
public:
this();
this() scope;
void beforeIntroducedVirtual();
~this();
void afterIntroducedVirtual(int);