Skip to content

Commit

Permalink
Merge pull request #7315 from RazvanN7/Issue_17371
Browse files Browse the repository at this point in the history
Fix Issue 17371 -  [REG 2.074.0] di generation broken for anonymous classes
merged-on-behalf-of: unknown
  • Loading branch information
dlang-bot committed Nov 27, 2017
2 parents d6f3b18 + a168267 commit 64bbb40
Show file tree
Hide file tree
Showing 15 changed files with 130 additions and 42 deletions.
19 changes: 15 additions & 4 deletions src/ddmd/aggregate.h
Expand Up @@ -247,6 +247,18 @@ struct ClassFlags
};
};

enum ClassKind
{
/// the class is a d(efault) class
d,
/// the class is a C++ interface
cpp,
/// the class is an Objective-C class/interface
objc,
/// the class is anonymous
anonymous,
};

class ClassDeclaration : public AggregateDeclaration
{
public:
Expand All @@ -273,11 +285,10 @@ class ClassDeclaration : public AggregateDeclaration

TypeInfoClassDeclaration *vclassinfo; // the ClassInfo object for this ClassDeclaration
bool com; // true if this is a COM class (meaning it derives from IUnknown)
bool cpp; // true if this is a C++ interface
bool isobjc; // true if this is an Objective-C class/interface
bool isscope; // true if this is a scope class
bool stack; // true if this is a scope class
ClassKind classKind; // specifies the linkage type

Abstract isabstract; // 0: fwdref, 1: is abstract class, 2: not abstract
int inuse; // to prevent recursive attempts
Baseok baseok; // set the progress of base classes resolving
Symbol *cpp_type_info_ptr_sym; // cached instance of class Id.cpp_type_info_ptr

Expand Down
58 changes: 44 additions & 14 deletions src/ddmd/dclass.d
Expand Up @@ -179,6 +179,24 @@ struct ClassFlags
alias hasDtor = Enum.hasDtor;
}

/**
* The ClassKind enum is used in ClassDeclaration AST nodes
* to specify the linkage type of the class or if it is an
* anonymous class. If the class is anonymous it is also
* considered to be a D class.
*/
enum ClassKind : int
{
/// the class is a d(efault) class
d,
/// the class is a C++ interface
cpp,
/// the class is an Objective-C class/interface
objc,
/// the class is anonymous
anonymous,
}

/***********************************************************
*/
extern (C++) class ClassDeclaration : AggregateDeclaration
Expand Down Expand Up @@ -212,20 +230,32 @@ extern (C++) class ClassDeclaration : AggregateDeclaration
// the ClassInfo object for this ClassDeclaration
TypeInfoClassDeclaration vclassinfo;

bool com; // true if this is a COM class (meaning it derives from IUnknown)
bool cpp; // true if this is a C++ interface
bool isobjc; // true if this is an Objective-C class/interface
bool isscope; // true if this is a scope class
private bool inuse; // to prevent recursive attempts
// true if this is a COM class
bool com;

/// true if this is a scope class
bool stack;

/// specifies whether this is a D, C++, Objective-C or anonymous class/interface
ClassKind classKind;

/// to prevent recursive attempts
private bool inuse;

Abstract isabstract;
Baseok baseok; // set the progress of base classes resolving

/// set the progress of base classes resolving
Baseok baseok;

Symbol* cpp_type_info_ptr_sym; // cached instance of class Id.cpp_type_info_ptr

final extern (D) this(Loc loc, Identifier id, BaseClasses* baseclasses, Dsymbols* members, bool inObject)
{
if (!id)
{
id = Identifier.generateId("__anonclass");
classKind = ClassKind.anonymous;
}
assert(id);

super(loc, id);
Expand Down Expand Up @@ -584,7 +614,7 @@ extern (C++) class ClassDeclaration : AggregateDeclaration

alignsize = baseClass.alignsize;
structsize = baseClass.structsize;
if (cpp && global.params.isWindows)
if (classKind == ClassKind.cpp && global.params.isWindows)
structsize = (structsize + alignsize - 1) & ~(alignsize - 1);
}
else if (isInterfaceDeclaration())
Expand All @@ -599,7 +629,7 @@ extern (C++) class ClassDeclaration : AggregateDeclaration
{
alignsize = Target.ptrsize;
structsize = Target.ptrsize; // allow room for __vptr
if (!cpp)
if (classKind != ClassKind.cpp)
structsize += Target.ptrsize; // allow room for __monitor
}

Expand Down Expand Up @@ -817,7 +847,7 @@ extern (C++) class ClassDeclaration : AggregateDeclaration

final bool isCPPclass() const
{
return cpp;
return classKind == ClassKind.cpp;
}

bool isCPPinterface() const
Expand Down Expand Up @@ -932,7 +962,7 @@ extern (C++) class ClassDeclaration : AggregateDeclaration
*/
int vtblOffset() const
{
return cpp ? 0 : 1;
return classKind == ClassKind.cpp ? 0 : 1;
}

/****************************************
Expand Down Expand Up @@ -973,7 +1003,7 @@ extern (C++) final class InterfaceDeclaration : ClassDeclaration
if (id == Id.IUnknown) // IUnknown is the root of all COM interfaces
{
com = true;
cpp = true; // IUnknown is also a C++ interface
classKind = ClassKind.cpp; // IUnknown is also a C++ interface
}
}

Expand All @@ -991,9 +1021,9 @@ extern (C++) final class InterfaceDeclaration : ClassDeclaration
auto sc2 = super.newScope(sc);
if (com)
sc2.linkage = LINKwindows;
else if (cpp)
else if (classKind == ClassKind.cpp)
sc2.linkage = LINKcpp;
else if (isobjc)
else if (classKind == ClassKind.objc)
sc2.linkage = LINKobjc;
return sc2;
}
Expand Down Expand Up @@ -1087,7 +1117,7 @@ extern (C++) final class InterfaceDeclaration : ClassDeclaration

override bool isCPPinterface() const
{
return cpp;
return classKind == ClassKind.cpp;
}

override bool isCOMinterface() const
Expand Down
2 changes: 1 addition & 1 deletion src/ddmd/declaration.d
Expand Up @@ -1343,7 +1343,7 @@ extern (C++) class VarDeclaration : Declaration

// Destroying C++ scope classes crashes currently. Since C++ class dtors are not currently supported, simply do not run dtors for them.
// See https://issues.dlang.org/show_bug.cgi?id=13182
if (cd.cpp)
if (cd.classKind == ClassKind.cpp)
{
break;
}
Expand Down
24 changes: 12 additions & 12 deletions src/ddmd/dsymbolsem.d
Expand Up @@ -4497,7 +4497,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor

/* These quirky conditions mimic what VC++ appears to do
*/
if (global.params.mscoff && cd.cpp &&
if (global.params.mscoff && cd.classKind == ClassKind.cpp &&
cd.baseClass && cd.baseClass.vtbl.dim)
{
/* if overriding an interface function, then this is not
Expand All @@ -4523,7 +4523,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
{
//printf("\tintroducing function %s\n", toChars());
funcdecl.introducing = 1;
if (cd.cpp && Target.reverseCppOverloads)
if (cd.classKind == ClassKind.cpp && Target.reverseCppOverloads)
{
// with dmc, overloaded functions are grouped and in reverse order
funcdecl.vtblIndex = cast(int)cd.vtbl.dim;
Expand Down Expand Up @@ -5594,14 +5594,14 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
if (cldec.storage_class & STCauto)
cldec.error("storage class 'auto' is invalid when declaring a class, did you mean to use 'scope'?");
if (cldec.storage_class & STCscope)
cldec.isscope = true;
cldec.stack = true;
if (cldec.storage_class & STCabstract)
cldec.isabstract = ABSyes;

cldec.userAttribDecl = sc.userAttribDecl;

if (sc.linkage == LINKcpp)
cldec.cpp = true;
cldec.classKind = ClassKind.cpp;
if (sc.linkage == LINKobjc)
objc.setObjc(cldec);
}
Expand Down Expand Up @@ -5795,7 +5795,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
cldec.baseok = BASEOKdone;

// If no base class, and this is not an Object, use Object as base class
if (!cldec.baseClass && cldec.ident != Id.Object && !cldec.cpp)
if (!cldec.baseClass && cldec.ident != Id.Object && !cldec.classKind == ClassKind.cpp)
{
void badObjectDotD()
{
Expand Down Expand Up @@ -5829,9 +5829,9 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
if (cldec.baseClass.isCOMclass())
cldec.com = true;
if (cldec.baseClass.isCPPclass())
cldec.cpp = true;
if (cldec.baseClass.isscope)
cldec.isscope = true;
cldec.classKind = ClassKind.cpp;
if (cldec.baseClass.stack)
cldec.stack = true;
cldec.enclosing = cldec.baseClass.enclosing;
cldec.storage_class |= cldec.baseClass.storage_class & STC_TYPECTOR;
}
Expand All @@ -5843,7 +5843,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
// then this is a COM interface too.
if (b.sym.isCOMinterface())
cldec.com = true;
if (cldec.cpp && !b.sym.isCPPinterface())
if (cldec.classKind == ClassKind.cpp && !b.sym.isCPPinterface())
{
error(cldec.loc, "C++ class '%s' cannot implement D interface '%s'",
cldec.toPrettyChars(), b.sym.toPrettyChars());
Expand Down Expand Up @@ -5917,7 +5917,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
// initialize vtbl
if (cldec.baseClass)
{
if (cldec.cpp && cldec.baseClass.vtbl.dim == 0)
if (cldec.classKind == ClassKind.cpp && cldec.baseClass.vtbl.dim == 0)
{
cldec.error("C++ base class %s needs at least one virtual function", cldec.baseClass.toChars());
}
Expand Down Expand Up @@ -6256,7 +6256,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
}

if (!idec.baseclasses.dim && sc.linkage == LINKcpp)
idec.cpp = true;
idec.classKind = ClassKind.cpp;

if (sc.linkage == LINKobjc)
objc.setObjc(idec);
Expand Down Expand Up @@ -6333,7 +6333,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
if (b.sym.isCOMinterface())
idec.com = true;
if (b.sym.isCPPinterface())
idec.cpp = true;
idec.classKind = ClassKind.cpp;
}

interfaceSemantic(idec);
Expand Down
4 changes: 2 additions & 2 deletions src/ddmd/e2ir.d
Expand Up @@ -4180,9 +4180,9 @@ elem *toElem(Expression e, IRState *irs)
// Casting from derived class to base class is a no-op
}
}
else if (cdfrom.cpp)
else if (cdfrom.classKind == ClassKind.cpp)
{
if (cdto.cpp)
if (cdto.classKind == ClassKind.cpp)
{
/* Casting from a C++ interface to a C++ interface
* is always a 'paint' operation
Expand Down
5 changes: 3 additions & 2 deletions src/ddmd/hdrgen.d
Expand Up @@ -1756,7 +1756,7 @@ public:

override void visit(ClassDeclaration d)
{
if (!d.isAnonymous())
if (d.classKind != ClassKind.anonymous)
{
buf.writestring(d.kind());
buf.writeByte(' ');
Expand All @@ -1783,7 +1783,8 @@ public:
{
if (!d || !d.baseclasses.dim)
return;
buf.writestring(" : ");
if (d.classKind != ClassKind.anonymous)
buf.writestring(" : ");
foreach (i, b; *d.baseclasses)
{
if (i)
Expand Down
2 changes: 1 addition & 1 deletion src/ddmd/mtype.d
Expand Up @@ -8534,7 +8534,7 @@ extern (C++) final class TypeClass : Type

override bool isscope() const
{
return sym.isscope;
return sym.stack;
}

override bool isBoolean() const
Expand Down
4 changes: 2 additions & 2 deletions src/ddmd/objc.d
Expand Up @@ -188,12 +188,12 @@ extern(C++) private final class Supported : Objc

override void setObjc(ClassDeclaration cd)
{
cd.isobjc = true;
cd.classKind = ClassKind.objc;
}

override void setObjc(InterfaceDeclaration id)
{
id.isobjc = true;
id.classKind = ClassKind.objc;
}

override void setSelector(FuncDeclaration fd, Scope* sc)
Expand Down
2 changes: 1 addition & 1 deletion src/ddmd/opover.d
Expand Up @@ -1145,7 +1145,7 @@ extern (C++) Expression op_overload(Expression e, Scope* sc)
{
ClassDeclaration cd1 = t1.isClassHandle();
ClassDeclaration cd2 = t2.isClassHandle();
if (!(cd1.cpp || cd2.cpp))
if (!(cd1.classKind == ClassKind.cpp || cd2.classKind == ClassKind.cpp))
{
/* Rewrite as:
* .object.opEquals(e1, e2)
Expand Down
2 changes: 1 addition & 1 deletion src/ddmd/tocvdebug.d
Expand Up @@ -538,7 +538,7 @@ void toDebug(ClassDeclaration cd)
//printf("ClassDeclaration::toDebug('%s')\n", cd.toChars());

assert(config.fulltypes >= CV4);
if (cd.isAnonymous())
if (cd.classKind == ClassKind.anonymous)
return /*0*/;

if (typidx) // if reference already generated
Expand Down
2 changes: 1 addition & 1 deletion src/ddmd/todt.d
Expand Up @@ -719,7 +719,7 @@ private void membersToDt(AggregateDeclaration ad, DtBuilder dtb,
{
dtb.xoff(toVtblSymbol(concreteType), 0); // __vptr
offset = Target.ptrsize;
if (!cd.cpp)
if (!cd.classKind == ClassKind.cpp)
{
dtb.size(0); // __monitor
offset += Target.ptrsize;
Expand Down
2 changes: 1 addition & 1 deletion src/ddmd/toobj.d
Expand Up @@ -421,7 +421,7 @@ void toObjFile(Dsymbol ds, bool multiobj)
dtb.size(0); // monitor

// m_init[]
assert(cd.structsize >= 8 || (cd.cpp && cd.structsize >= 4));
assert(cd.structsize >= 8 || (cd.classKind == ClassKind.cpp && cd.structsize >= 4));
dtb.size(cd.structsize); // size
dtb.xoff(sinit, 0, TYnptr); // initializer

Expand Down
12 changes: 12 additions & 0 deletions test/compilable/extra-files/header2.d
Expand Up @@ -158,3 +158,15 @@ void leFoo()()
sign = a == 2 ? false : sign ^ (y < 0);
sign = 2 + 3 | 7 + 5;
}

// 17371
interface LeInterface
{}
class LeClass
{
this()
{
auto foo = new class () LeInterface {};
}
}
const levar = new class LeClass, LeInterface {};
17 changes: 17 additions & 0 deletions test/compilable/extra-files/header2.di
Expand Up @@ -114,3 +114,20 @@ void leFoo()()
sign = a == 2 ? false : sign ^ (y < 0);
sign = 2 + 3 | 7 + 5;
}
interface LeInterface
{
}
class LeClass
{
this()
{
auto foo = new class LeInterface
{
}
;
}
}
const levar = new class LeClass, LeInterface
{
}
;

0 comments on commit 64bbb40

Please sign in to comment.