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 }