258 changes: 209 additions & 49 deletions src/dclass.d

Large diffs are not rendered by default.

93 changes: 84 additions & 9 deletions src/dstruct.d
Original file line number Diff line number Diff line change
Expand Up @@ -258,49 +258,64 @@ public:

override Dsymbol syntaxCopy(Dsymbol s)
{
StructDeclaration sd = s ? cast(StructDeclaration)s : new StructDeclaration(loc, ident);
StructDeclaration sd =
s ? cast(StructDeclaration)s
: new StructDeclaration(loc, ident);
return ScopeDsymbol.syntaxCopy(sd);
}

override final void semantic(Scope* sc)
{
//printf("+StructDeclaration::semantic(this=%p, %s '%s', sizeok = %d)\n", this, parent->toChars(), toChars(), sizeok);
//printf("StructDeclaration::semantic(this=%p, %s '%s', sizeok = %d)\n", this, parent.toChars(), toChars(), sizeok);

//static int count; if (++count == 20) assert(0);

if (semanticRun >= PASSsemanticdone)
return;
uint dprogress_save = Module.dprogress;
int errors = global.errors;

//printf("+StructDeclaration::semantic(this=%p, %s '%s', sizeok = %d)\n", this, parent.toChars(), toChars(), sizeok);
Scope* scx = null;
if (_scope)
{
sc = _scope;
scx = _scope; // save so we don't make redundant copies
_scope = null;
}

if (!parent)
{
assert(sc.parent && sc.func);
parent = sc.parent;
}
assert(parent && !isAnonymous());

if (this.errors)
type = Type.terror;
type = type.semantic(loc, sc);
if (type.ty == Tstruct && (cast(TypeStruct)type).sym != this)
{
TemplateInstance ti = (cast(TypeStruct)type).sym.isInstantiated();
if (ti && isError(ti))
(cast(TypeStruct)type).sym = this;
}

// Ungag errors when not speculative
Ungag ungag = ungagSpeculative();

if (semanticRun == PASSinit)
{
protection = sc.protection;

alignment = sc.structalign;

storage_class |= sc.stc;
if (storage_class & STCdeprecated)
isdeprecated = true;
if (storage_class & STCabstract)
error("structs, unions cannot be abstract");

userAttribDecl = sc.userAttribDecl;
}
else if (symtab && !scx)
Expand All @@ -309,13 +324,15 @@ public:
return;
}
semanticRun = PASSsemantic;

if (!members) // if opaque declaration
{
semanticRun = PASSsemanticdone;
return;
}
if (!symtab)
symtab = new DsymbolTable();

if (sizeok == SIZEOKnone) // if not already done the addMember step
{
for (size_t i = 0; i < members.dim; i++)
Expand All @@ -325,6 +342,7 @@ public:
s.addMember(sc, this);
}
}

Scope* sc2 = sc.push(this);
sc2.stc &= STCsafe | STCtrusted | STCsystem;
sc2.parent = this;
Expand All @@ -334,9 +352,11 @@ public:
sc2.explicitProtection = 0;
sc2.structalign = STRUCTALIGN_DEFAULT;
sc2.userAttribDecl = null;

if (sizeok == SIZEOKdone)
goto LafterSizeok;
sizeok = SIZEOKnone;

/* Set scope so if there are forward references, we still might be able to
* resolve individual members like enums.
*/
Expand All @@ -346,17 +366,21 @@ public:
//printf("struct: setScope %s %s\n", s->kind(), s->toChars());
s.setScope(sc2);
}

for (size_t i = 0; i < members.dim; i++)
{
Dsymbol s = (*members)[i];
s.importAll(sc2);
}

for (size_t i = 0; i < members.dim; i++)
{
Dsymbol s = (*members)[i];
s.semantic(sc2);
}

finalizeSize(sc2);

if (sizeok == SIZEOKfwd)
{
// semantic() failed because of forward references.
Expand All @@ -369,16 +393,20 @@ public:
fields.setDim(0);
structsize = 0;
alignsize = 0;

sc2.pop();

_scope = scx ? scx : sc.copy();
_scope.setNoFree();
_scope._module.addDeferredSemantic(this);
Module.dprogress = dprogress_save;
//printf("\tdeferring %s\n", toChars());
return;
}

Module.dprogress++;
//printf("-StructDeclaration::semantic(this=%p, '%s')\n", this, toChars());

LafterSizeok:
// The additions of special member functions should have its own
// sub-semantic analysis pass, and have to be deferred sometimes.
Expand All @@ -392,17 +420,21 @@ public:
StructDeclaration sd = (cast(TypeStruct)tb).sym;
if (sd.semanticRun >= PASSsemanticdone)
continue;

sc2.pop();

_scope = scx ? scx : sc.copy();
_scope.setNoFree();
_scope._module.addDeferredSemantic(this);
//printf("\tdeferring %s\n", toChars());
return;
}

/* Look for special member functions.
*/
aggNew = cast(NewDeclaration)search(Loc(), Id.classNew);
aggDelete = cast(DeleteDeclaration)search(Loc(), Id.classDelete);

// this->ctor is already set in finalizeSize()

dtor = buildDtor(this, sc2);
Expand All @@ -426,7 +458,9 @@ public:
* See semanticTypeInfo().
*/
inv = buildInv(this, sc2);

sc2.pop();

if (ctor)
{
Dsymbol scall = search(Loc(), Id.call);
Expand All @@ -439,15 +473,18 @@ public:
FuncDeclaration fcall = resolveFuncCall(loc, sc, scall, null, null, null, 1);
sc = sc.pop();
global.endGagging(xerrors);

if (fcall && fcall.isStatic())
{
error(fcall.loc, "static opCall is hidden by constructors and can never be called");
errorSupplemental(fcall.loc, "Please use a factory method instead, or replace all constructors with static opCall.");
}
}
}

Module.dprogress++;
semanticRun = PASSsemanticdone;

TypeTuple tup = toArgTypes(type);
size_t dim = tup.arguments.dim;
if (dim >= 1)
Expand All @@ -457,8 +494,10 @@ public:
if (dim == 2)
arg2type = (*tup.arguments)[1].type;
}

if (sc.func)
semantic2(sc);

if (global.errors != errors)
{
// The type is no good.
Expand All @@ -467,11 +506,13 @@ public:
if (deferred)
deferred.errors = true;
}

if (deferred && !global.gag)
{
deferred.semantic2(sc);
deferred.semantic3(sc);
}

version (none)
{
if (type.ty == Tstruct && (cast(TypeStruct)type).sym != this)
Expand All @@ -485,34 +526,51 @@ public:

final void semanticTypeInfoMembers()
{
if (xeq && xeq._scope && xeq.semanticRun < PASSsemantic3done)
if (xeq &&
xeq._scope &&
xeq.semanticRun < PASSsemantic3done)
{
uint errors = global.startGagging();
xeq.semantic3(xeq._scope);
if (global.endGagging(errors))
xeq = xerreq;
}
if (xcmp && xcmp._scope && xcmp.semanticRun < PASSsemantic3done)

if (xcmp &&
xcmp._scope &&
xcmp.semanticRun < PASSsemantic3done)
{
uint errors = global.startGagging();
xcmp.semantic3(xcmp._scope);
if (global.endGagging(errors))
xcmp = xerrcmp;
}

FuncDeclaration ftostr = search_toString(this);
if (ftostr && ftostr._scope && ftostr.semanticRun < PASSsemantic3done)
if (ftostr &&
ftostr._scope &&
ftostr.semanticRun < PASSsemantic3done)
{
ftostr.semantic3(ftostr._scope);
}
if (xhash && xhash._scope && xhash.semanticRun < PASSsemantic3done)

if (xhash &&
xhash._scope &&
xhash.semanticRun < PASSsemantic3done)
{
xhash.semantic3(xhash._scope);
}
if (postblit && postblit._scope && postblit.semanticRun < PASSsemantic3done)

if (postblit &&
postblit._scope &&
postblit.semanticRun < PASSsemantic3done)
{
postblit.semantic3(postblit._scope);
}
if (dtor && dtor._scope && dtor.semanticRun < PASSsemantic3done)

if (dtor &&
dtor._scope &&
dtor.semanticRun < PASSsemantic3done)
{
dtor.semantic3(dtor._scope);
}
Expand All @@ -523,11 +581,13 @@ public:
//printf("%s.StructDeclaration::search('%s')\n", toChars(), ident->toChars());
if (_scope && !symtab)
semantic(_scope);

if (!members || !symtab) // opaque or semantic() is not yet called
{
error("is forward referenced when looking for '%s'", ident.toChars());
return null;
}

return ScopeDsymbol.search(loc, ident, flags);
}

Expand Down Expand Up @@ -634,13 +694,15 @@ public:
{
if (!elements)
return true;

size_t nfields = fields.dim - isNested();
size_t offset = 0;
for (size_t i = 0; i < elements.dim; i++)
{
Expression e = (*elements)[i];
if (!e)
continue;

e = resolveProperties(sc, e);
if (i >= nfields)
{
Expand All @@ -659,11 +721,13 @@ public:
return false;
}
offset = cast(uint)(v.offset + v.type.size());

Type t = v.type;
if (stype)
t = t.addMod(stype.mod);
Type origType = t;
Type tb = t.toBasetype();

/* Look for case of initializing a static array with a too-short
* string literal, such as:
* char[5] foo = "abc";
Expand All @@ -675,12 +739,16 @@ public:
StringExp se = cast(StringExp)e;
Type typeb = se.type.toBasetype();
TY tynto = tb.nextOf().ty;
if (!se.committed && (typeb.ty == Tarray || typeb.ty == Tsarray) && (tynto == Tchar || tynto == Twchar || tynto == Tdchar) && se.length(cast(int)tb.nextOf().size()) < (cast(TypeSArray)tb).dim.toInteger())
if (!se.committed &&
(typeb.ty == Tarray || typeb.ty == Tsarray) &&
(tynto == Tchar || tynto == Twchar || tynto == Tdchar) &&
se.length(cast(int)tb.nextOf().size()) < (cast(TypeSArray)tb).dim.toInteger())
{
e = se.castTo(sc, t);
goto L1;
}
}

while (!e.implicitConvTo(t) && tb.ty == Tsarray)
{
/* Static array initialization, as in:
Expand All @@ -691,10 +759,12 @@ public:
}
if (!e.implicitConvTo(t))
t = origType; // restore type for better diagnostic

e = e.implicitCastTo(sc, t);
L1:
if (e.op == TOKerror)
return false;

(*elements)[i] = e.isLvalue() ? callCpCtor(sc, e) : valueNoDtor(e);
}
return true;
Expand All @@ -713,9 +783,12 @@ public:
// If we've already determined whether this struct is POD.
if (ispod != ISPODfwd)
return (ispod == ISPODyes);

ispod = ISPODyes;

if (enclosing || postblit || dtor)
ispod = ISPODno;

// Recursively check all fields are POD.
for (size_t i = 0; i < fields.dim; i++)
{
Expand All @@ -725,6 +798,7 @@ public:
ispod = ISPODno;
break;
}

Type tv = v.type.baseElemOf();
if (tv.ty == Tstruct)
{
Expand All @@ -737,6 +811,7 @@ public:
}
}
}

return (ispod == ISPODyes);
}

Expand Down
4 changes: 4 additions & 0 deletions src/dsymbol.d
Original file line number Diff line number Diff line change
Expand Up @@ -546,12 +546,16 @@ public:
if (!s2.overloadInsert(this))
{
sds.multiplyDefined(Loc(), this, s2);
errors = true;
}
}
if (sds.isAggregateDeclaration() || sds.isEnumDeclaration())
{
if (ident == Id.__sizeof || ident == Id.__xalignof || ident == Id._mangleof)
{
error(".%s property cannot be redefined", ident.toChars());
errors = true;
}
}
}
}
Expand Down
20 changes: 20 additions & 0 deletions test/fail_compilation/ice15092.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/*
TEST_OUTPUT:
---
fail_compilation/ice15092.d(13): Error: struct ice15092.A.S conflicts with struct ice15092.A.S at fail_compilation/ice15092.d(12)
fail_compilation/ice15092.d(16): Error: class ice15092.A.C conflicts with class ice15092.A.C at fail_compilation/ice15092.d(15)
fail_compilation/ice15092.d(19): Error: interface ice15092.A.I conflicts with interface ice15092.A.I at fail_compilation/ice15092.d(18)
---
*/

class A
{
struct S {}
struct S {}

class C {}
class C {}

interface I {}
interface I {}
}