2 // Compiler implementation of the D programming language
3 // Copyright (c) 1999-2006 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
57 enum PROT
AggregateDeclaration::prot()
62 void AggregateDeclaration::semantic2(Scope
*sc
)
64 //printf("AggregateDeclaration::semantic2(%s)\n", toChars());
66 { error("has forward references");
72 for (size_t i
= 0; i
< members
->dim
; i
++)
74 Dsymbol
*s
= (Dsymbol
*)members
->data
[i
];
81 void AggregateDeclaration::semantic3(Scope
*sc
)
84 //printf("AggregateDeclaration::semantic3(%s)\n", toChars());
88 for (i
= 0; i
< members
->dim
; i
++)
90 Dsymbol
*s
= (Dsymbol
*)members
->data
[i
];
97 void AggregateDeclaration::inlineScan()
100 //printf("AggregateDeclaration::inlineScan(%s)\n", toChars());
103 for (i
= 0; i
< members
->dim
; i
++)
105 Dsymbol
*s
= (Dsymbol
*)members
->data
[i
];
106 //printf("inline scan aggregate symbol '%s'\n", s->toChars());
112 target_size_t
AggregateDeclaration::size(Loc loc
)
114 //printf("AggregateDeclaration::size() = %d\n", structsize);
116 error(loc
, "unknown size");
118 { error(loc
, "no size yet for forward reference");
124 Type
*AggregateDeclaration::getType()
129 int AggregateDeclaration::isDeprecated()
134 /****************************
135 * Do byte or word alignment as necessary.
136 * Align sizes of 0, as we may not know array sizes yet.
139 void AggregateDeclaration::alignmember(target_size_t salign
, target_size_t size
, target_size_t
*poffset
)
141 //printf("salign = %d, size = %d, offset = %d\n",salign,size,offset);
150 *poffset
= (*poffset
+ 1) & ~1; // align to word
156 *poffset
= (*poffset
+ 3) & ~3; // align to dword
159 *poffset
= (*poffset
+ salign
- 1) & ~(salign
- 1);
163 //printf("result = %d\n",offset);
167 void AggregateDeclaration::addField(Scope
*sc
, VarDeclaration
*v
)
169 target_size_t memsize
; // size of member
170 target_size_t memalignsize
; // size of member for alignment purposes
171 target_size_t xalign
; // alignment boundaries
173 //printf("AggregateDeclaration::addField('%s') %s\n", v->toChars(), toChars());
175 // Check for forward referenced types which will fail the size() call
176 Type
*t
= v
->type
->toBasetype();
177 if (t
->ty
== Tstruct
/*&& isStructDeclaration()*/)
178 { TypeStruct
*ts
= (TypeStruct
*)t
;
180 if (ts
->sym
->sizeok
!= 1)
182 sizeok
= 2; // cannot finish; flag as forward referenced
188 sizeok
= 2; // cannot finish; flag as forward referenced
192 memsize
= v
->type
->size(loc
);
193 memalignsize
= v
->type
->alignsize();
194 xalign
= v
->type
->memalign(sc
->structalign
);
195 alignmember(xalign
, memalignsize
, &sc
->offset
);
196 v
->offset
= sc
->offset
;
197 sc
->offset
+= memsize
;
198 if (sc
->offset
> structsize
)
199 structsize
= sc
->offset
;
200 if (sc
->structalign
< memalignsize
)
201 memalignsize
= sc
->structalign
;
202 if (alignsize
< memalignsize
)
203 alignsize
= memalignsize
;
204 //printf("\talignsize = %d\n", alignsize);
206 v
->storage_class
|= STCfield
;
207 //printf(" addField '%s' to '%s' at offset %d, size = %d\n", v->toChars(), toChars(), v->offset, memsize);
212 /********************************* StructDeclaration ****************************/
214 StructDeclaration::StructDeclaration(Loc loc
, Identifier
*id
)
215 : AggregateDeclaration(loc
, id
)
217 zeroInit
= 0; // assume false until we do semantic processing
219 // For forward references
220 type
= new TypeStruct(this);
223 Dsymbol
*StructDeclaration::syntaxCopy(Dsymbol
*s
)
225 StructDeclaration
*sd
;
228 sd
= (StructDeclaration
*)s
;
230 sd
= new StructDeclaration(loc
, ident
);
231 ScopeDsymbol::syntaxCopy(sd
);
235 void StructDeclaration::semantic(Scope
*sc
)
239 //printf("+StructDeclaration::semantic(this=%p, '%s')\n", this, toChars());
241 //static int count; if (++count == 20) *(char*)0=0;
244 if (!members
) // if forward reference
249 return; // semantic() already completed
252 symtab
= new DsymbolTable();
257 scx
= scope
; // save so we don't make redundant copies
265 handle
= type
->pointerTo();
266 structalign
= sc
->structalign
;
267 protection
= sc
->protection
;
268 assert(!isAnonymous());
269 if (sc
->stc
& STCabstract
)
270 error("structs, unions cannot be abstract");
272 attributes
->append(sc
->attributes
);
274 attributes
= sc
->attributes
;
276 if (sizeok
== 0) // if not already done the addMember step
278 for (i
= 0; i
< members
->dim
; i
++)
280 Dsymbol
*s
= (Dsymbol
*)members
->data
[i
];
281 //printf("adding member '%s' to '%s'\n", s->toChars(), this->toChars());
282 s
->addMember(sc
, this, 1);
287 sc2
= sc
->push(this);
289 sc2
->attributes
= NULL
;
291 if (isUnionDeclaration())
293 sc2
->protection
= PROTpublic
;
294 sc2
->explicitProtection
= 0;
296 int members_dim
= members
->dim
;
297 for (i
= 0; i
< members_dim
; i
++)
299 Dsymbol
*s
= (Dsymbol
*)members
->data
[i
];
301 if (isUnionDeclaration())
305 { //printf("forward reference\n");
311 /* The TypeInfo_Struct is expecting an opEquals and opCmp with
312 * a parameter that is a pointer to the struct. But if there
313 * isn't one, but is an opEquals or opCmp with a value, write
314 * another that is a shell around the value:
315 * int opCmp(struct *p) { return opCmp(*p); }
318 TypeFunction
*tfeqptr
;
320 Arguments
*arguments
= new Arguments
;
321 Argument
*arg
= new Argument(STCin
, handle
, Id::p
, NULL
);
323 arguments
->push(arg
);
324 tfeqptr
= new TypeFunction(arguments
, Type::tint32
, 0, LINKd
);
325 tfeqptr
= (TypeFunction
*)tfeqptr
->semantic(0, sc
);
330 Arguments
*arguments
= new Arguments
;
331 Argument
*arg
= new Argument(STCin
, type
, NULL
, NULL
);
333 arguments
->push(arg
);
334 tfeq
= new TypeFunction(arguments
, Type::tint32
, 0, LINKd
);
335 tfeq
= (TypeFunction
*)tfeq
->semantic(0, sc
);
338 Identifier
*id
= Id::eq
;
339 for (int i
= 0; i
< 2; i
++)
341 Dsymbol
*s
= search_function(this, id
);
342 FuncDeclaration
*fdx
= s
? s
->isFuncDeclaration() : NULL
;
344 { FuncDeclaration
*fd
= fdx
->overloadExactMatch(tfeqptr
);
346 { fd
= fdx
->overloadExactMatch(tfeq
);
348 { // Create the thunk, fdptr
349 FuncDeclaration
*fdptr
= new FuncDeclaration(loc
, loc
, fdx
->ident
, STCundefined
, tfeqptr
);
350 Expression
*e
= new IdentifierExp(loc
, Id::p
);
351 e
= new PtrExp(loc
, e
);
352 Expressions
*args
= new Expressions();
354 e
= new IdentifierExp(loc
, id
);
355 e
= new CallExp(loc
, e
, args
);
356 fdptr
->fbody
= new ReturnStatement(loc
, e
);
357 ScopeDsymbol
*s
= fdx
->parent
->isScopeDsymbol();
359 s
->members
->push(fdptr
);
360 fdptr
->addMember(sc
, s
, 1);
361 fdptr
->semantic(sc2
);
373 { // semantic() failed because of forward references.
374 // Unwind what we did, and defer it for later
380 scope
= scx
? scx
: new Scope(*sc
);
382 scope
->module
->addDeferredSemantic(this);
383 //printf("\tdeferring %s\n", toChars());
387 // 0 sized struct's are set to 1 byte
394 // Round struct size up to next alignsize boundary.
395 // This will ensure that arrays of structs will get their internals
397 structsize
= (structsize
+ alignsize
- 1) & ~(alignsize
- 1);
402 //printf("-StructDeclaration::semantic(this=%p, '%s')\n", this, toChars());
404 // Determine if struct is all zeros or not
406 for (i
= 0; i
< fields
.dim
; i
++)
408 Dsymbol
*s
= (Dsymbol
*)fields
.data
[i
];
409 VarDeclaration
*vd
= s
->isVarDeclaration();
410 if (vd
&& !vd
->isDataseg())
414 // Should examine init to see if it is really all 0's
420 if (!vd
->type
->isZeroInit())
429 /* Look for special member functions.
431 inv
= (InvariantDeclaration
*)search(0, Id::classInvariant
, 0);
432 aggNew
= (NewDeclaration
*)search(0, Id::classNew
, 0);
433 aggDelete
= (DeleteDeclaration
*)search(0, Id::classDelete
, 0);
442 void StructDeclaration::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
445 buf
->printf("%s ", kind());
447 buf
->writestring(toChars());
457 for (i
= 0; i
< members
->dim
; i
++)
459 Dsymbol
*s
= (Dsymbol
*)members
->data
[i
];
461 buf
->writestring(" ");
462 s
->toCBuffer(buf
, hgs
);
469 char *StructDeclaration::kind()
474 /********************************* UnionDeclaration ****************************/
476 UnionDeclaration::UnionDeclaration(Loc loc
, Identifier
*id
)
477 : StructDeclaration(loc
, id
)
481 Dsymbol
*UnionDeclaration::syntaxCopy(Dsymbol
*s
)
483 UnionDeclaration
*ud
;
486 ud
= (UnionDeclaration
*)s
;
488 ud
= new UnionDeclaration(loc
, ident
);
489 StructDeclaration::syntaxCopy(ud
);
494 char *UnionDeclaration::kind()