Пример #1
0
        void visit(Expression *e)
        {
            /* Bugzilla 11201: CallExp is always non trivial expression,
             * especially for inlining.
             */
            if (e->op == TOKcall)
            {
                stop = true;
                return;
            }

            // stop walking if we determine this expression has side effects
            stop = lambdaHasSideEffect(e);
        }
Пример #2
0
 void visit(Expression *e)
 {
     // stop walking if we determine this expression has side effects
     stop = lambdaHasSideEffect(e);
 }
Пример #3
0
/***********************************
 * The result of this expression will be discarded.
 * Print error messages if the operation has no side effects (and hence is meaningless).
 * Returns:
 *      true if expression has no side effects
 */
bool discardValue(Expression *e)
{
    if (lambdaHasSideEffect(e))     // check side-effect shallowly
        return false;
    switch (e->op)
    {
        case TOKcast:
        {
            CastExp *ce = (CastExp *)e;
            if (ce->to->equals(Type::tvoid))
            {
                /*
                 * Don't complain about an expression with no effect if it was cast to void
                 */
                return false;
            }
            break;          // complain
        }

        case TOKerror:
            return false;

        case TOKvar:
        {
            VarDeclaration *v = ((VarExp *)e)->var->isVarDeclaration();
            if (v && (v->storage_class & STCtemp))
            {
                // Bugzilla 5810: Don't complain about an internal generated variable.
                return false;
            }
            break;
        }
        case TOKcall:
            /* Issue 3882: */
            if (global.params.warnings != DIAGNOSTICoff && !global.gag)
            {
                CallExp *ce = (CallExp *)e;
                if (e->type->ty == Tvoid)
                {
                    /* Don't complain about calling void-returning functions with no side-effect,
                     * because purity and nothrow are inferred, and because some of the
                     * runtime library depends on it. Needs more investigation.
                     *
                     * One possible solution is to restrict this message to only be called in hierarchies that
                     * never call assert (and or not called from inside unittest blocks)
                     */
                }
                else if (ce->e1->type)
                {
                    Type *t = ce->e1->type->toBasetype();
                    if (t->ty == Tdelegate)
                        t = ((TypeDelegate *)t)->next;
                    if (t->ty == Tfunction &&
                        (ce->f ? callSideEffectLevel(ce->f)
                               : callSideEffectLevel(ce->e1->type)) > 0)
                    {
                        const char *s;
                        if (ce->f)
                            s = ce->f->toPrettyChars();
                        else if (ce->e1->op == TOKstar)
                        {
                            // print 'fp' if ce->e1 is (*fp)
                            s = ((PtrExp *)ce->e1)->e1->toChars();
                        }
                        else
                            s = ce->e1->toChars();

                        e->warning("calling %s without side effects discards return value of type %s, prepend a cast(void) if intentional",
                                   s, e->type->toChars());
                    }
                }
            }
            return false;

        case TOKscope:
            e->error("%s has no effect", e->toChars());
            return true;

        case TOKandand:
        {
            AndAndExp *aae = (AndAndExp *)e;
            return discardValue(aae->e2);
        }

        case TOKoror:
        {
            OrOrExp *ooe = (OrOrExp *)e;
            return discardValue(ooe->e2);
        }

        case TOKquestion:
        {
            CondExp *ce = (CondExp *)e;

            /* Bugzilla 6178 & 14089: Either CondExp::e1 or e2 may have
             * redundant expression to make those types common. For example:
             *
             *  struct S { this(int n); int v; alias v this; }
             *  S[int] aa;
             *  aa[1] = 0;
             *
             * The last assignment statement will be rewitten to:
             *
             *  1 in aa ? aa[1].value = 0 : (aa[1] = 0, aa[1].this(0)).value;
             *
             * The last DotVarExp is necessary to take assigned value.
             *
             *  int value = (aa[1] = 0);    // value = aa[1].value
             *
             * To avoid false error, discardValue() should be called only when
             * the both tops of e1 and e2 have actually no side effects.
             */
            if (!lambdaHasSideEffect(ce->e1) &&
                !lambdaHasSideEffect(ce->e2))
            {
                return discardValue(ce->e1) |
                       discardValue(ce->e2);
            }
            return false;
        }

        case TOKcomma:
        {
            CommaExp *ce = (CommaExp *)e;
            /* Check for compiler-generated code of the form  auto __tmp, e, __tmp;
             * In such cases, only check e for side effect (it's OK for __tmp to have
             * no side effect).
             * See Bugzilla 4231 for discussion
             */
            CommaExp *firstComma = ce;
            while (firstComma->e1->op == TOKcomma)
                firstComma = (CommaExp *)firstComma->e1;
            if (firstComma->e1->op == TOKdeclaration &&
                ce->e2->op == TOKvar &&
                ((DeclarationExp *)firstComma->e1)->declaration == ((VarExp*)ce->e2)->var)
            {
                return false;
            }
            // Don't check e1 until we cast(void) the a,b code generation
            //discardValue(ce->e1);
            return discardValue(ce->e2);
        }

        case TOKtuple:
            /* Pass without complaint if any of the tuple elements have side effects.
             * Ideally any tuple elements with no side effects should raise an error,
             * this needs more investigation as to what is the right thing to do.
             */
            if (!hasSideEffect(e))
                break;
            return false;

        default:
            break;
    }
    e->error("%s has no effect in expression (%s)", Token::toChars(e->op), e->toChars());
    return true;
}
Пример #4
0
/***********************************
 * The result of this expression will be discarded.
 * Complain if the operation has no side effects (and hence is meaningless).
 */
void Expression::discardValue()
{
    bool has = FALSE;
    lambdaHasSideEffect(this, &has);
    if (!has)
    {
        switch (op)
        {
            case TOKcast:
            {   CastExp *ce = (CastExp *)this;
                if (ce->to->equals(Type::tvoid))
                {   /*
                     * Don't complain about an expression with no effect if it was cast to void
                     */
                    ce->e1->useValue();
                    break;
                }
                goto Ldefault;          // complain
            }

            case TOKerror:
                break;

            case TOKcall:
                /* Don't complain about calling functions with no effect,
                 * because purity and nothrow are inferred, and because some of the
                 * runtime library depends on it. Needs more investigation.
                 */
                break;

            case TOKimport:
                error("%s has no effect", toChars());
                break;

            case TOKandand:
            {   AndAndExp *aae = (AndAndExp *)this;
                aae->e1->useValue();
                aae->e2->discardValue();
                break;
            }

            case TOKoror:
            {   OrOrExp *ooe = (OrOrExp *)this;
                ooe->e1->useValue();
                ooe->e2->discardValue();
                break;
            }

            case TOKquestion:
            {   CondExp *ce = (CondExp *)this;
                ce->econd->useValue();
                ce->e1->discardValue();
                ce->e2->discardValue();
                break;
            }

            case TOKcomma:
            {   CommaExp *ce = (CommaExp *)this;

                /* Check for compiler-generated code of the form  auto __tmp, e, __tmp;
                 * In such cases, only check e for side effect (it's OK for __tmp to have
                 * no side effect).
                 * See Bugzilla 4231 for discussion
                 */
                CommaExp* firstComma = ce;
                while (firstComma->e1->op == TOKcomma)
                    firstComma = (CommaExp *)firstComma->e1;
                if (firstComma->e1->op == TOKdeclaration &&
                    ce->e2->op == TOKvar &&
                    ((DeclarationExp *)firstComma->e1)->declaration == ((VarExp*)ce->e2)->var)
                {
                    ce->e1->useValue();
                    break;
                }
                // Don't check e1 until we cast(void) the a,b code generation
                //ce->e1->discardValue();
                ce->e2->discardValue();
                break;
            }

            case TOKtuple:
                /* Pass without complaint if any of the tuple elements have side effects.
                 * Ideally any tuple elements with no side effects should raise an error,
                 * this needs more investigation as to what is the right thing to do.
                 */
                if (!hasSideEffect())
                    goto Ldefault;
                break;

            default:
            Ldefault:
                error("%s has no effect in expression (%s)",
                    Token::toChars(op), toChars());
                break;
        }
    }
    else
    {
        useValue();
    }
}