1 /**
2  * Compiler implementation of the
3  * $(LINK2 http://www.dlang.org, D programming language).
4  *
5  * Copyright:   Copyright (c) 1999-2016 by Digital Mars, All Rights Reserved
6  * Authors:     $(LINK2 http://www.digitalmars.com, Walter Bright)
7  * License:     $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
8  * Source:      $(DMDSRC _staticassert.d)
9  */
10 
11 module ddmd.staticassert;
12 
13 import ddmd.dscope;
14 import ddmd.dsymbol;
15 import ddmd.errors;
16 import ddmd.expression;
17 import ddmd.globals;
18 import ddmd.id;
19 import ddmd.identifier;
20 import ddmd.mtype;
21 import ddmd.visitor;
22 
23 /***********************************************************
24  */
25 extern (C++) final class StaticAssert : Dsymbol
26 {
27     Expression exp;
28     Expression msg;
29 
30     extern (D) this(Loc loc, Expression exp, Expression msg)
31     {
32         super(Id.empty);
33         this.loc = loc;
34         this.exp = exp;
35         this.msg = msg;
36     }
37 
38     override Dsymbol syntaxCopy(Dsymbol s)
39     {
40         assert(!s);
41         return new StaticAssert(loc, exp.syntaxCopy(), msg ? msg.syntaxCopy() : null);
42     }
43 
44     override void addMember(Scope* sc, ScopeDsymbol sds)
45     {
46         // we didn't add anything
47     }
48 
49     override void semantic(Scope* sc)
50     {
51     }
52 
53     override void semantic2(Scope* sc)
54     {
55         //printf("StaticAssert::semantic2() %s\n", toChars());
56         auto sds = new ScopeDsymbol();
57         sc = sc.push(sds);
58         sc.tinst = null;
59         sc.minst = null;
60         sc.flags |= SCOPEcondition;
61         sc = sc.startCTFE();
62         Expression e = exp.semantic(sc);
63         e = resolveProperties(sc, e);
64         sc = sc.endCTFE();
65         sc = sc.pop();
66         // Simplify expression, to make error messages nicer if CTFE fails
67         e = e.optimize(WANTvalue);
68         if (!e.type.isBoolean())
69         {
70             if (e.type.toBasetype() != Type.terror)
71                 exp.error("expression %s of type %s does not have a boolean value", exp.toChars(), e.type.toChars());
72             return;
73         }
74         uint olderrs = global.errors;
75         e = e.ctfeInterpret();
76         if (global.errors != olderrs)
77         {
78             errorSupplemental(loc, "while evaluating: static assert(%s)", exp.toChars());
79         }
80         else if (e.isBool(false))
81         {
82             if (msg)
83             {
84                 sc = sc.startCTFE();
85                 msg = msg.semantic(sc);
86                 msg = resolveProperties(sc, msg);
87                 sc = sc.endCTFE();
88                 msg = msg.ctfeInterpret();
89                 if (StringExp se = msg.toStringExp())
90                 {
91                     // same with pragma(msg)
92                     se = se.toUTF8(sc);
93                     error("\"%.*s\"", cast(int)se.len, se..string);
94                 }
95                 else
96                     error("%s", msg.toChars());
97             }
98             else
99                 error("(%s) is false", exp.toChars());
100             if (sc.tinst)
101                 sc.tinst.printInstantiationTrace();
102             if (!global.gag)
103                 fatal();
104         }
105         else if (!e.isBool(true))
106         {
107             error("(%s) is not evaluatable at compile time", exp.toChars());
108         }
109     }
110 
111     override bool oneMember(Dsymbol* ps, Identifier ident)
112     {
113         //printf("StaticAssert::oneMember())\n");
114         *ps = null;
115         return true;
116     }
117 
118     override const(char)* kind() const
119     {
120         return "static assert";
121     }
122 
123     override void accept(Visitor v)
124     {
125         v.visit(this);
126     }
127 }