2 // Compiler implementation of the D programming language
3 // Copyright (c) 1999-2008 by Digital Mars
5 // written by Walter Bright
6 // http://www.digitalmars.com
7 // License for redistribution is by either the Artistic License
8 // in artistic.txt, or the GNU General Public License in gnu.txt.
9 // See the included readme.txt for details.
11 /* NOTE: This file has been patched from the original DMD distribution to
12 work with the GDC compiler.
14 Modified by David Friedman, December 2006
21 #include "aggregate.h"
24 #include "declaration.h"
27 #include "statement.h"
29 /********************************* AggregateDeclaration ****************************/
31 AggregateDeclaration::AggregateDeclaration(Loc loc
, Identifier
*id
)
37 protection
= PROTpublic
;
40 structsize
= 0; // size of struct
41 alignsize
= 0; // size of struct for alignment purposes
42 structalign
= 0; // struct member alignment in effect
44 sizeok
= 0; // size not determined yet
58 enum PROT
AggregateDeclaration::prot()
63 void AggregateDeclaration::semantic2(Scope
*sc
)
65 //printf("AggregateDeclaration::semantic2(%s)\n", toChars());
67 { error("has forward references");
73 for (size_t i
= 0; i
< members
->dim
; i
++)
75 Dsymbol
*s
= (Dsymbol
*)members
->data
[i
];
82 void AggregateDeclaration::semantic3(Scope
*sc
)
85 //printf("AggregateDeclaration::semantic3(%s)\n", toChars());
89 for (i
= 0; i
< members
->dim
; i
++)
91 Dsymbol
*s
= (Dsymbol
*)members
->data
[i
];
98 void AggregateDeclaration::inlineScan()
101 //printf("AggregateDeclaration::inlineScan(%s)\n", toChars());
104 for (i
= 0; i
< members
->dim
; i
++)
106 Dsymbol
*s
= (Dsymbol
*)members
->data
[i
];
107 //printf("inline scan aggregate symbol '%s'\n", s->toChars());
113 target_size_t
AggregateDeclaration::size(Loc loc
)
115 //printf("AggregateDeclaration::size() = %d\n", structsize);
117 error(loc
, "unknown size");
119 { error(loc
, "no size yet for forward reference");
125 Type
*AggregateDeclaration::getType()
130 int AggregateDeclaration::isDeprecated()
135 /****************************
136 * Do byte or word alignment as necessary.
137 * Align sizes of 0, as we may not know array sizes yet.
140 void AggregateDeclaration::alignmember(target_size_t salign
, target_size_t size
, target_size_t
*poffset
)
142 //printf("salign = %d, size = %d, offset = %d\n",salign,size,offset);
151 *poffset
= (*poffset
+ 1) & ~1; // align to word
157 *poffset
= (*poffset
+ 3) & ~3; // align to dword
160 *poffset
= (*poffset
+ salign
- 1) & ~(salign
- 1);
164 //printf("result = %d\n",offset);
168 void AggregateDeclaration::addField(Scope
*sc
, VarDeclaration
*v
)
170 target_size_t memsize
; // size of member
171 target_size_t memalignsize
; // size of member for alignment purposes
172 target_size_t xalign
; // alignment boundaries
174 //printf("AggregateDeclaration::addField('%s') %s\n", v->toChars(), toChars());
175 assert(!(v
->storage_class
& (STCstatic
| STCextern
| STCparameter
| STCtls
)));
177 // Check for forward referenced types which will fail the size() call
178 Type
*t
= v
->type
->toBasetype();
179 if (t
->ty
== Tstruct
/*&& isStructDeclaration()*/)
180 { TypeStruct
*ts
= (TypeStruct
*)t
;
184 error("cannot have field %s with same struct type", v
->toChars());
187 if (ts
->sym
->sizeok
!= 1)
189 sizeok
= 2; // cannot finish; flag as forward referenced
195 sizeok
= 2; // cannot finish; flag as forward referenced
199 memsize
= v
->type
->size(loc
);
200 memalignsize
= v
->type
->alignsize();
201 xalign
= v
->type
->memalign(sc
->structalign
);
202 alignmember(xalign
, memalignsize
, &sc
->offset
);
203 v
->offset
= sc
->offset
;
204 sc
->offset
+= memsize
;
205 if (sc
->offset
> structsize
)
206 structsize
= sc
->offset
;
207 if (sc
->structalign
< memalignsize
)
208 memalignsize
= sc
->structalign
;
209 if (alignsize
< memalignsize
)
210 alignsize
= memalignsize
;
211 //printf("\talignsize = %d\n", alignsize);
213 v
->storage_class
|= STCfield
;
214 //printf(" addField '%s' to '%s' at offset %d, size = %d\n", v->toChars(), toChars(), v->offset, memsize);
219 /********************************* StructDeclaration ****************************/
221 StructDeclaration::StructDeclaration(Loc loc
, Identifier
*id
)
222 : AggregateDeclaration(loc
, id
)
224 zeroInit
= 0; // assume false until we do semantic processing
225 hasIdentityAssign
= 0;
229 // For forward references
230 type
= new TypeStruct(this);
233 Dsymbol
*StructDeclaration::syntaxCopy(Dsymbol
*s
)
235 StructDeclaration
*sd
;
238 sd
= (StructDeclaration
*)s
;
240 sd
= new StructDeclaration(loc
, ident
);
241 ScopeDsymbol::syntaxCopy(sd
);
245 void StructDeclaration::semantic(Scope
*sc
)
249 //printf("+StructDeclaration::semantic(this=%p, '%s')\n", this, toChars());
251 //static int count; if (++count == 20) *(char*)0=0;
254 if (!members
) // if forward reference
259 return; // semantic() already completed
262 symtab
= new DsymbolTable();
267 scx
= scope
; // save so we don't make redundant copies
275 handle
= type
->pointerTo();
276 structalign
= sc
->structalign
;
277 protection
= sc
->protection
;
278 storage_class
|= sc
->stc
;
279 assert(!isAnonymous());
280 if (sc
->stc
& STCabstract
)
281 error("structs, unions cannot be abstract");
282 if (storage_class
& STCinvariant
)
283 type
= type
->invariantOf();
284 else if (storage_class
& STCconst
)
285 type
= type
->constOf();
287 attributes
->append(sc
->attributes
);
289 attributes
= sc
->attributes
;
291 if (sizeok
== 0) // if not already done the addMember step
293 for (i
= 0; i
< members
->dim
; i
++)
295 Dsymbol
*s
= (Dsymbol
*)members
->data
[i
];
296 //printf("adding member '%s' to '%s'\n", s->toChars(), this->toChars());
297 s
->addMember(sc
, this, 1);
302 sc2
= sc
->push(this);
303 sc2
->stc
&= storage_class
& (STCconst
| STCinvariant
);
304 sc2
->attributes
= NULL
;
306 if (isUnionDeclaration())
308 sc2
->protection
= PROTpublic
;
309 sc2
->explicitProtection
= 0;
311 int members_dim
= members
->dim
;
312 for (i
= 0; i
< members_dim
; i
++)
314 Dsymbol
*s
= (Dsymbol
*)members
->data
[i
];
316 if (isUnionDeclaration())
320 { //printf("forward reference\n");
326 /* The TypeInfo_Struct is expecting an opEquals and opCmp with
327 * a parameter that is a pointer to the struct. But if there
328 * isn't one, but is an opEquals or opCmp with a value, write
329 * another that is a shell around the value:
330 * int opCmp(struct *p) { return opCmp(*p); }
333 TypeFunction
*tfeqptr
;
335 Arguments
*arguments
= new Arguments
;
336 Argument
*arg
= new Argument(STCin
, handle
, Id::p
, NULL
);
338 arguments
->push(arg
);
339 tfeqptr
= new TypeFunction(arguments
, Type::tint32
, 0, LINKd
);
340 tfeqptr
= (TypeFunction
*)tfeqptr
->semantic(0, sc
);
345 Arguments
*arguments
= new Arguments
;
346 Argument
*arg
= new Argument(STCin
, type
, NULL
, NULL
);
348 arguments
->push(arg
);
349 tfeq
= new TypeFunction(arguments
, Type::tint32
, 0, LINKd
);
350 tfeq
= (TypeFunction
*)tfeq
->semantic(0, sc
);
353 Identifier
*id
= Id::eq
;
354 for (int i
= 0; i
< 2; i
++)
356 Dsymbol
*s
= search_function(this, id
);
357 FuncDeclaration
*fdx
= s
? s
->isFuncDeclaration() : NULL
;
359 { FuncDeclaration
*fd
= fdx
->overloadExactMatch(tfeqptr
);
361 { fd
= fdx
->overloadExactMatch(tfeq
);
363 { // Create the thunk, fdptr
364 FuncDeclaration
*fdptr
= new FuncDeclaration(loc
, loc
, fdx
->ident
, STCundefined
, tfeqptr
);
365 Expression
*e
= new IdentifierExp(loc
, Id::p
);
366 e
= new PtrExp(loc
, e
);
367 Expressions
*args
= new Expressions();
369 e
= new IdentifierExp(loc
, id
);
370 e
= new CallExp(loc
, e
, args
);
371 fdptr
->fbody
= new ReturnStatement(loc
, e
);
372 ScopeDsymbol
*s
= fdx
->parent
->isScopeDsymbol();
374 s
->members
->push(fdptr
);
375 fdptr
->addMember(sc
, s
, 1);
376 fdptr
->semantic(sc2
);
384 dtor
= buildDtor(sc2
);
385 postblit
= buildPostBlit(sc2
);
386 cpctor
= buildCpCtor(sc2
);
392 { // semantic() failed because of forward references.
393 // Unwind what we did, and defer it for later
399 scope
= scx
? scx
: new Scope(*sc
);
401 scope
->module
->addDeferredSemantic(this);
402 //printf("\tdeferring %s\n", toChars());
406 // 0 sized struct's are set to 1 byte
413 // Round struct size up to next alignsize boundary.
414 // This will ensure that arrays of structs will get their internals
416 structsize
= (structsize
+ alignsize
- 1) & ~(alignsize
- 1);
421 //printf("-StructDeclaration::semantic(this=%p, '%s')\n", this, toChars());
423 // Determine if struct is all zeros or not
425 for (i
= 0; i
< fields
.dim
; i
++)
427 Dsymbol
*s
= (Dsymbol
*)fields
.data
[i
];
428 VarDeclaration
*vd
= s
->isVarDeclaration();
429 if (vd
&& !vd
->isDataseg())
433 // Should examine init to see if it is really all 0's
439 if (!vd
->type
->isZeroInit())
448 /* Look for special member functions.
450 inv
= (InvariantDeclaration
*)search(0, Id::classInvariant
, 0);
451 aggNew
= (NewDeclaration
*)search(0, Id::classNew
, 0);
452 aggDelete
= (DeleteDeclaration
*)search(0, Id::classDelete
, 0);
461 void StructDeclaration::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
464 buf
->printf("%s ", kind());
466 buf
->writestring(toChars());
476 for (i
= 0; i
< members
->dim
; i
++)
478 Dsymbol
*s
= (Dsymbol
*)members
->data
[i
];
480 buf
->writestring(" ");
481 s
->toCBuffer(buf
, hgs
);
488 char *StructDeclaration::kind()
493 /********************************* UnionDeclaration ****************************/
495 UnionDeclaration::UnionDeclaration(Loc loc
, Identifier
*id
)
496 : StructDeclaration(loc
, id
)
500 Dsymbol
*UnionDeclaration::syntaxCopy(Dsymbol
*s
)
502 UnionDeclaration
*ud
;
505 ud
= (UnionDeclaration
*)s
;
507 ud
= new UnionDeclaration(loc
, ident
);
508 StructDeclaration::syntaxCopy(ud
);
513 char *UnionDeclaration::kind()