Bug 9539 – Wrong implicit conversion of array to pointer
Status
RESOLVED
Resolution
FIXED
Severity
regression
Priority
P2
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2013-02-19T14:13:00Z
Last change time
2013-05-13T06:51:28Z
Keywords
pull, wrong-code
Assigned to
nobody
Creator
andrej.mitrovich
Comments
Comment #0 by andrej.mitrovich — 2013-02-19T14:13:47Z
void f(int** ptr)
{
assert(**ptr == 10);
}
void main()
{
int* i = new int;
*i = 10;
int*[1] x = [i];
f(&x[0]);
}
2.060:
$ dmd test.d
>
2.061
$ dmd test.d
> core.exception.AssertError@test(5): Assertion failure
2.062
$ dmd test.d
> core.exception.AssertError@test(5): Assertion failure
Same thing happens when you use 'x.ptr'.
Comment #1 by k.hara.pg — 2013-02-20T23:48:00Z
(In reply to comment #0)
> void f(int** ptr)
> {
> assert(**ptr == 10);
> }
>
> void main()
> {
> int* i = new int;
> *i = 10;
> int*[1] x = [i];
> f(&x[0]);
> }
More simple case:
int*[1] x;
int* p = new int;
x = [p]; // is wrongly rewritten to: x[] = [p].ptr
printf("p = %p, x[0] = %p\n", p, x[0]);
assert(p == x[0]); // fails!?
----
This is horribly serious problem.
The root issue is in TypeDArray::implicitConvTo. FROM THE BEGINNING of D2, an implicit conversion from dynamic array to its element pointer type as a deprecated feature.
int[] arr; int* p;
p = arr; // is expected to rewrite to p = arr.ptr
BUT, it was completely broken FROM THE BEGINNING of D2. Instead of the expected behavior, dynamic array can be convertible to its element type.
int*[] arr = [null];
int* p;
p = arr; // bad!
printf("p = %p, arr.ptr = %p\n", p, arr.ptr);
It has been wrongly accepted in long time if '-d' switch is specified. Then, from 2.061, the situation has become worse by "informational deprecated error in default". Above code would be _silently_ accepted in default, and compiler outputs wrong-code.
----
But, we cannot *fix* TypeDArray::implicitConvTo to implement the deprecated feature, because it breaks phobos building.
In std.process line 367:
scope(exit) if (exists(filename)) remove(filename); // <----
Today, it calls std.file.remove in here.
std.stdio.file line 413:
void remove(in char[] name)
But std.process also imports core.stdc.stdio through std.stdio. In there another 'remove' is defined.
core.stdc.stdio line 453:
int remove(in char* filename); // <----
After *fixing* the deprecated feature, the 'remove' call in std.process will match both 'remove's that defined in different modules, and it will raise an error according to overload set resolution rule.
std\process.d(367): Error: std.file.remove at std\file.d(413) conflicts with core.stdc.stdio.remove at C:\Users\khara\dmd2\src\druntime\import\core\stdc\stdio.d(453)
----
So as a conclusion, we should just remove the deprecated "array to pointer conversion" feature, rather than fixing broken deprecated feature that already outdated.
Comment #4 by bearophile_hugs — 2013-02-21T18:22:08Z
From the commit:
> the deprecated implicit conversion feature already being a cancer in D2 type system.
Thank you Hara for fixing such things. Implicit type conversions are dangerous.
Comment #5 by andrej.mitrovich — 2013-03-01T13:19:34Z
Another person has ran into this recently.
Shouldn't this be a good reason for an emergency release of a patched 2.062? It's really an awful bug.
Comment #6 by k.hara.pg — 2013-04-10T22:01:32Z
*** Issue 9518 has been marked as a duplicate of this issue. ***
Comment #7 by k.hara.pg — 2013-04-11T01:54:36Z
*** Issue 9916 has been marked as a duplicate of this issue. ***
Comment #8 by andrej.mitrovich — 2013-05-13T06:51:28Z
*** Issue 10072 has been marked as a duplicate of this issue. ***