diff gcc/d/dmd/staticcond.c @ 145:1830386684a0

gcc-9.2.0
author anatofuz
date Thu, 13 Feb 2020 11:34:05 +0900
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gcc/d/dmd/staticcond.c	Thu Feb 13 11:34:05 2020 +0900
@@ -0,0 +1,100 @@
+
+/* Compiler implementation of the D programming language
+ * Copyright (C) 1999-2019 by The D Language Foundation, All Rights Reserved
+ * written by Walter Bright
+ * http://www.digitalmars.com
+ * Distributed under the Boost Software License, Version 1.0.
+ * http://www.boost.org/LICENSE_1_0.txt
+ * https://github.com/D-Programming-Language/dmd/blob/master/src/staticcond.c
+ */
+
+#include "mars.h"
+#include "expression.h"
+#include "mtype.h"
+#include "scope.h"
+
+Expression *semantic(Expression *e, Scope *sc);
+
+/********************************************
+ * Semantically analyze and then evaluate a static condition at compile time.
+ * This is special because short circuit operators &&, || and ?: at the top
+ * level are not semantically analyzed if the result of the expression is not
+ * necessary.
+ * Params:
+ *      exp = original expression, for error messages
+ * Returns:
+ *      true if evaluates to true
+ */
+
+bool evalStaticCondition(Scope *sc, Expression *exp, Expression *e, bool &errors)
+{
+    if (e->op == TOKandand)
+    {
+        AndAndExp *aae = (AndAndExp *)e;
+        bool result = evalStaticCondition(sc, exp, aae->e1, errors);
+        if (errors || !result)
+            return false;
+        result = evalStaticCondition(sc, exp, aae->e2, errors);
+        return !errors && result;
+    }
+
+    if (e->op == TOKoror)
+    {
+        OrOrExp *ooe = (OrOrExp *)e;
+        bool result = evalStaticCondition(sc, exp, ooe->e1, errors);
+        if (errors)
+            return false;
+        if (result)
+            return true;
+        result = evalStaticCondition(sc, exp, ooe->e2, errors);
+        return !errors && result;
+    }
+
+    if (e->op == TOKquestion)
+    {
+        CondExp *ce = (CondExp *)e;
+        bool result = evalStaticCondition(sc, exp, ce->econd, errors);
+        if (errors)
+            return false;
+        Expression *leg = result ? ce->e1 : ce->e2;
+        result = evalStaticCondition(sc, exp, leg, errors);
+        return !errors && result;
+    }
+
+    unsigned nerrors = global.errors;
+
+    sc = sc->startCTFE();
+    sc->flags |= SCOPEcondition;
+
+    e = semantic(e, sc);
+    e = resolveProperties(sc, e);
+
+    sc = sc->endCTFE();
+    e = e->optimize(WANTvalue);
+
+    if (nerrors != global.errors ||
+        e->op == TOKerror ||
+        e->type->toBasetype() == Type::terror)
+    {
+        errors = true;
+        return false;
+    }
+
+    if (!e->type->isBoolean())
+    {
+        exp->error("expression %s of type %s does not have a boolean value", exp->toChars(), e->type->toChars());
+        errors = true;
+        return false;
+    }
+
+    e = e->ctfeInterpret();
+
+    if (e->isBool(true))
+        return true;
+    else if (e->isBool(false))
+        return false;
+
+    e->error("expression %s is not constant", e->toChars());
+    errors = true;
+    return false;
+}