[Issue 18792] New: Incorrect scope analysis with -dip1000 for small-sized-optimized string
d-bugmail at puremagic.com
d-bugmail at puremagic.com
Mon Apr 23 09:46:43 UTC 2018
https://issues.dlang.org/show_bug.cgi?id=18792
Issue ID: 18792
Summary: Incorrect scope analysis with -dip1000 for
small-sized-optimized string
Product: D
Version: D2
Hardware: All
OS: All
Status: NEW
Severity: normal
Priority: P1
Component: dmd
Assignee: nobody at puremagic.com
Reporter: per.nordlow at gmail.com
The following code should fail to compile in functions shouldFail1 and
shouldFail2 when compiled with flag -dip1000:
/** Small-size-optimized (SSO) variant of `string`.
*
* Store on the stack if constructed with <= `smallCapacity` number of
* characters, otherwise on the GC heap.
*
* See_Also: https://forum.dlang.org/post/pb87rn$2icb$1@digitalmars.com
*/
struct SSOString
{
private alias E = immutable(char); // immutable element type
pure nothrow @nogc:
scope E[] opSlice() const return @trusted // TODO @safe for -dip1000?
{
if (isLarge)
{
union RawLarge
{
Raw raw;
Large large;
}
RawLarge copy = void;
copy.large = cast(Large)large;
copy.raw.length /= 2; // adjust length
return copy.large;
}
else
{
return small.data[0 .. small.length/2]; // scoped. TODO use .ptr
when proved stable
}
}
/// ditto
scope E[] opSlice(size_t i, size_t j) const return @trusted // TODO @safe
for -dip1000?
{
return opSlice()[i .. j];
}
private:
/** Returns: `true` iff this is a large string, otherwise `false.` */
@property bool isLarge() const @trusted
{
return large.length & 1; // first bit discriminates small from large
}
struct Raw // same memory layout as `E[]`
{
size_t length; // can be bit-fiddled without GC allocation
E* ptr;
}
alias Large = E[];
enum smallCapacity = Large.sizeof - Small.length.sizeof;
static assert(smallCapacity > 0, "No room for small source for E being " ~
E.stringof);
version(LittleEndian) // see:
http://forum.dlang.org/posting/zifyahfohbwavwkwbgmw
{
struct Small
{
ubyte length; // TODO only first 4 bits are needed to represent a
length between 0-15, use other 4 bits
E[smallCapacity] data;
}
}
else
{
static assert(0, "TODO Add BigEndian support and test");
}
union
{
Raw raw;
Large large;
Small small;
}
}
///
@safe pure nothrow @nogc unittest
{
string shouldFail1() @safe pure nothrow @nogc
{
SSOString x;
return x[]; // TODO should fail with -dip1000
}
string shouldFail2() @safe pure nothrow @nogc
{
SSOString x;
return x[0 .. 0]; // TODO should fail with -dip1000
}
}
--
More information about the Digitalmars-d-bugs
mailing list