Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue 12909 & 12910 - fix purity level calculation for AA parameter #3667

Merged
merged 4 commits into from
Jun 14, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
127 changes: 66 additions & 61 deletions src/mtype.c
Original file line number Diff line number Diff line change
Expand Up @@ -5770,71 +5770,76 @@ Type *TypeFunction::semantic(Loc loc, Scope *sc)
void TypeFunction::purityLevel()
{
TypeFunction *tf = this;
if (tf->purity == PUREfwdref)
{ /* Evaluate what kind of purity based on the modifiers for the parameters
if (tf->purity != PUREfwdref)
return;

/* Evaluate what kind of purity based on the modifiers for the parameters
*/
tf->purity = PUREstrong; // assume strong until something weakens it

size_t dim = Parameter::dim(tf->parameters);
if (!dim)
return;
for (size_t i = 0; i < dim; i++)
{
Parameter *fparam = Parameter::getNth(tf->parameters, i);
Type *t = fparam->type;
if (!t)
continue;

if (fparam->storageClass & (STClazy | STCout))
{
tf->purity = PUREweak;
break;
}
if (fparam->storageClass & STCref)
{
if (t->mod & MODimmutable)
continue;
if (t->mod & (MODconst | MODwild))
{
tf->purity = PUREconst;
continue;
}
tf->purity = PUREweak;
break;
}

t = t->baseElemOf();
if (!t->hasPointers())
continue;
if (t->mod & MODimmutable)
continue;

/* Accept immutable(T)[] and immutable(T)* as being strongly pure
*/
tf->purity = PUREstrong; // assume strong until something weakens it
if (tf->parameters)
if (t->ty == Tarray || t->ty == Tpointer)
{
size_t dim = Parameter::dim(tf->parameters);
for (size_t i = 0; i < dim; i++)
{ Parameter *fparam = Parameter::getNth(tf->parameters, i);
if (fparam->storageClass & STClazy)
{
tf->purity = PUREweak;
break;
}
if (fparam->storageClass & STCout)
{
tf->purity = PUREweak;
break;
}
if (!fparam->type)
continue;
if (fparam->storageClass & STCref)
{
if (!(fparam->type->mod & (MODconst | MODimmutable | MODwild)))
{ tf->purity = PUREweak;
break;
}
if (fparam->type->mod & MODconst)
{ tf->purity = PUREconst;
continue;
}
}
Type *t = fparam->type->toBasetype();
if (!t->hasPointers())
continue;
if (t->mod & MODimmutable)
continue;
/* The rest of this is too strict; fix later.
* For example, the only pointer members of a struct may be immutable,
* which would maintain strong purity.
*/
if (t->mod & (MODconst | MODwild))
{ tf->purity = PUREconst;
continue;
}
Type *tn = t->nextOf();
if (tn)
{ tn = tn->toBasetype();
if (tn->ty == Tpointer || tn->ty == Tarray)
{ /* Accept immutable(T)* and immutable(T)[] as being strongly pure
*/
if (tn->mod & MODimmutable)
continue;
if (tn->mod & (MODconst | MODwild))
{ tf->purity = PUREconst;
continue;
}
}
}
/* Should catch delegates and function pointers, and fold in their purity
*/
tf->purity = PUREweak; // err on the side of too strict
break;
Type *tn = t->nextOf()->toBasetype();
if (tn->mod & MODimmutable)
continue;
if (tn->mod & (MODconst | MODwild))
{
tf->purity = PUREconst;
continue;
}
}

/* The rest of this is too strict; fix later.
* For example, the only pointer members of a struct may be immutable,
* which would maintain strong purity.
*/
if (t->mod & (MODconst | MODwild))
{
tf->purity = PUREconst;
continue;
}

/* Should catch delegates and function pointers, and fold in their purity
*/

tf->purity = PUREweak; // err on the side of too strict
break;
}
}

Expand Down
66 changes: 66 additions & 0 deletions test/compilable/warn3882.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
// PERMUTE_ARGS: -w -wi -debug
/*
TEST_OUTPUT:
---
---
*/

@safe pure nothrow void strictVoidReturn(T)(T x) {}
@safe pure nothrow void nonstrictVoidReturn(T)(ref T x) {}

void main()
{
int x = 3;
strictVoidReturn(x);
nonstrictVoidReturn(x);
}

/******************************************/
// 12619

extern (C) @system nothrow pure void* memcpy(void* s1, in void* s2, size_t n);
// -> weakly pure

void test12619() pure
{
ubyte[10] a, b;
debug memcpy(a.ptr, b.ptr, 5); // memcpy call should have side effect
}

/******************************************/
// 12760

struct S12760(T)
{
T i;
this(T j) inout {}
}

struct K12760
{
S12760!int nullable;

this(int)
{
nullable = 0; // weak purity
}
}

/******************************************/
// 12909

int f12909(immutable(int[])[int] aa) pure nothrow
{
aa[0] = [];
return 0;
}

void test12909()
{
immutable(int[])[int] aa;
f12909(aa);

// from 12910
const(int[])[int] makeAA() { return null; } // to make r-value
makeAA().rehash();
}
55 changes: 19 additions & 36 deletions test/fail_compilation/fail3882.d
Original file line number Diff line number Diff line change
@@ -1,21 +1,17 @@
// REQUIRED_ARGS: -w
// PERMUTE_ARGS: -debug

/******************************************/
// 3882

/*
TEST_OUTPUT:
---
fail_compilation/fail3882.d(29): Warning: calling fail3882.strictlyPure!int.strictlyPure without side effects discards return value of type int, prepend a cast(void) if intentional
fail_compilation/fail3882.d(33): Warning: calling fp without side effects discards return value of type int, prepend a cast(void) if intentional
fail_compilation/fail3882.d(23): Warning: calling fail3882.strictlyPure!int.strictlyPure without side effects discards return value of type int, prepend a cast(void) if intentional
fail_compilation/fail3882.d(27): Warning: calling fp without side effects discards return value of type int, prepend a cast(void) if intentional
---
*/

@safe pure nothrow void strictVoidReturn(T)(T x)
{
}

@safe pure nothrow void nonstrictVoidReturn(T)(ref T x)
{
}

@safe pure nothrow T strictlyPure(T)(T x)
{
return x*x;
Expand All @@ -24,8 +20,6 @@ fail_compilation/fail3882.d(33): Warning: calling fp without side effects discar
void main()
{
int x = 3;
strictVoidReturn(x);
nonstrictVoidReturn(x);
strictlyPure(x);

// 12649
Expand All @@ -34,32 +28,21 @@ void main()
}

/******************************************/
// 12619

extern (C) @system nothrow pure void* memcpy(void* s1, in void* s2, size_t n);
// -> weakly pure

void test12619() pure
{
ubyte[10] a, b;
debug memcpy(a.ptr, b.ptr, 5); // memcpy call should have side effect
}
// bugfix in TypeFunction::purityLevel

/******************************************/
// 12760
/*
TEST_OUTPUT:
---
fail_compilation/fail3882.d(46): Warning: calling fail3882.f1 without side effects discards return value of type int, prepend a cast(void) if intentional
fail_compilation/fail3882.d(47): Warning: calling fail3882.f2 without side effects discards return value of type int, prepend a cast(void) if intentional
---
*/

struct S12760(T)
{
T i;
this(T j) inout {}
}
nothrow pure int f1(immutable(int)[] a) { return 0; }
nothrow pure int f2(immutable(int)* p) { return 0; }

struct K12760
void test_bug()
{
S12760!int nullable;

this(int)
{
nullable = 0; // weak purity
}
f1([]);
f2(null);
}