mirror of
https://github.com/dlang/dmd.git
synced 2025-04-26 13:10:12 +03:00
Fix Issue 12118 - Modify immutable data using throw (#14706)
* Fix Issue 12118 - Modify immutable data using throw * Change immutable test to const * Deprecate throwing any qualified type * Allow throw shared as std.concurrency does that * Use static this instead of static const for test * Only allow single shared qualifier or none * Add changelog * Disallow throwing shared objects too * Update changelog/dmd.throw-qualifier.dd Co-authored-by: Razvan Nitu <razvan.nitu1305@gmail.com> --------- Co-authored-by: Razvan Nitu <razvan.nitu1305@gmail.com>
This commit is contained in:
parent
c69d3d4e0c
commit
7d6ac55712
5 changed files with 46 additions and 4 deletions
11
changelog/dmd.throw-qualifier.dd
Normal file
11
changelog/dmd.throw-qualifier.dd
Normal file
|
@ -0,0 +1,11 @@
|
|||
Throwing qualified objects is now deprecated
|
||||
|
||||
Previously, an `immutable`, `const`, `inout` or `shared` exception could be
|
||||
thrown and then caught in an unqualified `catch (Exception e)` clause.
|
||||
That breaks type safety.
|
||||
Throwing a qualified object is now deprecated. This helps to prevent
|
||||
possible mutation of an immutable object in a `catch` clause.
|
||||
|
||||
The runtime also modifies a thrown object (e.g. to contain a stack
|
||||
trace) which can violate `const` or `immutable` objects. Throwing
|
||||
qualified objects has been deprecated for this reason also.
|
|
@ -3796,7 +3796,13 @@ package (dmd) extern (C++) final class StatementSemanticVisitor : Visitor
|
|||
exp = checkGC(sc, exp);
|
||||
if (exp.op == EXP.error)
|
||||
return false;
|
||||
|
||||
if (!exp.type.isNaked())
|
||||
{
|
||||
// @@@DEPRECATED_2.112@@@
|
||||
// Deprecated in 2.102, change into an error & return false in 2.112
|
||||
exp.loc.deprecation("cannot throw object of qualified type `%s`", exp.type.toChars());
|
||||
//return false;
|
||||
}
|
||||
checkThrowEscape(sc, exp, false);
|
||||
|
||||
ClassDeclaration cd = exp.type.toBasetype().isClassHandle();
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
/*
|
||||
TEST_OUTPUT:
|
||||
---
|
||||
fail_compilation/ice10651.d(11): Error: can only throw class objects derived from `Throwable`, not type `int*`
|
||||
fail_compilation/ice10651.d(13): Error: can only throw class objects derived from `Throwable`, not type `int*`
|
||||
fail_compilation/ice10651.d(19): Deprecation: cannot throw object of qualified type `immutable(Exception)`
|
||||
fail_compilation/ice10651.d(20): Deprecation: cannot throw object of qualified type `const(Dummy)`
|
||||
---
|
||||
*/
|
||||
|
||||
|
@ -10,3 +12,20 @@ void main()
|
|||
alias T = int;
|
||||
throw new T(); // ICE
|
||||
}
|
||||
|
||||
void f()
|
||||
{
|
||||
immutable c = new Exception("");
|
||||
if (c) throw c;
|
||||
throw new const Dummy([]);
|
||||
}
|
||||
|
||||
class Dummy: Exception
|
||||
{
|
||||
int[] data;
|
||||
@safe pure nothrow this(immutable int[] data) immutable
|
||||
{
|
||||
super("Dummy");
|
||||
this.data = data;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -154,7 +154,13 @@ void testDeleteWithoutCpp()
|
|||
|
||||
class ThrowingChildD : ChildD
|
||||
{
|
||||
static immutable ex = new Exception("STOP");
|
||||
static Exception ex;
|
||||
|
||||
static this()
|
||||
{
|
||||
ex = new Exception("STOP");
|
||||
}
|
||||
|
||||
~this()
|
||||
{
|
||||
throw ex;
|
||||
|
|
|
@ -24,7 +24,7 @@ class Abc : Throwable
|
|||
{
|
||||
printf("foo 1\n");
|
||||
x |= 4;
|
||||
throw this;
|
||||
throw cast() this;
|
||||
printf("foo 2\n");
|
||||
x |= 8;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue