1 
2 /* Compiler implementation of the D programming language
3  * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
4  * written by Walter Bright
5  * http://www.digitalmars.com
6  * Distributed under the Boost Software License, Version 1.0.
7  * http://www.boost.org/LICENSE_1_0.txt
8  * https://github.com/D-Programming-Language/dmd/blob/master/src/staticcond.c
9  */
10 
11 #include "mars.h"
12 #include "expression.h"
13 #include "mtype.h"
14 #include "scope.h"
15 
16 /********************************************
17  * Semantically analyze and then evaluate a static condition at compile time.
18  * This is special because short circuit operators &&, || and ?: at the top
19  * level are not semantically analyzed if the result of the expression is not
20  * necessary.
21  * Params:
22  *      exp = original expression, for error messages
23  * Returns:
24  *      true if evaluates to true
25  */
26 
evalStaticCondition(Scope * sc,Expression * exp,Expression * e,bool & errors)27 bool evalStaticCondition(Scope *sc, Expression *exp, Expression *e, bool &errors)
28 {
29     if (e->op == TOKandand || e->op == TOKoror)
30     {
31         LogicalExp *aae = (LogicalExp *)e;
32         bool result = evalStaticCondition(sc, exp, aae->e1, errors);
33         if (errors)
34             return false;
35         if (e->op == TOKandand)
36         {
37             if (!result)
38                 return false;
39         }
40         else
41         {
42             if (result)
43                 return true;
44         }
45         result = evalStaticCondition(sc, exp, aae->e2, errors);
46         return !errors && result;
47     }
48 
49     if (e->op == TOKquestion)
50     {
51         CondExp *ce = (CondExp *)e;
52         bool result = evalStaticCondition(sc, exp, ce->econd, errors);
53         if (errors)
54             return false;
55         Expression *leg = result ? ce->e1 : ce->e2;
56         result = evalStaticCondition(sc, exp, leg, errors);
57         return !errors && result;
58     }
59 
60     unsigned nerrors = global.errors;
61 
62     sc = sc->startCTFE();
63     sc->flags |= SCOPEcondition;
64 
65     e = expressionSemantic(e, sc);
66     e = resolveProperties(sc, e);
67 
68     sc = sc->endCTFE();
69     e = e->optimize(WANTvalue);
70 
71     if (nerrors != global.errors ||
72         e->op == TOKerror ||
73         e->type->toBasetype() == Type::terror)
74     {
75         errors = true;
76         return false;
77     }
78 
79     if (!e->type->isBoolean())
80     {
81         exp->error("expression %s of type %s does not have a boolean value", exp->toChars(), e->type->toChars());
82         errors = true;
83         return false;
84     }
85 
86     e = e->ctfeInterpret();
87 
88     if (e->isBool(true))
89         return true;
90     else if (e->isBool(false))
91         return false;
92 
93     e->error("expression %s is not constant", e->toChars());
94     errors = true;
95     return false;
96 }
97