comparison dmd/DeclarationExp.d @ 0:10317f0c89a5

Initial commit
author korDen
date Sat, 24 Oct 2009 08:42:06 +0400
parents
children cab4c37afb89
comparison
equal deleted inserted replaced
-1:000000000000 0:10317f0c89a5
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