Mercurial > projects > ddmd
annotate dmd/StructDeclaration.d @ 178:e3afd1303184
Many small bugs fixed
Made all classes derive from TObject to detect memory leaks (functionality is disabled for now)
Began work on overriding backend memory allocations (to avoid memory leaks)
author | korDen |
---|---|
date | Sun, 17 Oct 2010 07:42:00 +0400 |
parents | fa9a71a9f5a8 |
children | cd48cb899aee |
rev | line source |
---|---|
0 | 1 module dmd.StructDeclaration; |
2 | |
114 | 3 import dmd.common; |
0 | 4 import dmd.AggregateDeclaration; |
5 import dmd.FuncDeclaration; | |
6 import dmd.DeclarationExp; | |
7 import dmd.VoidInitializer; | |
8 import dmd.Initializer; | |
9 import dmd.ExpInitializer; | |
10 import dmd.TOK; | |
11 import dmd.Statement; | |
12 import dmd.VarExp; | |
13 import dmd.CompoundStatement; | |
14 import dmd.AssignExp; | |
15 import dmd.DotVarExp; | |
16 import dmd.AddrExp; | |
17 import dmd.CastExp; | |
18 import dmd.PostBlitDeclaration; | |
19 import dmd.Lexer; | |
20 import dmd.ExpStatement; | |
21 import dmd.DotIdExp; | |
22 import dmd.TypeSArray; | |
23 import dmd.ThisExp; | |
24 import dmd.ThisDeclaration; | |
25 import dmd.TypeFunction; | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
26 import dmd.Parameter; |
0 | 27 import dmd.Id; |
28 import dmd.TY; | |
29 import dmd.LINK; | |
30 import dmd.Type; | |
31 import dmd.DsymbolTable; | |
32 import dmd.ArrayTypes; | |
33 import dmd.Loc; | |
34 import dmd.STC; | |
35 import dmd.Identifier; | |
36 import dmd.TemplateInstance; | |
37 import dmd.Dsymbol; | |
38 import dmd.Scope; | |
39 import dmd.OutBuffer; | |
40 import dmd.HdrGenState; | |
41 import dmd.PROT; | |
42 import dmd.TypeStruct; | |
43 import dmd.expression.Util; | |
44 import dmd.Expression; | |
45 import dmd.IdentifierExp; | |
46 import dmd.PtrExp; | |
47 import dmd.CallExp; | |
48 import dmd.ReturnStatement; | |
49 import dmd.ScopeDsymbol; | |
50 import dmd.Module; | |
51 import dmd.VarDeclaration; | |
52 import dmd.InvariantDeclaration; | |
53 import dmd.NewDeclaration; | |
54 import dmd.DeleteDeclaration; | |
55 import dmd.Global; | |
131
206db751bd4c
dmdfe 2.037 compiles now
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
130
diff
changeset
|
56 import dmd.MOD; |
206db751bd4c
dmdfe 2.037 compiles now
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
130
diff
changeset
|
57 import dmd.IntegerExp; |
206db751bd4c
dmdfe 2.037 compiles now
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
130
diff
changeset
|
58 import dmd.EqualExp; |
206db751bd4c
dmdfe 2.037 compiles now
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
130
diff
changeset
|
59 import dmd.AndAndExp; |
0 | 60 |
61 import dmd.backend.dt_t; | |
62 import dmd.backend.Util; | |
63 import dmd.backend.SC; | |
64 import dmd.backend.DT; | |
65 import dmd.backend.FL; | |
66 import dmd.backend.glue; | |
67 | |
129 | 68 import std.stdio; |
69 | |
0 | 70 class StructDeclaration : AggregateDeclaration |
71 { | |
72 bool zeroInit; // true if initialize with 0 fill | |
176 | 73 |
0 | 74 version (DMDV2) { |
75 int hasIdentityAssign; // !=0 if has identity opAssign | |
76 FuncDeclaration cpctor; // generated copy-constructor, if any | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
77 FuncDeclaration eq; // bool opEquals(ref const T), if any |
0 | 78 |
79 FuncDeclarations postblits; // Array of postblit functions | |
80 FuncDeclaration postblit; // aggregate postblit | |
81 } | |
82 | |
83 this(Loc loc, Identifier id) | |
84 { | |
178 | 85 register(); |
0 | 86 super(loc, id); |
87 | |
88 // For forward references | |
89 type = new TypeStruct(this); | |
176 | 90 |
0 | 91 postblits = new FuncDeclarations(); /// |
92 } | |
176 | 93 |
72 | 94 override Dsymbol syntaxCopy(Dsymbol s) |
0 | 95 { |
49 | 96 StructDeclaration sd; |
97 | |
98 if (s) | |
99 sd = cast(StructDeclaration)s; | |
100 else | |
101 sd = new StructDeclaration(loc, ident); | |
102 ScopeDsymbol.syntaxCopy(sd); | |
103 return sd; | |
0 | 104 } |
176 | 105 |
72 | 106 override void semantic(Scope sc) |
0 | 107 { |
108 Scope sc2; | |
109 | |
138 | 110 //writef("+StructDeclaration.semantic(this=%p, '%s', sizeok = %d)\n", this, toChars(), sizeok); |
0 | 111 |
138 | 112 //static int count; if (++count == 20) halt(); |
0 | 113 |
114 assert(type); | |
115 if (!members) // if forward reference | |
116 return; | |
117 | |
138 | 118 if (sizeok == 1 || symtab) |
119 { | |
120 if (!scope_) | |
121 { | |
122 // writef("already completed\n"); | |
123 scope_ = null; | |
0 | 124 return; // semantic() already completed |
138 | 125 } |
0 | 126 } |
127 else | |
128 symtab = new DsymbolTable(); | |
129 | |
130 Scope scx = null; | |
131 if (scope_) | |
132 { sc = scope_; | |
133 scx = scope_; // save so we don't make redundant copies | |
134 scope_ = null; | |
135 } | |
136 | |
137 parent = sc.parent; | |
138 type = type.semantic(loc, sc); | |
139 version (STRUCTTHISREF) { | |
140 handle = type; | |
141 } else { | |
142 handle = type.pointerTo(); | |
143 } | |
144 structalign = sc.structalign; | |
145 protection = sc.protection; | |
146 storage_class |= sc.stc; | |
147 if (sc.stc & STC.STCdeprecated) | |
148 isdeprecated = 1; | |
149 assert(!isAnonymous()); | |
150 if (sc.stc & STC.STCabstract) | |
151 error("structs, unions cannot be abstract"); | |
152 version (DMDV2) { | |
153 if (storage_class & STC.STCimmutable) | |
154 type = type.invariantOf(); | |
155 else if (storage_class & STC.STCconst) | |
156 type = type.constOf(); | |
157 else if (storage_class & STC.STCshared) | |
158 type = type.sharedOf(); | |
159 } | |
160 | |
161 if (sizeok == 0) // if not already done the addMember step | |
162 { | |
163 int hasfunctions = 0; | |
77
ad4792a1cfd6
more D-ification container accessing
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
74
diff
changeset
|
164 foreach(Dsymbol s; members) |
0 | 165 { |
166 //printf("adding member '%s' to '%s'\n", s.toChars(), this.toChars()); | |
13 | 167 s.addMember(sc, this, true); |
0 | 168 if (s.isFuncDeclaration()) |
169 hasfunctions = 1; | |
170 } | |
171 | |
172 // If nested struct, add in hidden 'this' pointer to outer scope | |
173 if (hasfunctions && !(storage_class & STC.STCstatic)) | |
174 { Dsymbol s = toParent2(); | |
175 if (s) | |
176 { | |
177 AggregateDeclaration ad = s.isAggregateDeclaration(); | |
178 FuncDeclaration fd = s.isFuncDeclaration(); | |
179 | |
180 TemplateInstance ti; | |
181 if (ad && (ti = ad.parent.isTemplateInstance()) !is null && ti.isnested || fd) | |
182 { isnested = true; | |
183 Type t; | |
184 if (ad) | |
185 t = ad.handle; | |
186 else if (fd) | |
176 | 187 { |
0 | 188 AggregateDeclaration add = fd.isMember2(); |
189 if (add) | |
190 t = add.handle; | |
191 else | |
176 | 192 t = global.tvoidptr; |
0 | 193 } |
194 else | |
195 assert(0); | |
196 if (t.ty == TY.Tstruct) | |
176 | 197 t = global.tvoidptr; // t should not be a ref type |
0 | 198 assert(!vthis); |
199 vthis = new ThisDeclaration(loc, t); | |
200 //vthis.storage_class |= STC.STCref; | |
74
7e0d548de9e6
Switch Arrays of Dsymbols to the new templated Vector type
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
72
diff
changeset
|
201 members.push(vthis); |
0 | 202 } |
203 } | |
204 } | |
205 } | |
206 | |
207 sizeok = 0; | |
208 sc2 = sc.push(this); | |
209 sc2.stc &= storage_class & STC.STC_TYPECTOR; | |
210 sc2.parent = this; | |
211 if (isUnionDeclaration()) | |
212 sc2.inunion = 1; | |
213 sc2.protection = PROT.PROTpublic; | |
214 sc2.explicitProtection = 0; | |
215 | |
135 | 216 |
217 /* Set scope so if there are forward references, we still might be able to | |
218 * resolve individual members like enums. | |
219 */ | |
220 foreach (s; members) | |
221 { | |
222 /* There are problems doing this in the general case because | |
223 * Scope keeps track of things like 'offset' | |
224 */ | |
225 if (s.isEnumDeclaration() || (s.isAggregateDeclaration() && s.ident)) | |
226 { | |
227 //printf("setScope %s %s\n", s->kind(), s->toChars()); | |
228 s.setScope(sc2); | |
229 } | |
230 } | |
231 | |
77
ad4792a1cfd6
more D-ification container accessing
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
74
diff
changeset
|
232 foreach(Dsymbol s; members) |
0 | 233 { |
129 | 234 s.semantic(sc2); |
235 if (isUnionDeclaration()) | |
236 sc2.offset = 0; | |
0 | 237 static if (false) { |
129 | 238 if (sizeok == 2) |
239 { //printf("forward reference\n"); | |
240 break; | |
241 } | |
0 | 242 } |
129 | 243 if (auto d = s.isDeclaration()) |
176 | 244 { |
129 | 245 if (auto t = d.type) { |
246 if (t.toBasetype().ty == TY.Tstruct) { | |
247 auto ad = t.toDsymbol(sc).isThis(); | |
248 /* | |
249 StructDeclaration sd = cast(StructDeclaration)foo; | |
250 if (foo && !sd) { | |
251 writeln(t.classin); | |
252 writeln(foo.classinfo.name); | |
253 assert(false); | |
254 } | |
255 */ | |
256 if (ad && ad.isnested) | |
257 error("inner struct %s cannot be a field", ad.toChars()); | |
258 } | |
259 } | |
260 } | |
0 | 261 } |
262 | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
263 version(DMDV1) { |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
264 /* This doesn't work for DMDV2 because (ref S) and (S) parameter |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
265 * lists will overload the same. |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
266 */ |
0 | 267 /* The TypeInfo_Struct is expecting an opEquals and opCmp with |
268 * a parameter that is a pointer to the struct. But if there | |
269 * isn't one, but is an opEquals or opCmp with a value, write | |
270 * another that is a shell around the value: | |
271 * int opCmp(struct *p) { return opCmp(*p); } | |
272 */ | |
273 | |
274 TypeFunction tfeqptr; | |
275 { | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
276 auto arguments = new Parameters; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
277 auto arg = new Parameter(STC.STCin, handle, Id.p, null); |
0 | 278 |
129 | 279 arguments.push(arg); |
280 tfeqptr = new TypeFunction(arguments, Type.tint32, 0, LINK.LINKd); | |
281 tfeqptr = cast(TypeFunction)tfeqptr.semantic(Loc(0), sc); | |
0 | 282 } |
283 | |
284 TypeFunction tfeq; | |
285 { | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
286 auto arguments = new Parameters; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
287 auto arg = new Parameter(STC.STCin, type, null, null); |
0 | 288 |
129 | 289 arguments.push(arg); |
290 tfeq = new TypeFunction(arguments, Type.tint32, 0, LINK.LINKd); | |
291 tfeq = cast(TypeFunction)tfeq.semantic(Loc(0), sc); | |
0 | 292 } |
293 | |
294 Identifier id = Id.eq; | |
295 for (int j = 0; j < 2; j++) | |
296 { | |
297 Dsymbol s = search_function(this, id); | |
298 FuncDeclaration fdx = s ? s.isFuncDeclaration() : null; | |
299 if (fdx) | |
300 { FuncDeclaration fd = fdx.overloadExactMatch(tfeqptr); | |
301 if (!fd) | |
302 { fd = fdx.overloadExactMatch(tfeq); | |
303 if (fd) | |
304 { // Create the thunk, fdptr | |
305 FuncDeclaration fdptr = new FuncDeclaration(loc, loc, fdx.ident, STC.STCundefined, tfeqptr); | |
306 Expression e = new IdentifierExp(loc, Id.p); | |
307 e = new PtrExp(loc, e); | |
84
be2ab491772e
Expressions -> Vector!Expression
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
79
diff
changeset
|
308 auto args = new Expressions(); |
be2ab491772e
Expressions -> Vector!Expression
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
79
diff
changeset
|
309 args.push(e); |
0 | 310 e = new IdentifierExp(loc, id); |
311 e = new CallExp(loc, e, args); | |
312 fdptr.fbody = new ReturnStatement(loc, e); | |
313 ScopeDsymbol ss = fdx.parent.isScopeDsymbol(); | |
314 assert(ss); | |
74
7e0d548de9e6
Switch Arrays of Dsymbols to the new templated Vector type
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
72
diff
changeset
|
315 ss.members.push(fdptr); |
13 | 316 fdptr.addMember(sc, ss, true); |
0 | 317 fdptr.semantic(sc2); |
318 } | |
319 } | |
320 } | |
321 | |
322 id = Id.cmp; | |
323 } | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
324 } |
0 | 325 version (DMDV2) { |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
326 /* Try to find the opEquals function. Build it if necessary. |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
327 */ |
131
206db751bd4c
dmdfe 2.037 compiles now
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
130
diff
changeset
|
328 TypeFunction tfeqptr; |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
329 { // bool opEquals(const T*) const; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
330 auto parameters = new Parameters; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
331 version(STRUCTTHISREF) { |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
332 // bool opEquals(ref const T) const; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
333 auto param = new Parameter(STC.STCref, type.constOf(), null, null); |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
334 } else { |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
335 // bool opEquals(const T*) const; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
336 auto param = new Parameter(STC.STCin, type.pointerTo(), null, null); |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
337 } |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
338 |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
339 parameters.push(param); |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
340 tfeqptr = new TypeFunction(parameters, Type.tbool, 0, LINK.LINKd); |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
341 tfeqptr.mod = MOD.MODconst; |
131
206db751bd4c
dmdfe 2.037 compiles now
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
130
diff
changeset
|
342 tfeqptr = cast(TypeFunction)(tfeqptr.semantic(Loc(0), sc2)); |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
343 |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
344 Dsymbol s = search_function(this, Id.eq); |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
345 FuncDeclaration fdx = s ? s.isFuncDeclaration() : null; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
346 if (fdx) |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
347 { |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
348 eq = fdx.overloadExactMatch(tfeqptr); |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
349 if (!eq) |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
350 fdx.error("type signature should be %s not %s", tfeqptr.toChars(), fdx.type.toChars()); |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
351 } |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
352 |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
353 if (!eq) |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
354 eq = buildOpEquals(sc2); |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
355 } |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
356 |
0 | 357 dtor = buildDtor(sc2); |
358 postblit = buildPostBlit(sc2); | |
359 cpctor = buildCpCtor(sc2); | |
360 buildOpAssign(sc2); | |
361 } | |
362 | |
363 sc2.pop(); | |
364 | |
365 if (sizeok == 2) | |
366 { // semantic() failed because of forward references. | |
367 // Unwind what we did, and defer it for later | |
368 fields.setDim(0); | |
369 structsize = 0; | |
370 alignsize = 0; | |
371 structalign = 0; | |
372 | |
87
b17640f0e4e8
Fixed a bug with a Scope.this(Scope enclosing) being called instead of Scope.clone() method (as a copy ctor replacement)
korDen
parents:
79
diff
changeset
|
373 scope_ = scx ? scx : sc.clone(); |
0 | 374 scope_.setNoFree(); |
375 scope_.module_.addDeferredSemantic(this); | |
138 | 376 writef("\tdeferring %s\n", toChars()); |
0 | 377 return; |
378 } | |
379 | |
380 // 0 sized struct's are set to 1 byte | |
381 if (structsize == 0) | |
382 { | |
383 structsize = 1; | |
384 alignsize = 1; | |
385 } | |
386 | |
387 // Round struct size up to next alignsize boundary. | |
388 // This will ensure that arrays of structs will get their internals | |
389 // aligned properly. | |
390 structsize = (structsize + alignsize - 1) & ~(alignsize - 1); | |
391 | |
392 sizeok = 1; | |
169 | 393 global.dprogress++; |
0 | 394 |
395 //printf("-StructDeclaration.semantic(this=%p, '%s')\n", this, toChars()); | |
396 | |
397 // Determine if struct is all zeros or not | |
398 zeroInit = true; | |
85
8e69d041a99d
Previous commit didn't compile. Fixed.
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
84
diff
changeset
|
399 foreach (VarDeclaration vd; fields) |
0 | 400 { |
79 | 401 if (vd && !vd.isDataseg()) |
0 | 402 { |
79 | 403 if (vd.init) |
404 { | |
405 // Should examine init to see if it is really all 0's | |
0 | 406 zeroInit = false; |
407 break; | |
79 | 408 } |
409 else | |
410 { | |
411 if (!vd.type.isZeroInit(loc)) | |
412 { | |
413 zeroInit = false; | |
414 break; | |
415 } | |
416 } | |
0 | 417 } |
418 } | |
419 | |
420 /* Look for special member functions. | |
421 */ | |
422 version (DMDV2) { | |
423 ctor = search(Loc(0), Id.ctor, 0); | |
424 } | |
425 inv = cast(InvariantDeclaration)search(Loc(0), Id.classInvariant, 0); | |
426 aggNew = cast(NewDeclaration)search(Loc(0), Id.classNew, 0); | |
427 aggDelete = cast(DeleteDeclaration)search(Loc(0), Id.classDelete, 0); | |
428 | |
429 if (sc.func) | |
430 { | |
431 semantic2(sc); | |
432 semantic3(sc); | |
433 } | |
434 } | |
176 | 435 |
154
14feb7ae01a6
* changed the build system to build a release version if the debug one compiles
trass3r
parents:
139
diff
changeset
|
436 override Dsymbol search(Loc loc, Identifier ident, int flags) |
135 | 437 { |
438 //printf("%s.StructDeclaration::search('%s')\n", toChars(), ident->toChars()); | |
439 | |
440 if (scope_) | |
441 semantic(scope_); | |
442 | |
443 if (!members || !symtab) | |
444 { | |
445 error("is forward referenced when looking for '%s'", ident.toChars()); | |
446 return null; | |
447 } | |
448 | |
449 return ScopeDsymbol.search(loc, ident, flags); | |
450 } | |
451 | |
72 | 452 override void toCBuffer(OutBuffer buf, HdrGenState* hgs) |
0 | 453 { |
454 assert(false); | |
455 } | |
176 | 456 |
72 | 457 override string mangle() |
0 | 458 { |
459 //printf("StructDeclaration.mangle() '%s'\n", toChars()); | |
460 return Dsymbol.mangle(); | |
461 } | |
176 | 462 |
72 | 463 override string kind() |
0 | 464 { |
465 assert(false); | |
466 } | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
467 |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
468 version(DMDV1) |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
469 { |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
470 Expression cloneMembers() |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
471 { |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
472 assert(false); |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
473 } |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
474 } |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
475 |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
476 version(DMDV2) |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
477 { |
0 | 478 /******************************************* |
479 * We need an opAssign for the struct if | |
480 * it has a destructor or a postblit. | |
481 * We need to generate one if a user-specified one does not exist. | |
482 */ | |
483 bool needOpAssign() | |
484 { | |
485 static if (false) { | |
486 printf("StructDeclaration.needOpAssign() %s\n", toChars()); | |
487 } | |
488 if (hasIdentityAssign) | |
489 goto Ldontneed; | |
490 | |
491 if (dtor || postblit) | |
492 goto Lneed; | |
493 | |
494 /* If any of the fields need an opAssign, then we | |
495 * need it too. | |
496 */ | |
85
8e69d041a99d
Previous commit didn't compile. Fixed.
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
84
diff
changeset
|
497 foreach (VarDeclaration v; fields) |
0 | 498 { |
499 assert(v && v.storage_class & STC.STCfield); | |
500 if (v.storage_class & STC.STCref) | |
501 continue; | |
502 Type tv = v.type.toBasetype(); | |
503 while (tv.ty == TY.Tsarray) | |
504 { TypeSArray ta = cast(TypeSArray)tv; | |
505 tv = tv.nextOf().toBasetype(); | |
506 } | |
507 if (tv.ty == TY.Tstruct) | |
508 { TypeStruct ts = cast(TypeStruct)tv; | |
509 StructDeclaration sd = ts.sym; | |
510 if (sd.needOpAssign()) | |
511 goto Lneed; | |
512 } | |
513 } | |
514 Ldontneed: | |
515 static if (false) { | |
516 printf("\tdontneed\n"); | |
517 } | |
518 return false; | |
519 | |
520 Lneed: | |
521 static if (false) { | |
522 printf("\tneed\n"); | |
523 } | |
524 return true; | |
525 } | |
176 | 526 |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
527 /******************************************* |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
528 * We need an opEquals for the struct if |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
529 * any fields has an opEquals. |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
530 * Generate one if a user-specified one does not exist. |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
531 */ |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
532 bool needOpEquals() |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
533 { |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
534 enum X = 0; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
535 static if (X) printf("StructDeclaration::needOpEquals() %s\n", toChars()); |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
536 |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
537 /* If any of the fields has an opEquals, then we |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
538 * need it too. |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
539 */ |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
540 foreach (s; fields) |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
541 { |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
542 VarDeclaration v = s.isVarDeclaration(); |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
543 assert(v && v.storage_class & STC.STCfield); |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
544 if (v.storage_class & STC.STCref) |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
545 continue; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
546 Type tv = v.type.toBasetype(); |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
547 while (tv.ty == Tsarray) |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
548 { auto ta = cast(TypeSArray)tv; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
549 tv = tv.nextOf().toBasetype(); |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
550 } |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
551 if (tv.ty == Tstruct) |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
552 { auto ts = cast(TypeStruct)tv; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
553 StructDeclaration sd = ts.sym; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
554 if (sd.eq) |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
555 goto Lneed; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
556 } |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
557 } |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
558 Ldontneed: |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
559 static if (X) printf("\tdontneed\n"); |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
560 return false; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
561 |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
562 Lneed: |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
563 static if (X) printf("\tneed\n"); |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
564 return true; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
565 } |
176 | 566 |
0 | 567 /****************************************** |
568 * Build opAssign for struct. | |
569 * S* opAssign(S s) { ... } | |
570 */ | |
571 FuncDeclaration buildOpAssign(Scope sc) | |
572 { | |
573 if (!needOpAssign()) | |
574 return null; | |
575 | |
576 //printf("StructDeclaration.buildOpAssign() %s\n", toChars()); | |
577 | |
578 FuncDeclaration fop = null; | |
579 | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
580 auto param = new Parameter(STC.STCnodtor, type, Id.p, null); |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
581 auto fparams = new Parameters; |
126
1765f3ef917d
ClassDeclarations, Arguments -> Vector
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
114
diff
changeset
|
582 fparams.push(param); |
0 | 583 Type ftype = new TypeFunction(fparams, handle, false, LINK.LINKd); |
584 version (STRUCTTHISREF) { | |
585 (cast(TypeFunction)ftype).isref = 1; | |
586 } | |
587 | |
588 fop = new FuncDeclaration(Loc(0), Loc(0), Id.assign, STC.STCundefined, ftype); | |
589 | |
590 Expression e = null; | |
591 if (postblit) | |
592 { /* Swap: | |
593 * tmp = *this; *this = s; tmp.dtor(); | |
594 */ | |
595 //printf("\tswap copy\n"); | |
596 Identifier idtmp = Lexer.uniqueId("__tmp"); | |
597 VarDeclaration tmp; | |
598 AssignExp ec = null; | |
599 if (dtor) | |
600 { | |
601 tmp = new VarDeclaration(Loc(0), type, idtmp, new VoidInitializer(Loc(0))); | |
602 tmp.noauto = true; | |
603 e = new DeclarationExp(Loc(0), tmp); | |
604 | |
605 Expression e2; | |
606 version (STRUCTTHISREF) { | |
607 e2 = new ThisExp(Loc(0)); | |
608 } else { | |
609 e2 = new PtrExp(Loc(0), new ThisExp(Loc(0))); | |
610 } | |
611 ec = new AssignExp(Loc(0), new VarExp(Loc(0), tmp), e2); | |
612 ec.op = TOK.TOKblit; | |
613 e = Expression.combine(e, ec); | |
614 } | |
615 Expression e2; | |
616 version (STRUCTTHISREF) { | |
617 e2 = new ThisExp(Loc(0)); | |
618 } else { | |
619 e2 = new PtrExp(Loc(0), new ThisExp(Loc(0))); | |
620 } | |
176 | 621 |
0 | 622 ec = new AssignExp(Loc(0), e2, new IdentifierExp(Loc(0), Id.p)); |
623 ec.op = TOK.TOKblit; | |
624 e = Expression.combine(e, ec); | |
625 if (dtor) | |
626 { | |
627 /* Instead of running the destructor on s, run it | |
628 * on tmp. This avoids needing to copy tmp back in to s. | |
629 */ | |
630 Expression ecc = new DotVarExp(Loc(0), new VarExp(Loc(0), tmp), dtor, 0); | |
631 ecc = new CallExp(Loc(0), ecc); | |
632 e = Expression.combine(e, ecc); | |
633 } | |
634 } | |
635 else | |
636 { /* Do memberwise copy | |
637 */ | |
638 //printf("\tmemberwise copy\n"); | |
85
8e69d041a99d
Previous commit didn't compile. Fixed.
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
84
diff
changeset
|
639 foreach (VarDeclaration v; fields) |
0 | 640 { |
641 assert(v && v.storage_class & STC.STCfield); | |
642 // this.v = s.v; | |
643 AssignExp ec = new AssignExp(Loc(0), new DotVarExp(Loc(0), new ThisExp(Loc(0)), v, 0), new DotVarExp(Loc(0), new IdentifierExp(Loc(0), Id.p), v, 0)); | |
644 ec.op = TOK.TOKblit; | |
645 e = Expression.combine(e, ec); | |
646 } | |
647 } | |
648 Statement s1 = new ExpStatement(Loc(0), e); | |
649 | |
650 /* Add: | |
651 * return this; | |
652 */ | |
653 e = new ThisExp(Loc(0)); | |
654 Statement s2 = new ReturnStatement(Loc(0), e); | |
655 | |
656 fop.fbody = new CompoundStatement(Loc(0), s1, s2); | |
657 | |
74
7e0d548de9e6
Switch Arrays of Dsymbols to the new templated Vector type
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
72
diff
changeset
|
658 members.push(fop); |
13 | 659 fop.addMember(sc, this, true); |
0 | 660 |
661 sc = sc.push(); | |
662 sc.stc = STC.STCundefined; | |
663 sc.linkage = LINK.LINKd; | |
664 | |
665 fop.semantic(sc); | |
666 | |
667 sc.pop(); | |
668 | |
669 //printf("-StructDeclaration.buildOpAssign() %s\n", toChars()); | |
670 | |
671 return fop; | |
672 } | |
176 | 673 |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
674 /****************************************** |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
675 * Build opEquals for struct. |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
676 * const bool opEquals(const ref S s) { ... } |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
677 */ |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
678 FuncDeclaration buildOpEquals(Scope sc) |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
679 { |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
680 if (!needOpEquals()) |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
681 return null; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
682 //printf("StructDeclaration::buildOpEquals() %s\n", toChars()); |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
683 Loc loc = this.loc; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
684 |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
685 auto parameters = new Parameters; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
686 version (STRUCTTHISREF) { |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
687 // bool opEquals(ref const T) const; |
131
206db751bd4c
dmdfe 2.037 compiles now
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
130
diff
changeset
|
688 auto param = new Parameter(STC.STCref, type.constOf(), Id.p, null); |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
689 } else { |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
690 // bool opEquals(const T*) const; |
131
206db751bd4c
dmdfe 2.037 compiles now
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
130
diff
changeset
|
691 auto param = new Parameter(STC.STCin, type.pointerTo(), Id.p, null); |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
692 } |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
693 |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
694 parameters.push(param); |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
695 auto ftype = new TypeFunction(parameters, Type.tbool, 0, LINKd); |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
696 ftype.mod = MOD.MODconst; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
697 ftype = cast(TypeFunction)ftype.semantic(loc, sc); |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
698 |
131
206db751bd4c
dmdfe 2.037 compiles now
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
130
diff
changeset
|
699 auto fop = new FuncDeclaration(loc, Loc(0), Id.eq, STC.STCundefined, ftype); |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
700 |
131
206db751bd4c
dmdfe 2.037 compiles now
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
130
diff
changeset
|
701 Expression e = null; |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
702 /* Do memberwise compare |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
703 */ |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
704 //printf("\tmemberwise compare\n"); |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
705 foreach (s; fields) |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
706 { |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
707 VarDeclaration v = s.isVarDeclaration(); |
131
206db751bd4c
dmdfe 2.037 compiles now
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
130
diff
changeset
|
708 assert(v && v.storage_class & STC.STCfield); |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
709 if (v.storage_class & STC.STCref) |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
710 assert(0); // what should we do with this? |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
711 // this.v == s.v; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
712 auto ec = new EqualExp(TOKequal, loc, |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
713 new DotVarExp(loc, new ThisExp(loc), v, 0), |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
714 new DotVarExp(loc, new IdentifierExp(loc, Id.p), v, 0)); |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
715 if (e) |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
716 e = new AndAndExp(loc, e, ec); |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
717 else |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
718 e = ec; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
719 } |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
720 if (!e) |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
721 e = new IntegerExp(loc, 1, Type.tbool); |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
722 fop.fbody = new ReturnStatement(loc, e); |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
723 |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
724 members.push(fop); |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
725 fop.addMember(sc, this, 1); |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
726 |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
727 sc = sc.push(); |
139 | 728 sc.stc = STCundefined; |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
729 sc.linkage = LINK.LINKd; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
730 |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
731 fop.semantic(sc); |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
732 |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
733 sc.pop(); |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
734 |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
735 //printf("-StructDeclaration::buildOpEquals() %s\n", toChars()); |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
736 |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
737 return fop; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
738 } |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
739 |
0 | 740 /***************************************** |
741 * Create inclusive postblit for struct by aggregating | |
742 * all the postblits in postblits[] with the postblits for | |
743 * all the members. | |
744 * Note the close similarity with AggregateDeclaration.buildDtor(), | |
745 * and the ordering changes (runs forward instead of backwards). | |
746 */ | |
747 | |
748 version (DMDV2) { | |
749 FuncDeclaration buildPostBlit(Scope sc) | |
750 { | |
751 //printf("StructDeclaration.buildPostBlit() %s\n", toChars()); | |
752 Expression e = null; | |
753 | |
85
8e69d041a99d
Previous commit didn't compile. Fixed.
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
84
diff
changeset
|
754 foreach (VarDeclaration v; fields) |
0 | 755 { |
79 | 756 assert(v && v.storage_class & STC.STCfield); |
757 if (v.storage_class & STC.STCref) | |
758 continue; | |
759 Type tv = v.type.toBasetype(); | |
760 size_t dim = 1; | |
761 while (tv.ty == TY.Tsarray) | |
762 { TypeSArray ta = cast(TypeSArray)tv; | |
763 dim *= (cast(TypeSArray)tv).dim.toInteger(); | |
764 tv = tv.nextOf().toBasetype(); | |
0 | 765 } |
79 | 766 if (tv.ty == TY.Tstruct) |
767 { TypeStruct ts = cast(TypeStruct)tv; | |
768 StructDeclaration sd = ts.sym; | |
769 if (sd.postblit) | |
770 { Expression ex; | |
176 | 771 |
79 | 772 // this.v |
773 ex = new ThisExp(Loc(0)); | |
774 ex = new DotVarExp(Loc(0), ex, v, 0); | |
176 | 775 |
79 | 776 if (dim == 1) |
777 { // this.v.postblit() | |
778 ex = new DotVarExp(Loc(0), ex, sd.postblit, 0); | |
779 ex = new CallExp(Loc(0), ex); | |
780 } | |
781 else | |
782 { | |
783 // Typeinfo.postblit(cast(void*)&this.v); | |
784 Expression ea = new AddrExp(Loc(0), ex); | |
785 ea = new CastExp(Loc(0), ea, Type.tvoid.pointerTo()); | |
176 | 786 |
79 | 787 Expression et = v.type.getTypeInfo(sc); |
103 | 788 et = new DotIdExp(Loc(0), et, Id._postblit); |
176 | 789 |
79 | 790 ex = new CallExp(Loc(0), et, ea); |
791 } | |
792 e = Expression.combine(e, ex); // combine in forward order | |
793 } | |
0 | 794 } |
795 } | |
796 | |
797 /* Build our own "postblit" which executes e | |
798 */ | |
799 if (e) | |
800 { //printf("Building __fieldPostBlit()\n"); | |
74
7e0d548de9e6
Switch Arrays of Dsymbols to the new templated Vector type
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
72
diff
changeset
|
801 auto dd = new PostBlitDeclaration(Loc(0), Loc(0), Lexer.idPool("__fieldPostBlit")); |
0 | 802 dd.fbody = new ExpStatement(Loc(0), e); |
74
7e0d548de9e6
Switch Arrays of Dsymbols to the new templated Vector type
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
72
diff
changeset
|
803 postblits.shift(dd); |
7e0d548de9e6
Switch Arrays of Dsymbols to the new templated Vector type
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
72
diff
changeset
|
804 members.push(dd); |
0 | 805 dd.semantic(sc); |
806 } | |
807 | |
808 switch (postblits.dim) | |
809 { | |
810 case 0: | |
811 return null; | |
812 | |
813 case 1: | |
77
ad4792a1cfd6
more D-ification container accessing
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
74
diff
changeset
|
814 return cast(FuncDeclaration)postblits[0]; |
0 | 815 |
816 default: | |
817 e = null; | |
77
ad4792a1cfd6
more D-ification container accessing
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
74
diff
changeset
|
818 foreach(FuncDeclaration fd; postblits) |
ad4792a1cfd6
more D-ification container accessing
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
74
diff
changeset
|
819 { |
0 | 820 Expression ex = new ThisExp(Loc(0)); |
821 ex = new DotVarExp(Loc(0), ex, fd, 0); | |
822 ex = new CallExp(Loc(0), ex); | |
823 e = Expression.combine(e, ex); | |
824 } | |
74
7e0d548de9e6
Switch Arrays of Dsymbols to the new templated Vector type
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
72
diff
changeset
|
825 auto dd = new PostBlitDeclaration(Loc(0), Loc(0), Lexer.idPool("__aggrPostBlit")); |
0 | 826 dd.fbody = new ExpStatement(Loc(0), e); |
74
7e0d548de9e6
Switch Arrays of Dsymbols to the new templated Vector type
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
72
diff
changeset
|
827 members.push(dd); |
0 | 828 dd.semantic(sc); |
829 return dd; | |
830 } | |
831 } | |
832 } | |
833 | |
834 /******************************************* | |
835 * Build copy constructor for struct. | |
836 * Copy constructors are compiler generated only, and are only | |
837 * callable from the compiler. They are not user accessible. | |
838 * A copy constructor is: | |
839 * void cpctpr(ref S s) | |
840 * { | |
841 * *this = s; | |
842 * this.postBlit(); | |
843 * } | |
844 * This is done so: | |
845 * - postBlit() never sees uninitialized data | |
846 * - memcpy can be much more efficient than memberwise copy | |
847 * - no fields are overlooked | |
848 */ | |
849 FuncDeclaration buildCpCtor(Scope sc) | |
850 { | |
851 //printf("StructDeclaration.buildCpCtor() %s\n", toChars()); | |
852 FuncDeclaration fcp = null; | |
853 | |
854 /* Copy constructor is only necessary if there is a postblit function, | |
855 * otherwise the code generator will just do a bit copy. | |
856 */ | |
857 if (postblit) | |
858 { | |
129 | 859 //printf("generating cpctor\n"); |
0 | 860 |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
861 auto param = new Parameter(STC.STCref, type, Id.p, null); |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
862 auto fparams = new Parameters; |
129 | 863 fparams.push(param); |
864 Type ftype = new TypeFunction(fparams, Type.tvoid, false, LINK.LINKd); | |
0 | 865 |
129 | 866 fcp = new FuncDeclaration(Loc(0), Loc(0), Id.cpctor, STC.STCundefined, ftype); |
0 | 867 |
129 | 868 // Build *this = p; |
869 Expression e = new ThisExp(Loc(0)); | |
0 | 870 version (STRUCTTHISREF) { |
871 } else { | |
129 | 872 e = new PtrExp(Loc(0), e); |
0 | 873 } |
129 | 874 AssignExp ea = new AssignExp(Loc(0), e, new IdentifierExp(Loc(0), Id.p)); |
875 ea.op = TOK.TOKblit; | |
876 Statement s = new ExpStatement(Loc(0), ea); | |
0 | 877 |
129 | 878 // Build postBlit(); |
879 e = new VarExp(Loc(0), postblit, 0); | |
880 e = new CallExp(Loc(0), e); | |
0 | 881 |
129 | 882 s = new CompoundStatement(Loc(0), s, new ExpStatement(Loc(0), e)); |
883 fcp.fbody = s; | |
0 | 884 |
129 | 885 members.push(fcp); |
0 | 886 |
129 | 887 sc = sc.push(); |
888 sc.stc = STC.STCundefined; | |
889 sc.linkage = LINK.LINKd; | |
0 | 890 |
129 | 891 fcp.semantic(sc); |
0 | 892 |
129 | 893 sc.pop(); |
0 | 894 } |
895 | |
896 return fcp; | |
897 } | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
898 } |
72 | 899 override void toDocBuffer(OutBuffer buf) |
0 | 900 { |
901 assert(false); | |
902 } | |
176 | 903 |
72 | 904 override PROT getAccess(Dsymbol smember) // determine access to smember |
0 | 905 { |
906 assert(false); | |
907 } | |
908 | |
72 | 909 override void toObjFile(int multiobj) // compile to .obj file |
0 | 910 { |
911 //printf("StructDeclaration.toObjFile('%s')\n", toChars()); | |
912 | |
913 if (multiobj) | |
176 | 914 { |
0 | 915 obj_append(this); |
916 return; | |
917 } | |
918 | |
919 // Anonymous structs/unions only exist as part of others, | |
920 // do not output forward referenced structs's | |
921 if (!isAnonymous() && members) | |
922 { | |
923 if (global.params.symdebug) { | |
924 toDebug(); | |
925 } | |
926 | |
927 type.getTypeInfo(null); // generate TypeInfo | |
928 | |
929 if (true) | |
930 { | |
931 // Generate static initializer | |
932 toInitializer(); | |
933 | |
934 static if (false) { | |
935 sinit.Sclass = SC.SCcomdat; | |
936 } else { | |
937 if (inTemplateInstance()) | |
938 { | |
939 sinit.Sclass = SC.SCcomdat; | |
940 } | |
941 else | |
942 { | |
943 sinit.Sclass = SC.SCglobal; | |
944 } | |
945 } | |
946 sinit.Sfl = FL.FLdata; | |
947 | |
948 toDt(&sinit.Sdt); | |
949 | |
95 | 950 version (OMFOBJ) |
951 { | |
0 | 952 /* For OMF, common blocks aren't pulled in from the library. |
953 */ | |
954 /* ELF comdef's generate multiple | |
955 * definition errors for them from the gnu linker. | |
956 * Need to figure out how to generate proper comdef's for ELF. | |
957 */ | |
958 // See if we can convert a comdat to a comdef, | |
959 // which saves on exe file space. | |
95 | 960 if (0 && // causes multiple def problems with COMMON in one file and COMDAT in library |
961 sinit.Sclass == SCcomdat && | |
0 | 962 sinit.Sdt && |
963 sinit.Sdt.dt == DT.DT_azeros && | |
964 sinit.Sdt.DTnext == null && | |
965 !global.params.multiobj) | |
966 { | |
967 sinit.Sclass = SC.SCglobal; | |
968 sinit.Sdt.dt = DT.DT_common; | |
969 } | |
970 } | |
971 | |
972 version (ELFOBJ) { | |
973 sinit.Sseg = Segment.CDATA; | |
974 } | |
975 version (MACHOBJ) { | |
976 sinit.Sseg = Segment.DATA; | |
977 } | |
978 outdata(sinit); | |
979 } | |
980 | |
981 // Put out the members | |
77
ad4792a1cfd6
more D-ification container accessing
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
74
diff
changeset
|
982 foreach(Dsymbol member; members) |
0 | 983 member.toObjFile(0); |
984 } | |
985 } | |
176 | 986 |
0 | 987 void toDt(dt_t** pdt) |
988 { | |
989 uint offset; | |
990 dt_t* dt; | |
991 | |
992 //printf("StructDeclaration.toDt(), this='%s'\n", toChars()); | |
993 offset = 0; | |
994 | |
995 // Note equivalence of this loop to class's | |
79 | 996 for (uint i = 0; i < fields.dim; i++) |
0 | 997 { |
79 | 998 VarDeclaration v = cast(VarDeclaration)fields[i]; |
0 | 999 //printf("\tfield '%s' voffset %d, offset = %d\n", v.toChars(), v.offset, offset); |
1000 dt = null; | |
1001 int sz; | |
1002 | |
1003 if (v.storage_class & STC.STCref) | |
1004 { | |
1005 sz = PTRSIZE; | |
1006 if (v.offset >= offset) | |
1007 dtnzeros(&dt, sz); | |
1008 } | |
1009 else | |
1010 { | |
1011 sz = cast(uint)v.type.size(); | |
1012 Initializer init = v.init; | |
1013 if (init) | |
176 | 1014 { |
0 | 1015 //printf("\t\thas initializer %s\n", init.toChars()); |
1016 ExpInitializer ei = init.isExpInitializer(); | |
1017 Type tb = v.type.toBasetype(); | |
1018 if (ei && tb.ty == TY.Tsarray) | |
1019 (cast(TypeSArray)tb).toDtElem(&dt, ei.exp); | |
1020 else | |
1021 dt = init.toDt(); | |
1022 } | |
1023 else if (v.offset >= offset) | |
1024 v.type.toDt(&dt); | |
1025 } | |
1026 if (dt) | |
1027 { | |
1028 if (v.offset < offset) | |
1029 error("overlapping initialization for struct %s.%s", toChars(), v.toChars()); | |
1030 else | |
1031 { | |
1032 if (offset < v.offset) | |
1033 dtnzeros(pdt, v.offset - offset); | |
1034 dtcat(pdt, dt); | |
1035 offset = v.offset + sz; | |
1036 } | |
1037 } | |
1038 } | |
1039 | |
1040 if (offset < structsize) | |
1041 dtnzeros(pdt, structsize - offset); | |
1042 | |
1043 dt_optimize(*pdt); | |
1044 } | |
176 | 1045 |
0 | 1046 void toDebug() // to symbolic debug info |
1047 { | |
1048 assert(false); | |
1049 } | |
1050 | |
72 | 1051 override StructDeclaration isStructDeclaration() { return this; } |
1052 } |