mirror of
https://github.com/xomboverlord/ldc.git
synced 2026-03-03 11:03:14 +01:00
Merged dmd 2.059beta
This commit is contained in:
191
dmd2/struct.c
191
dmd2/struct.c
@@ -1,6 +1,6 @@
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2011 by Digital Mars
|
||||
// Copyright (c) 1999-2012 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
@@ -39,7 +39,7 @@ AggregateDeclaration::AggregateDeclaration(Loc loc, Identifier *id)
|
||||
alignsize = 0; // size of struct for alignment purposes
|
||||
structalign = 0; // struct member alignment in effect
|
||||
hasUnions = 0;
|
||||
sizeok = 0; // size not determined yet
|
||||
sizeok = SIZEOKnone; // size not determined yet
|
||||
deferred = NULL;
|
||||
isdeprecated = false;
|
||||
inv = NULL;
|
||||
@@ -129,9 +129,46 @@ unsigned AggregateDeclaration::size(Loc loc)
|
||||
//printf("AggregateDeclaration::size() %s, scope = %p\n", toChars(), scope);
|
||||
if (!members)
|
||||
error(loc, "unknown size");
|
||||
if (sizeok != 1 && scope)
|
||||
if (sizeok != SIZEOKdone && scope)
|
||||
semantic(NULL);
|
||||
if (sizeok != 1)
|
||||
|
||||
StructDeclaration *sd = isStructDeclaration();
|
||||
if (sizeok != SIZEOKdone && sd && sd->members)
|
||||
{
|
||||
/* See if enough is done to determine the size,
|
||||
* meaning all the fields are done.
|
||||
*/
|
||||
struct SV
|
||||
{
|
||||
static int func(Dsymbol *s, void *param)
|
||||
{ SV *psv = (SV *)param;
|
||||
VarDeclaration *v = s->isVarDeclaration();
|
||||
if (v)
|
||||
{
|
||||
if (v->scope)
|
||||
v->semantic(NULL);
|
||||
if (v->storage_class & (STCstatic | STCextern | STCtls | STCgshared | STCconst | STCimmutable | STCmanifest | STCctfe | STCtemplateparameter))
|
||||
return 0;
|
||||
if (v->storage_class & STCfield && v->sem >= SemanticDone)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
SV sv;
|
||||
|
||||
for (size_t i = 0; i < members->dim; i++)
|
||||
{ Dsymbol *s = (*members)[i];
|
||||
if (s->apply(&SV::func, &sv))
|
||||
goto L1;
|
||||
}
|
||||
sd->finalizeSize(NULL);
|
||||
|
||||
L1: ;
|
||||
}
|
||||
|
||||
if (sizeok != SIZEOKdone)
|
||||
{ error(loc, "no size yet for forward reference");
|
||||
//*(char*)0=0;
|
||||
}
|
||||
@@ -175,76 +212,38 @@ void AggregateDeclaration::alignmember(
|
||||
//printf("result = %d\n",offset);
|
||||
}
|
||||
|
||||
|
||||
void AggregateDeclaration::addField(Scope *sc, VarDeclaration *v)
|
||||
/****************************************
|
||||
* Place a member (mem) into an aggregate (agg), which can be a struct, union or class
|
||||
* Returns:
|
||||
* offset to place field at
|
||||
*/
|
||||
unsigned AggregateDeclaration::placeField(
|
||||
unsigned *nextoffset, // next location in aggregate
|
||||
unsigned memsize, // size of member
|
||||
unsigned memalignsize, // size of member for alignment purposes
|
||||
unsigned memalign, // alignment in effect for this member
|
||||
unsigned *paggsize, // size of aggregate (updated)
|
||||
unsigned *paggalignsize, // size of aggregate for alignment purposes (updated)
|
||||
bool isunion // the aggregate is a union
|
||||
)
|
||||
{
|
||||
unsigned memsize; // size of member
|
||||
unsigned memalignsize; // size of member for alignment purposes
|
||||
unsigned xalign; // alignment boundaries
|
||||
|
||||
//printf("AggregateDeclaration::addField('%s') %s\n", v->toChars(), toChars());
|
||||
assert(!(v->storage_class & (STCstatic | STCextern | STCparameter | STCtls)));
|
||||
|
||||
// Check for forward referenced types which will fail the size() call
|
||||
Type *t = v->type->toBasetype();
|
||||
if (v->storage_class & STCref)
|
||||
{ // References are the size of a pointer
|
||||
t = Type::tvoidptr;
|
||||
}
|
||||
if (t->ty == Tstruct /*&& isStructDeclaration()*/)
|
||||
{ TypeStruct *ts = (TypeStruct *)t;
|
||||
#if DMDV2
|
||||
if (ts->sym == this)
|
||||
{
|
||||
error("cannot have field %s with same struct type", v->toChars());
|
||||
}
|
||||
#endif
|
||||
|
||||
if (ts->sym->sizeok != 1 && ts->sym->scope)
|
||||
ts->sym->semantic(NULL);
|
||||
if (ts->sym->sizeok != 1)
|
||||
{
|
||||
sizeok = 2; // cannot finish; flag as forward referenced
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (t->ty == Tident)
|
||||
{
|
||||
sizeok = 2; // cannot finish; flag as forward referenced
|
||||
return;
|
||||
}
|
||||
|
||||
memsize = t->size(loc);
|
||||
memalignsize = t->alignsize();
|
||||
xalign = t->memalign(sc->structalign);
|
||||
#if 0
|
||||
alignmember(xalign, memalignsize, &sc->offset);
|
||||
v->offset = sc->offset;
|
||||
sc->offset += memsize;
|
||||
if (sc->offset > structsize)
|
||||
structsize = sc->offset;
|
||||
#else
|
||||
unsigned ofs = sc->offset;
|
||||
alignmember(xalign, memalignsize, &ofs);
|
||||
v->offset = ofs;
|
||||
unsigned ofs = *nextoffset;
|
||||
alignmember(memalign, memalignsize, &ofs);
|
||||
unsigned memoffset = ofs;
|
||||
ofs += memsize;
|
||||
if (ofs > structsize)
|
||||
structsize = ofs;
|
||||
if (!isUnionDeclaration())
|
||||
sc->offset = ofs;
|
||||
#endif
|
||||
if (global.params.is64bit && sc->structalign == 8 && memalignsize == 16 && isUnionDeclaration())
|
||||
if (ofs > *paggsize)
|
||||
*paggsize = ofs;
|
||||
if (!isunion)
|
||||
*nextoffset = ofs;
|
||||
if (global.params.is64bit && memalign == 8 && memalignsize == 16)
|
||||
/* Not sure how to handle this */
|
||||
;
|
||||
else if (sc->structalign < memalignsize)
|
||||
memalignsize = sc->structalign;
|
||||
if (alignsize < memalignsize)
|
||||
alignsize = memalignsize;
|
||||
//printf("\t%s: alignsize = %d\n", toChars(), alignsize);
|
||||
else if (memalign < memalignsize)
|
||||
memalignsize = memalign;
|
||||
if (*paggalignsize < memalignsize)
|
||||
*paggalignsize = memalignsize;
|
||||
|
||||
v->storage_class |= STCfield;
|
||||
//printf(" addField '%s' to '%s' at offset %d, size = %d\n", v->toChars(), toChars(), v->offset, memsize);
|
||||
fields.push(v);
|
||||
return memoffset;
|
||||
}
|
||||
|
||||
|
||||
@@ -363,7 +362,7 @@ void StructDeclaration::semantic(Scope *sc)
|
||||
return;
|
||||
|
||||
if (symtab)
|
||||
{ if (sizeok == 1 || !scope)
|
||||
{ if (sizeok == SIZEOKdone || !scope)
|
||||
{ //printf("already completed\n");
|
||||
scope = NULL;
|
||||
return; // semantic() already completed
|
||||
@@ -398,16 +397,8 @@ void StructDeclaration::semantic(Scope *sc)
|
||||
assert(!isAnonymous());
|
||||
if (sc->stc & STCabstract)
|
||||
error("structs, unions cannot be abstract");
|
||||
#if DMDV2
|
||||
if (storage_class & STCimmutable)
|
||||
type = type->addMod(MODimmutable);
|
||||
if (storage_class & STCconst)
|
||||
type = type->addMod(MODconst);
|
||||
if (storage_class & STCshared)
|
||||
type = type->addMod(MODshared);
|
||||
#endif
|
||||
|
||||
if (sizeok == 0) // if not already done the addMember step
|
||||
if (sizeok == SIZEOKnone) // if not already done the addMember step
|
||||
{
|
||||
int hasfunctions = 0;
|
||||
for (size_t i = 0; i < members->dim; i++)
|
||||
@@ -453,7 +444,7 @@ void StructDeclaration::semantic(Scope *sc)
|
||||
}
|
||||
}
|
||||
|
||||
sizeok = 0;
|
||||
sizeok = SIZEOKnone;
|
||||
sc2 = sc->push(this);
|
||||
sc2->stc &= STCsafe | STCtrusted | STCsystem;
|
||||
sc2->parent = this;
|
||||
@@ -472,7 +463,7 @@ void StructDeclaration::semantic(Scope *sc)
|
||||
/* There are problems doing this in the general case because
|
||||
* Scope keeps track of things like 'offset'
|
||||
*/
|
||||
if (s->isEnumDeclaration() || (s->isAggregateDeclaration() && s->ident))
|
||||
//if (s->isEnumDeclaration() || (s->isAggregateDeclaration() && s->ident))
|
||||
{
|
||||
//printf("setScope %s %s\n", s->kind(), s->toChars());
|
||||
s->setScope(sc2);
|
||||
@@ -490,15 +481,27 @@ void StructDeclaration::semantic(Scope *sc)
|
||||
*/
|
||||
if (i + 1 == members_dim)
|
||||
{
|
||||
if (sizeok == 0 && s->isAliasDeclaration())
|
||||
finalizeSize();
|
||||
if (sizeok == SIZEOKnone && s->isAliasDeclaration())
|
||||
finalizeSize(sc2);
|
||||
}
|
||||
// Ungag errors when not speculative
|
||||
unsigned oldgag = global.gag;
|
||||
if (global.isSpeculativeGagging() && !isSpeculative())
|
||||
global.gag = 0;
|
||||
s->semantic(sc2);
|
||||
global.gag = oldgag;
|
||||
}
|
||||
finalizeSize(sc2);
|
||||
|
||||
if (sizeok == 2)
|
||||
if (sizeok == SIZEOKfwd)
|
||||
{ // semantic() failed because of forward references.
|
||||
// Unwind what we did, and defer it for later
|
||||
for (size_t i = 0; i < fields.dim; i++)
|
||||
{ Dsymbol *s = fields[i];
|
||||
VarDeclaration *vd = s->isVarDeclaration();
|
||||
if (vd)
|
||||
vd->offset = 0;
|
||||
}
|
||||
fields.setDim(0);
|
||||
structsize = 0;
|
||||
alignsize = 0;
|
||||
@@ -513,7 +516,6 @@ void StructDeclaration::semantic(Scope *sc)
|
||||
return;
|
||||
}
|
||||
|
||||
finalizeSize();
|
||||
Module::dprogress++;
|
||||
|
||||
//printf("-StructDeclaration::semantic(this=%p, '%s')\n", this, toChars());
|
||||
@@ -522,7 +524,7 @@ void StructDeclaration::semantic(Scope *sc)
|
||||
zeroInit = 1;
|
||||
for (size_t i = 0; i < fields.dim; i++)
|
||||
{
|
||||
Dsymbol *s = fields.tdata()[i];
|
||||
Dsymbol *s = fields[i];
|
||||
VarDeclaration *vd = s->isVarDeclaration();
|
||||
if (vd && !vd->isDataseg())
|
||||
{
|
||||
@@ -661,8 +663,21 @@ Dsymbol *StructDeclaration::search(Loc loc, Identifier *ident, int flags)
|
||||
return ScopeDsymbol::search(loc, ident, flags);
|
||||
}
|
||||
|
||||
void StructDeclaration::finalizeSize()
|
||||
void StructDeclaration::finalizeSize(Scope *sc)
|
||||
{
|
||||
if (sizeok != SIZEOKnone)
|
||||
return;
|
||||
|
||||
// Set the offsets of the fields and determine the size of the struct
|
||||
unsigned offset = 0;
|
||||
bool isunion = isUnionDeclaration() != NULL;
|
||||
for (size_t i = 0; i < members->dim; i++)
|
||||
{ Dsymbol *s = (*members)[i];
|
||||
s->setFieldOffset(this, &offset, isunion);
|
||||
}
|
||||
if (sizeok == SIZEOKfwd)
|
||||
return;
|
||||
|
||||
// 0 sized struct's are set to 1 byte
|
||||
if (structsize == 0)
|
||||
{
|
||||
@@ -675,7 +690,7 @@ void StructDeclaration::finalizeSize()
|
||||
// aligned properly.
|
||||
structsize = (structsize + alignsize - 1) & ~(alignsize - 1);
|
||||
|
||||
sizeok = 1;
|
||||
sizeok = SIZEOKdone;
|
||||
}
|
||||
|
||||
void StructDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
|
||||
Reference in New Issue
Block a user