1 
2 /* Compiler implementation of the D programming language
3  * Copyright (C) 1999-2019 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/staticassert.c
9  */
10 
11 #include "root/dsystem.h"
12 
13 #include "mars.h"
14 #include "dsymbol.h"
15 #include "staticassert.h"
16 #include "expression.h"
17 #include "id.h"
18 #include "scope.h"
19 #include "template.h"
20 #include "declaration.h"
21 
22 Expression *semantic(Expression *e, Scope *sc);
23 bool evalStaticCondition(Scope *sc, Expression *exp, Expression *e, bool &errors);
24 
25 /********************************* AttribDeclaration ****************************/
26 
StaticAssert(Loc loc,Expression * exp,Expression * msg)27 StaticAssert::StaticAssert(Loc loc, Expression *exp, Expression *msg)
28         : Dsymbol(Id::empty)
29 {
30     this->loc = loc;
31     this->exp = exp;
32     this->msg = msg;
33 }
34 
syntaxCopy(Dsymbol * s)35 Dsymbol *StaticAssert::syntaxCopy(Dsymbol *s)
36 {
37     assert(!s);
38     return new StaticAssert(loc, exp->syntaxCopy(), msg ? msg->syntaxCopy() : NULL);
39 }
40 
addMember(Scope *,ScopeDsymbol *)41 void StaticAssert::addMember(Scope *, ScopeDsymbol *)
42 {
43     // we didn't add anything
44 }
45 
semantic(Scope *)46 void StaticAssert::semantic(Scope *)
47 {
48 }
49 
semantic2(Scope * sc)50 void StaticAssert::semantic2(Scope *sc)
51 {
52     //printf("StaticAssert::semantic2() %s\n", toChars());
53     ScopeDsymbol *sds = new ScopeDsymbol();
54     sc = sc->push(sds);
55     sc->tinst = NULL;
56     sc->minst = NULL;
57 
58     bool errors = false;
59     bool result = evalStaticCondition(sc, exp, exp, errors);
60     sc = sc->pop();
61     if (errors)
62     {
63         errorSupplemental(loc, "while evaluating: static assert(%s)", exp->toChars());
64     }
65     else if (!result)
66     {
67         if (msg)
68         {
69             sc = sc->startCTFE();
70             msg = ::semantic(msg, sc);
71             msg = resolveProperties(sc, msg);
72             sc = sc->endCTFE();
73             msg = msg->ctfeInterpret();
74             if (StringExp * se = msg->toStringExp())
75             {
76                 // same with pragma(msg)
77                 se = se->toUTF8(sc);
78                 error("\"%.*s\"", (int)se->len, (char *)se->string);
79             }
80             else
81                 error("%s", msg->toChars());
82         }
83         else
84             error("(%s) is false", exp->toChars());
85         if (sc->tinst)
86             sc->tinst->printInstantiationTrace();
87         if (!global.gag)
88               fatal();
89     }
90 }
91 
oneMember(Dsymbol ** ps,Identifier *)92 bool StaticAssert::oneMember(Dsymbol **ps, Identifier *)
93 {
94     //printf("StaticAssert::oneMember())\n");
95     *ps = NULL;
96     return true;
97 }
98 
kind()99 const char *StaticAssert::kind() const
100 {
101     return "static assert";
102 }
103