mirror of
https://github.com/dlang/dmd.git
synced 2025-04-26 13:10:12 +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();
|
||||
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.
|
||||
|
|
|
@ -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());
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
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
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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 { }
|
||||
|
||||
|
|
|
@ -494,7 +494,7 @@ void test23()
|
|||
int status24;
|
||||
|
||||
class C24{
|
||||
this(){
|
||||
this() scope {
|
||||
assert(status24==0);
|
||||
status24+=2;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue