Skip to content

Commit

Permalink
Merge pull request #3667 from 9rnsr/fix12909
Browse files Browse the repository at this point in the history
Issue 12909 & 12910 - fix purity level calculation for AA parameter
  • Loading branch information
dnadlinger committed Jun 14, 2014
2 parents 7d363bb + fd44afb commit 27fc066
Show file tree
Hide file tree
Showing 3 changed files with 151 additions and 97 deletions.
127 changes: 66 additions & 61 deletions src/mtype.c
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
@@ -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
@@ -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);
}

0 comments on commit 27fc066

Please sign in to comment.