diff --git a/src/mtype.c b/src/mtype.c index 87850601ba08..fefad7822ff4 100644 --- a/src/mtype.c +++ b/src/mtype.c @@ -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; } } diff --git a/test/compilable/warn3882.d b/test/compilable/warn3882.d new file mode 100644 index 000000000000..07e145ee6c13 --- /dev/null +++ b/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(); +} diff --git a/test/fail_compilation/fail3882.d b/test/fail_compilation/fail3882.d index fa008eb8127b..b7d8a9789a90 100644 --- a/test/fail_compilation/fail3882.d +++ b/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; @@ -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 @@ -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); }