+2020-04-29 Iain Buclaw <ibuclaw@gdcproject.org>
+
+ * d-codegen.cc (d_decl_context): Don't include module in the name of
+ class and struct types that aren't extern(D).
+
2020-04-27 Iain Buclaw <ibuclaw@gdcproject.org>
PR d/94777
{
Dsymbol *parent = dsym;
Declaration *decl = dsym->isDeclaration ();
+ AggregateDeclaration *ad = dsym->isAggregateDeclaration ();
while ((parent = parent->toParent2 ()))
{
but only for extern(D) symbols. */
if (parent->isModule ())
{
- if (decl != NULL && decl->linkage != LINKd)
+ if ((decl != NULL && decl->linkage != LINKd)
+ || (ad != NULL && ad->classKind != ClassKind::d))
return NULL_TREE;
return build_import_decl (parent);
-f8a1a515346b16ebbd9da56a908540cbef1ee582
+06160ccaed7af7955d169024f417c43beb7a8f9f
The first line of this file holds the git revision number of the last
merge done from the dlang/dmd repository.
FuncDeclaration *buildInv(AggregateDeclaration *ad, Scope *sc);
FuncDeclaration *search_toString(StructDeclaration *sd);
+struct ClassKind
+{
+ enum Type
+ {
+ /// the class is a d(efault) class
+ d,
+ /// the class is a C++ interface
+ cpp,
+ /// the class is an Objective-C class/interface
+ objc,
+ };
+};
+
class AggregateDeclaration : public ScopeDsymbol
{
public:
Dsymbol *deferred; // any deferred semantic2() or semantic3() symbol
bool isdeprecated; // true if deprecated
+ ClassKind::Type classKind; // specifies the linkage type
+
/* !=NULL if is nested
* pointing to the dsymbol that directly enclosing it.
* 1. The function that enclosing it (nested struct and class)
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
Abstract isabstract; // 0: fwdref, 1: is abstract class, 2: not abstract
int inuse; // to prevent recursive attempts
}
com = false;
- cpp = false;
isscope = false;
isabstract = ABSfwdref;
inuse = 0;
baseok = BASEOKnone;
- isobjc = false;
cpp_type_info_ptr_sym = NULL;
}
userAttribDecl = sc->userAttribDecl;
if (sc->linkage == LINKcpp)
- cpp = true;
+ classKind = ClassKind::cpp;
if (sc->linkage == LINKobjc)
objc()->setObjc(this);
}
baseok = BASEOKdone;
// If no base class, and this is not an Object, use Object as base class
- if (!baseClass && ident != Id::Object && !cpp)
+ if (!baseClass && ident != Id::Object && !isCPPclass())
{
if (!object || object->errors)
badObjectDotD(this);
if (baseClass->isCOMclass())
com = true;
if (baseClass->isCPPclass())
- cpp = true;
+ classKind = ClassKind::cpp;
if (baseClass->isscope)
isscope = true;
enclosing = baseClass->enclosing;
// then this is a COM interface too.
if (b->sym->isCOMinterface())
com = true;
- if (cpp && !b->sym->isCPPinterface())
+ if (isCPPclass() && !b->sym->isCPPinterface())
{
::error(loc, "C++ class '%s' cannot implement D interface '%s'",
toPrettyChars(), b->sym->toPrettyChars());
// initialize vtbl
if (baseClass)
{
- if (cpp && baseClass->vtbl.dim == 0)
+ if (isCPPclass() && baseClass->vtbl.dim == 0)
{
error("C++ base class %s needs at least one virtual function", baseClass->toChars());
}
alignsize = baseClass->alignsize;
structsize = baseClass->structsize;
- if (cpp && global.params.isWindows)
+ if (isCPPclass() && global.params.isWindows)
structsize = (structsize + alignsize - 1) & ~(alignsize - 1);
}
else if (isInterfaceDeclaration())
{
alignsize = Target::ptrsize;
structsize = Target::ptrsize; // allow room for __vptr
- if (!cpp)
+ if (!isCPPclass())
structsize += Target::ptrsize; // allow room for __monitor
}
bool ClassDeclaration::isCPPclass() const
{
- return cpp;
+ return classKind == ClassKind::cpp;
}
bool ClassDeclaration::isCPPinterface() const
int ClassDeclaration::vtblOffset() const
{
- return cpp ? 0 : 1;
+ return classKind == ClassKind::cpp ? 0 : 1;
}
/****************************************
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
}
}
Scope *sc2 = ClassDeclaration::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;
}
}
if (!baseclasses->dim && sc->linkage == LINKcpp)
- cpp = true;
+ classKind = ClassKind::cpp;
if (sc->linkage == LINKobjc)
objc()->setObjc(this);
if (b->sym->isCOMinterface())
com = true;
if (b->sym->isCPPinterface())
- cpp = true;
+ classKind = ClassKind::cpp;
}
interfaceSemantic(sc);
bool InterfaceDeclaration::isCPPinterface() const
{
- return cpp;
+ return classKind == ClassKind::cpp;
}
/*******************************************
// 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->isCPPclass())
{
break;
}
sizeok = SIZEOKnone; // size not determined yet
deferred = NULL;
isdeprecated = false;
+ classKind = ClassKind::d;
inv = NULL;
aggNew = NULL;
aggDelete = NULL;
if (storage_class & STCabstract)
error("structs, unions cannot be abstract");
userAttribDecl = sc->userAttribDecl;
+
+ if (sc->linkage == LINKcpp)
+ classKind = ClassKind::cpp;
}
else if (symtab && !scx)
{
/* These quirky conditions mimic what VC++ appears to do
*/
- if (global.params.mscoff && cd->cpp &&
+ if (global.params.mscoff && cd->isCPPclass() &&
cd->baseClass && cd->baseClass->vtbl.dim)
{
/* if overriding an interface function, then this is not
{
//printf("\tintroducing function %s\n", toChars());
introducing = 1;
- if (cd->cpp && Target::reverseCppOverloads)
+ if (cd->isCPPclass() && Target::reverseCppOverloads)
{
// with dmc, overloaded functions are grouped and in reverse order
vtblIndex = (int)cd->vtbl.dim;
ClassDeclaration *cd1 = t1->isClassHandle();
ClassDeclaration *cd2 = t2->isClassHandle();
- if (!(cd1->cpp || cd2->cpp))
+ if (!(cd1->isCPPclass() || cd2->isCPPclass()))
{
/* Rewrite as:
* .object.opEquals(e1, e2)
{
Dsymbol *s = getDsymbol(o);
Declaration *d = NULL;
- if (!s || (d = s->isDeclaration()) == NULL)
+ AggregateDeclaration *ad = NULL;
+ if (!s || ((d = s->isDeclaration()) == NULL
+ && (ad = s->isAggregateDeclaration()) == NULL))
{
e->error("argument to `__traits(getLinkage, %s)` is not a declaration", o->toChars());
return new ErrorExp();
}
- link = d->linkage;
+ if (d != NULL)
+ link = d->linkage;
+ else
+ {
+ switch (ad->classKind)
+ {
+ case ClassKind::d:
+ link = LINKd;
+ break;
+ case ClassKind::cpp:
+ link = LINKcpp;
+ break;
+ case ClassKind::objc:
+ link = LINKobjc;
+ break;
+ default:
+ assert(0);
+ }
+ }
}
const char *linkage = linkageToChars(link);
StringExp *se = new StringExp(e->loc, const_cast<char *>(linkage));
void nested() { }
static assert(__traits(getLinkage, typeof(&nested)) == "D");
}
+
+class FooD {}
+interface FooDInterface {}
+extern (C++) class FooCpp {}
+extern (C++) struct FooCppStruct {}
+extern (C++) interface FooCppInterface {}
+
+static assert(__traits(getLinkage, FooD) == "D");
+static assert(__traits(getLinkage, FooDInterface) == "D");
+static assert(__traits(getLinkage, FooCpp) == "C++");
+static assert(__traits(getLinkage, FooCppStruct) == "C++");
+static assert(__traits(getLinkage, FooCppInterface) == "C++");
+
+version (D_ObjectiveC)
+{
+ extern (Objective-C) interface FooObjC {}
+ static assert(__traits(getLinkage, FooObjC) == "Objective-C");
+}