mirror of
https://github.com/dlang/dmd.git
synced 2025-04-26 21:21:48 +03:00
fix Issue 23145 - Stack allocation of scope new variables defeats @safe (#14175)
This commit is contained in:
parent
f1b70f41f7
commit
74e40179b5
13 changed files with 103 additions and 42 deletions
|
@ -1065,7 +1065,7 @@ private DtorDeclaration buildWindowsCppDtor(AggregateDeclaration ad, DtorDeclara
|
||||||
{
|
{
|
||||||
auto cldec = ad.isClassDeclaration();
|
auto cldec = ad.isClassDeclaration();
|
||||||
if (!cldec || cldec.cppDtorVtblIndex == -1) // scalar deleting dtor not built for non-virtual dtors
|
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:
|
// generate deleting C++ destructor corresponding to:
|
||||||
// void* C::~C(int del)
|
// 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);
|
Parameter delparam = new Parameter(STC.undefined_, Type.tuns32, Identifier.idPool("del"), new IntegerExp(dtor.loc, 0, Type.tuns32), null);
|
||||||
Parameters* params = new Parameters;
|
Parameters* params = new Parameters;
|
||||||
params.push(delparam);
|
params.push(delparam);
|
||||||
auto ftype = new TypeFunction(ParameterList(params), Type.tvoidptr, LINK.cpp, dtor.storage_class);
|
const stc = dtor.storage_class & ~STC.scope_; // because we add the `return this;` later
|
||||||
auto func = new DtorDeclaration(dtor.loc, dtor.loc, dtor.storage_class, Id.cppdtor);
|
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;
|
func.type = ftype;
|
||||||
|
|
||||||
// Always generate the function with body, because it is not exported from DLLs.
|
// Always generate the function with body, because it is not exported from DLLs.
|
||||||
|
|
|
@ -1090,9 +1090,26 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
|
||||||
ex = (cast(AssignExp)ex).e2;
|
ex = (cast(AssignExp)ex).e2;
|
||||||
if (auto ne = ex.isNewExp())
|
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)
|
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;
|
ne.onstack = 1;
|
||||||
dsym.onstack = true;
|
dsym.onstack = true;
|
||||||
}
|
}
|
||||||
|
@ -4199,8 +4216,8 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
|
||||||
|
|
||||||
override void visit(DtorDeclaration dd)
|
override void visit(DtorDeclaration dd)
|
||||||
{
|
{
|
||||||
//printf("DtorDeclaration::semantic() %s\n", toChars());
|
//printf("DtorDeclaration::semantic() %s\n", dd.toChars());
|
||||||
//printf("ident: %s, %s, %p, %p\n", ident.toChars(), Id.dtor.toChars(), ident, Id.dtor);
|
//printf("ident: %s, %s, %p, %p\n", dd.ident.toChars(), Id.dtor.toChars(), dd.ident, Id.dtor);
|
||||||
if (dd.semanticRun >= PASS.semanticdone)
|
if (dd.semanticRun >= PASS.semanticdone)
|
||||||
return;
|
return;
|
||||||
if (dd._scope)
|
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)
|
// 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);
|
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.isGenerated = true;
|
||||||
ctor.fbody = new CompoundStatement(Loc.initial, new Statements());
|
ctor.fbody = new CompoundStatement(Loc.initial, new Statements());
|
||||||
|
|
||||||
|
|
|
@ -2320,6 +2320,7 @@ extern (C++) class FuncDeclaration : Declaration
|
||||||
* base.in();
|
* base.in();
|
||||||
* assert(false, "Logic error: " ~ thr.msg);
|
* assert(false, "Logic error: " ~ thr.msg);
|
||||||
* }
|
* }
|
||||||
|
* }
|
||||||
*/
|
*/
|
||||||
|
|
||||||
foreach (fdv; foverrides)
|
foreach (fdv; foverrides)
|
||||||
|
@ -3861,7 +3862,7 @@ extern (C++) final class CtorDeclaration : FuncDeclaration
|
||||||
{
|
{
|
||||||
super(loc, endloc, Id.ctor, stc, type);
|
super(loc, endloc, Id.ctor, stc, type);
|
||||||
this.isCpCtor = isCpCtor;
|
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)
|
override CtorDeclaration syntaxCopy(Dsymbol s)
|
||||||
|
|
|
@ -13,11 +13,14 @@
|
||||||
|
|
||||||
module dmd.nogc;
|
module dmd.nogc;
|
||||||
|
|
||||||
|
import core.stdc.stdio;
|
||||||
|
|
||||||
import dmd.aggregate;
|
import dmd.aggregate;
|
||||||
import dmd.apply;
|
import dmd.apply;
|
||||||
import dmd.astenums;
|
import dmd.astenums;
|
||||||
import dmd.declaration;
|
import dmd.declaration;
|
||||||
import dmd.dscope;
|
import dmd.dscope;
|
||||||
|
import dmd.errors;
|
||||||
import dmd.expression;
|
import dmd.expression;
|
||||||
import dmd.func;
|
import dmd.func;
|
||||||
import dmd.globals;
|
import dmd.globals;
|
||||||
|
|
39
compiler/test/compilable/test23145.d
Normal file
39
compiler/test/compilable/test23145.d
Normal 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;
|
||||||
|
}
|
|
@ -67,13 +67,13 @@ int ax;
|
||||||
|
|
||||||
class A2
|
class A2
|
||||||
{
|
{
|
||||||
this()
|
this() scope
|
||||||
{
|
{
|
||||||
printf("A2.this()\n");
|
printf("A2.this()\n");
|
||||||
ax += 1;
|
ax += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
~this()
|
~this() scope
|
||||||
{
|
{
|
||||||
printf("A2.~this()\n");
|
printf("A2.~this()\n");
|
||||||
ax += 1000;
|
ax += 1000;
|
||||||
|
@ -102,12 +102,12 @@ class Parent3
|
||||||
|
|
||||||
class Child3 : Parent3
|
class Child3 : Parent3
|
||||||
{
|
{
|
||||||
this(){
|
this() scope {
|
||||||
assert(status3==0);
|
assert(status3==0);
|
||||||
status3=1;
|
status3=1;
|
||||||
}
|
}
|
||||||
|
|
||||||
~this(){
|
~this() scope {
|
||||||
assert(status3==1);
|
assert(status3==1);
|
||||||
status3=2;
|
status3=2;
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,12 +38,12 @@ extern (C) int printf(scope const char*, ...);
|
||||||
extern (C++) class CppA
|
extern (C++) class CppA
|
||||||
{
|
{
|
||||||
int num;
|
int num;
|
||||||
this(int num)
|
this(int num) scope
|
||||||
{
|
{
|
||||||
this.num = num;
|
this.num = num;
|
||||||
}
|
}
|
||||||
|
|
||||||
~this()
|
~this() scope
|
||||||
{
|
{
|
||||||
printf("%d: CppA.~this\n", num);
|
printf("%d: CppA.~this\n", num);
|
||||||
}
|
}
|
||||||
|
@ -51,12 +51,12 @@ extern (C++) class CppA
|
||||||
|
|
||||||
extern (C++) class CppB : CppA
|
extern (C++) class CppB : CppA
|
||||||
{
|
{
|
||||||
this(int num)
|
this(int num) scope
|
||||||
{
|
{
|
||||||
super(num);
|
super(num);
|
||||||
}
|
}
|
||||||
|
|
||||||
~this()
|
~this() scope
|
||||||
{
|
{
|
||||||
printf("%d: CppB.~this\n", num);
|
printf("%d: CppB.~this\n", num);
|
||||||
}
|
}
|
||||||
|
@ -64,12 +64,12 @@ extern (C++) class CppB : CppA
|
||||||
|
|
||||||
extern (C++) class CppC : CppB
|
extern (C++) class CppC : CppB
|
||||||
{
|
{
|
||||||
this(int num)
|
this(int num) scope
|
||||||
{
|
{
|
||||||
super(num);
|
super(num);
|
||||||
}
|
}
|
||||||
|
|
||||||
~this()
|
~this() scope
|
||||||
{
|
{
|
||||||
printf("%d: CppC.~this\n", num);
|
printf("%d: CppC.~this\n", num);
|
||||||
}
|
}
|
||||||
|
@ -78,12 +78,12 @@ extern (C++) class CppC : CppB
|
||||||
extern (D) class DA
|
extern (D) class DA
|
||||||
{
|
{
|
||||||
int num;
|
int num;
|
||||||
this(int num)
|
this(int num) scope
|
||||||
{
|
{
|
||||||
this.num = num;
|
this.num = num;
|
||||||
}
|
}
|
||||||
|
|
||||||
~this()
|
~this() scope
|
||||||
{
|
{
|
||||||
printf("%d: DA.~this\n", num);
|
printf("%d: DA.~this\n", num);
|
||||||
}
|
}
|
||||||
|
@ -91,12 +91,12 @@ extern (D) class DA
|
||||||
|
|
||||||
extern (D) class DB : DA
|
extern (D) class DB : DA
|
||||||
{
|
{
|
||||||
this(int num)
|
this(int num) scope
|
||||||
{
|
{
|
||||||
super(num);
|
super(num);
|
||||||
}
|
}
|
||||||
|
|
||||||
~this()
|
~this() scope
|
||||||
{
|
{
|
||||||
printf("%d: DB.~this\n", num);
|
printf("%d: DB.~this\n", num);
|
||||||
}
|
}
|
||||||
|
@ -104,12 +104,12 @@ extern (D) class DB : DA
|
||||||
|
|
||||||
extern (D) class DC : DB
|
extern (D) class DC : DB
|
||||||
{
|
{
|
||||||
this(int num)
|
this(int num) scope
|
||||||
{
|
{
|
||||||
super(num);
|
super(num);
|
||||||
}
|
}
|
||||||
|
|
||||||
~this()
|
~this() scope
|
||||||
{
|
{
|
||||||
printf("%d: DC.~this\n", num);
|
printf("%d: DC.~this\n", num);
|
||||||
}
|
}
|
||||||
|
@ -118,7 +118,7 @@ extern (D) class DC : DB
|
||||||
extern (C++) class CppNoDestruct
|
extern (C++) class CppNoDestruct
|
||||||
{
|
{
|
||||||
int num;
|
int num;
|
||||||
this(int num)
|
this(int num) scope
|
||||||
{
|
{
|
||||||
this.num = num;
|
this.num = num;
|
||||||
}
|
}
|
||||||
|
|
|
@ -82,13 +82,13 @@ int x5;
|
||||||
|
|
||||||
class Foo5
|
class Foo5
|
||||||
{
|
{
|
||||||
this ()
|
this () scope
|
||||||
{
|
{
|
||||||
printf ("Constructor\n");
|
printf ("Constructor\n");
|
||||||
assert(x5 == 0);
|
assert(x5 == 0);
|
||||||
x5++;
|
x5++;
|
||||||
}
|
}
|
||||||
~this ()
|
~this () scope
|
||||||
{
|
{
|
||||||
printf ("Destructor\n");
|
printf ("Destructor\n");
|
||||||
assert(x5 == 2);
|
assert(x5 == 2);
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
string exp()
|
string exp()
|
||||||
{
|
{
|
||||||
string s = "a = b + c * d + a;";
|
string s = "a = b + c * d + a;";
|
||||||
foreach (i; 0 .. 9)
|
foreach (i; 0 .. 8)
|
||||||
s = s ~ s;
|
s = s ~ s;
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,6 @@ int main()
|
||||||
{
|
{
|
||||||
int a = test();
|
int a = test();
|
||||||
printf("a = %d\n", a);
|
printf("a = %d\n", a);
|
||||||
assert(test() == 7169);
|
assert(test() == 3585);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1322,22 +1322,22 @@ void test70()
|
||||||
class C71
|
class C71
|
||||||
{
|
{
|
||||||
static int cnt;
|
static int cnt;
|
||||||
this() { printf("C()\n"); cnt++; }
|
this() scope { printf("C()\n"); cnt++; }
|
||||||
~this() { printf("~C()\n"); cnt--; }
|
~this() scope { printf("~C()\n"); cnt--; }
|
||||||
}
|
}
|
||||||
|
|
||||||
class D71
|
class D71
|
||||||
{
|
{
|
||||||
static int cnt;
|
static int cnt;
|
||||||
this() { printf("D()\n"); cnt++; }
|
this() scope { printf("D()\n"); cnt++; }
|
||||||
~this() { printf("~D()\n"); cnt--; }
|
~this() scope { printf("~D()\n"); cnt--; }
|
||||||
}
|
}
|
||||||
|
|
||||||
class E71
|
class E71
|
||||||
{
|
{
|
||||||
static int cnt;
|
static int cnt;
|
||||||
this() { printf("E()\n"); cnt++; }
|
this() scope { printf("E()\n"); cnt++; }
|
||||||
~this() { printf("~E()\n"); cnt--; }
|
~this() scope { printf("~E()\n"); cnt--; }
|
||||||
}
|
}
|
||||||
|
|
||||||
void test71()
|
void test71()
|
||||||
|
|
|
@ -786,8 +786,8 @@ void test42()
|
||||||
int x44;
|
int x44;
|
||||||
|
|
||||||
class A44 {
|
class A44 {
|
||||||
this() { printf("A44 ctor\n"); x44 += 1; }
|
this() scope { printf("A44 ctor\n"); x44 += 1; }
|
||||||
~this() { printf("A44 dtor\n"); x44 += 0x100; }
|
~this() scope { printf("A44 dtor\n"); x44 += 0x100; }
|
||||||
}
|
}
|
||||||
class B44 : A44 { }
|
class B44 : A44 { }
|
||||||
|
|
||||||
|
|
|
@ -494,7 +494,7 @@ void test23()
|
||||||
int status24;
|
int status24;
|
||||||
|
|
||||||
class C24{
|
class C24{
|
||||||
this(){
|
this() scope {
|
||||||
assert(status24==0);
|
assert(status24==0);
|
||||||
status24+=2;
|
status24+=2;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1324,7 +1324,7 @@ extern(C++)
|
||||||
class Cpp15589Derived : Cpp15589Base
|
class Cpp15589Derived : Cpp15589Base
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
this();
|
this() scope;
|
||||||
final ~this();
|
final ~this();
|
||||||
int b;
|
int b;
|
||||||
}
|
}
|
||||||
|
@ -1334,7 +1334,7 @@ extern(C++)
|
||||||
public:
|
public:
|
||||||
void beforeDtor();
|
void beforeDtor();
|
||||||
|
|
||||||
this();
|
this() scope;
|
||||||
~this();
|
~this();
|
||||||
|
|
||||||
void afterDtor();
|
void afterDtor();
|
||||||
|
@ -1344,7 +1344,7 @@ extern(C++)
|
||||||
class Cpp15589DerivedVirtual : Cpp15589BaseVirtual
|
class Cpp15589DerivedVirtual : Cpp15589BaseVirtual
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
this();
|
this() scope;
|
||||||
~this();
|
~this();
|
||||||
|
|
||||||
override void afterDtor();
|
override void afterDtor();
|
||||||
|
@ -1355,7 +1355,7 @@ extern(C++)
|
||||||
class Cpp15589IntroducingVirtual : Cpp15589Base
|
class Cpp15589IntroducingVirtual : Cpp15589Base
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
this();
|
this() scope;
|
||||||
void beforeIntroducedVirtual();
|
void beforeIntroducedVirtual();
|
||||||
~this();
|
~this();
|
||||||
void afterIntroducedVirtual(int);
|
void afterIntroducedVirtual(int);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue