0
|
1 module dmd.DeclarationExp;
|
|
2
|
|
3 import dmd.Expression;
|
|
4 import dmd.backend.elem;
|
|
5 import dmd.InterState;
|
|
6 import dmd.ExpInitializer;
|
|
7 import dmd.OutBuffer;
|
|
8 import dmd.Loc;
|
|
9 import dmd.Scope;
|
|
10 import dmd.InlineCostState;
|
|
11 import dmd.IRState;
|
|
12 import dmd.InlineDoState;
|
|
13 import dmd.HdrGenState;
|
|
14 import dmd.TupleDeclaration;
|
|
15 import dmd.InlineScanState;
|
|
16 import dmd.Dsymbol;
|
|
17 import dmd.AttribDeclaration;
|
|
18 import dmd.VarDeclaration;
|
|
19 import dmd.Global;
|
|
20 import dmd.TOK;
|
|
21 import dmd.VoidInitializer;
|
|
22 import dmd.Type;
|
|
23 import dmd.codegen.Util;
|
|
24
|
|
25 // Declaration of a symbol
|
|
26
|
|
27 class DeclarationExp : Expression
|
|
28 {
|
|
29 Dsymbol declaration;
|
|
30
|
|
31 this(Loc loc, Dsymbol declaration)
|
|
32 {
|
|
33 super(loc, TOK.TOKdeclaration, DeclarationExp.sizeof);
|
|
34 this.declaration = declaration;
|
|
35 }
|
|
36
|
|
37 Expression syntaxCopy()
|
|
38 {
|
|
39 return new DeclarationExp(loc, declaration.syntaxCopy(null));
|
|
40 }
|
|
41
|
|
42 Expression semantic(Scope sc)
|
|
43 {
|
|
44 if (type)
|
|
45 return this;
|
|
46
|
|
47 version (LOGSEMANTIC) {
|
|
48 printf("DeclarationExp.semantic() %s\n", toChars());
|
|
49 }
|
|
50
|
|
51 /* This is here to support extern(linkage) declaration,
|
|
52 * where the extern(linkage) winds up being an AttribDeclaration
|
|
53 * wrapper.
|
|
54 */
|
|
55 Dsymbol s = declaration;
|
|
56
|
|
57 AttribDeclaration ad = declaration.isAttribDeclaration();
|
|
58 if (ad)
|
|
59 {
|
|
60 if (ad.decl && ad.decl.dim == 1)
|
|
61 s = cast(Dsymbol)ad.decl.data[0];
|
|
62 }
|
|
63
|
|
64 if (s.isVarDeclaration())
|
|
65 {
|
|
66 // Do semantic() on initializer first, so:
|
|
67 // int a = a;
|
|
68 // will be illegal.
|
|
69 declaration.semantic(sc);
|
|
70 s.parent = sc.parent;
|
|
71 }
|
|
72
|
|
73 //printf("inserting '%s' %p into sc = %p\n", s.toChars(), s, sc);
|
|
74 // Insert into both local scope and function scope.
|
|
75 // Must be unique in both.
|
|
76 if (s.ident)
|
|
77 {
|
|
78 if (!sc.insert(s))
|
|
79 error("declaration %s is already defined", s.toPrettyChars());
|
|
80 else if (sc.func)
|
|
81 {
|
|
82 VarDeclaration v = s.isVarDeclaration();
|
|
83 if (s.isFuncDeclaration() && !sc.func.localsymtab.insert(s))
|
|
84 error("declaration %s is already defined in another scope in %s", s.toPrettyChars(), sc.func.toChars());
|
|
85 else if (!global.params.useDeprecated)
|
|
86 {
|
|
87 // Disallow shadowing
|
|
88
|
|
89 for (Scope scx = sc.enclosing; scx && scx.func is sc.func; scx = scx.enclosing)
|
|
90 {
|
|
91 Dsymbol s2;
|
|
92
|
|
93 if (scx.scopesym && scx.scopesym.symtab && (s2 = scx.scopesym.symtab.lookup(s.ident)) !is null && s !is s2)
|
|
94 {
|
|
95 error("shadowing declaration %s is deprecated", s.toPrettyChars());
|
|
96 }
|
|
97 }
|
|
98 }
|
|
99 }
|
|
100 }
|
|
101 if (!s.isVarDeclaration())
|
|
102 {
|
|
103 declaration.semantic(sc);
|
|
104 s.parent = sc.parent;
|
|
105 }
|
|
106 if (!global.errors)
|
|
107 {
|
|
108 declaration.semantic2(sc);
|
|
109 if (!global.errors)
|
|
110 {
|
|
111 declaration.semantic3(sc);
|
|
112
|
|
113 if (!global.errors && global.params.useInline)
|
|
114 declaration.inlineScan();
|
|
115 }
|
|
116 }
|
|
117
|
|
118 type = Type.tvoid;
|
|
119 return this;
|
|
120 }
|
|
121
|
|
122 Expression interpret(InterState* istate)
|
|
123 {
|
|
124 assert(false);
|
|
125 }
|
|
126
|
|
127 bool checkSideEffect(int flag)
|
|
128 {
|
|
129 return true;
|
|
130 }
|
|
131
|
|
132 void toCBuffer(OutBuffer buf, HdrGenState* hgs)
|
|
133 {
|
|
134 declaration.toCBuffer(buf, hgs);
|
|
135 }
|
|
136
|
|
137 elem* toElem(IRState* irs)
|
|
138 {
|
|
139 //printf("DeclarationExp::toElem() %s\n", toChars());
|
|
140 elem* e = Dsymbol_toElem(declaration, irs);
|
|
141 return e;
|
|
142 }
|
|
143
|
|
144 void scanForNestedRef(Scope sc)
|
|
145 {
|
|
146 assert(false);
|
|
147 }
|
|
148
|
|
149 version (DMDV2) {
|
|
150 bool canThrow()
|
|
151 {
|
|
152 VarDeclaration v = declaration.isVarDeclaration();
|
|
153 if (v && v.init)
|
|
154 {
|
|
155 ExpInitializer ie = v.init.isExpInitializer();
|
|
156 return ie && ie.exp.canThrow();
|
|
157 }
|
|
158
|
|
159 return false;
|
|
160 }
|
|
161 }
|
|
162 int inlineCost(InlineCostState* ics)
|
|
163 {
|
|
164 int cost = 0;
|
|
165 VarDeclaration vd;
|
|
166
|
|
167 //printf("DeclarationExp.inlineCost()\n");
|
|
168 vd = declaration.isVarDeclaration();
|
|
169 if (vd)
|
|
170 {
|
|
171 TupleDeclaration td = vd.toAlias().isTupleDeclaration();
|
|
172 if (td)
|
|
173 {
|
|
174 static if (true) {
|
|
175 return COST_MAX; // finish DeclarationExp.doInline
|
|
176 } else {
|
|
177 for (size_t i = 0; i < td.objects.dim; i++)
|
|
178 {
|
|
179 Object o = cast(Object)td.objects.data[i];
|
|
180 Expression eo = cast(Expression)o;
|
|
181 if (eo is null)
|
|
182 return COST_MAX;
|
|
183
|
|
184 if (eo.op != TOKdsymbol)
|
|
185 return COST_MAX;
|
|
186 }
|
|
187
|
|
188 return td.objects.dim;
|
|
189 }
|
|
190 }
|
|
191 if (!ics.hdrscan && vd.isDataseg())
|
|
192 return COST_MAX;
|
|
193
|
|
194 cost += 1;
|
|
195
|
|
196 // Scan initializer (vd.init)
|
|
197 if (vd.init)
|
|
198 {
|
|
199 ExpInitializer ie = vd.init.isExpInitializer();
|
|
200
|
|
201 if (ie)
|
|
202 {
|
|
203 cost += ie.exp.inlineCost(ics);
|
|
204 }
|
|
205 }
|
|
206 }
|
|
207
|
|
208 // These can contain functions, which when copied, get output twice.
|
|
209 if (declaration.isStructDeclaration() ||
|
|
210 declaration.isClassDeclaration() ||
|
|
211 declaration.isFuncDeclaration() ||
|
|
212 declaration.isTypedefDeclaration() ||
|
|
213 declaration.isTemplateMixin()
|
|
214 )
|
|
215 return COST_MAX;
|
|
216
|
|
217 //printf("DeclarationExp.inlineCost('%s')\n", toChars());
|
|
218 return cost;
|
|
219 }
|
|
220
|
|
221 Expression doInline(InlineDoState ids)
|
|
222 {
|
|
223 DeclarationExp de = cast(DeclarationExp)copy();
|
|
224 VarDeclaration vd;
|
|
225
|
|
226 //printf("DeclarationExp.doInline(%s)\n", toChars());
|
|
227 vd = declaration.isVarDeclaration();
|
|
228 if (vd)
|
|
229 {
|
|
230 static if (false) {
|
|
231 // Need to figure this out before inlining can work for tuples
|
|
232 TupleDeclaration td = vd.toAlias().isTupleDeclaration();
|
|
233 if (td)
|
|
234 {
|
|
235 for (size_t i = 0; i < td.objects.dim; i++)
|
|
236 {
|
|
237 DsymbolExp se = cast(DsymbolExp)td.objects.data[i];
|
|
238 assert(se.op == TOKdsymbol);
|
|
239 se.s;
|
|
240 }
|
|
241 return st.objects.dim;
|
|
242 }
|
|
243 }
|
|
244 if (vd.isStatic())
|
|
245 {
|
|
246 ;
|
|
247 }
|
|
248 else
|
|
249 {
|
|
250 VarDeclaration vto = new VarDeclaration(vd.loc, vd.type, vd.ident, vd.init);
|
|
251
|
|
252 ///*vto = *vd;
|
|
253 memcpy(cast(void*)vto, cast(void*)vd, VarDeclaration.classinfo.init.length);
|
|
254
|
|
255 vto.parent = ids.parent;
|
|
256 vto.csym = null;
|
|
257 vto.isym = null;
|
|
258
|
|
259 ids.from.push(cast(void*)vd);
|
|
260 ids.to.push(cast(void*)vto);
|
|
261
|
|
262 if (vd.init)
|
|
263 {
|
|
264 if (vd.init.isVoidInitializer())
|
|
265 {
|
|
266 vto.init = new VoidInitializer(vd.init.loc);
|
|
267 }
|
|
268 else
|
|
269 {
|
|
270 Expression e = vd.init.toExpression();
|
|
271 assert(e);
|
|
272 vto.init = new ExpInitializer(e.loc, e.doInline(ids));
|
|
273 }
|
|
274 }
|
|
275 de.declaration = vto;
|
|
276 }
|
|
277 }
|
|
278 /* This needs work, like DeclarationExp.toElem(), if we are
|
|
279 * to handle TemplateMixin's. For now, we just don't inline them.
|
|
280 */
|
|
281 return de;
|
|
282 }
|
|
283
|
|
284 Expression inlineScan(InlineScanState* iss)
|
|
285 {
|
|
286 //printf("DeclarationExp.inlineScan()\n");
|
|
287 scanVar(declaration, iss);
|
|
288 return this;
|
|
289 }
|
|
290 }
|
|
291
|