From 75f758a703924184fc07b01a138bb6f0028d077c Mon Sep 17 00:00:00 2001 From: Iain Buclaw Date: Wed, 29 Apr 2020 10:19:55 +0200 Subject: [PATCH] d: Merge bug fix from upstream dmd 06160ccae Adds classKind information to the front-end AST, which in turn allows us to fix code generation of type names for extern(C) and extern(C++) structs and classes. Inspecting such types inside a debugger now just works without the need to 'cast(module_name.cxx_type)'. gcc/d/ChangeLog: * d-codegen.cc (d_decl_context): Don't include module in the name of class and struct types that aren't extern(D). --- gcc/d/ChangeLog | 5 +++ gcc/d/d-codegen.cc | 4 ++- gcc/d/dmd/MERGE | 2 +- gcc/d/dmd/aggregate.h | 17 ++++++++-- gcc/d/dmd/dclass.c | 32 +++++++++---------- gcc/d/dmd/declaration.c | 2 +- gcc/d/dmd/dstruct.c | 4 +++ gcc/d/dmd/func.c | 4 +-- gcc/d/dmd/opover.c | 2 +- gcc/d/dmd/traits.c | 24 ++++++++++++-- gcc/testsuite/gdc.test/compilable/test17419.d | 18 +++++++++++ 11 files changed, 87 insertions(+), 27 deletions(-) diff --git a/gcc/d/ChangeLog b/gcc/d/ChangeLog index 3b5fc12a8fd..9550a6d581f 100644 --- a/gcc/d/ChangeLog +++ b/gcc/d/ChangeLog @@ -1,3 +1,8 @@ +2020-04-29 Iain Buclaw + + * 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 PR d/94777 diff --git a/gcc/d/d-codegen.cc b/gcc/d/d-codegen.cc index 12c6f138362..b4927a2de10 100644 --- a/gcc/d/d-codegen.cc +++ b/gcc/d/d-codegen.cc @@ -66,6 +66,7 @@ d_decl_context (Dsymbol *dsym) { Dsymbol *parent = dsym; Declaration *decl = dsym->isDeclaration (); + AggregateDeclaration *ad = dsym->isAggregateDeclaration (); while ((parent = parent->toParent2 ())) { @@ -74,7 +75,8 @@ d_decl_context (Dsymbol *dsym) 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); diff --git a/gcc/d/dmd/MERGE b/gcc/d/dmd/MERGE index f933cf1c992..a2699d39842 100644 --- a/gcc/d/dmd/MERGE +++ b/gcc/d/dmd/MERGE @@ -1,4 +1,4 @@ -f8a1a515346b16ebbd9da56a908540cbef1ee582 +06160ccaed7af7955d169024f417c43beb7a8f9f The first line of this file holds the git revision number of the last merge done from the dlang/dmd repository. diff --git a/gcc/d/dmd/aggregate.h b/gcc/d/dmd/aggregate.h index 881be58f2b8..da4a0398522 100644 --- a/gcc/d/dmd/aggregate.h +++ b/gcc/d/dmd/aggregate.h @@ -71,6 +71,19 @@ FuncDeclaration *buildDtor(AggregateDeclaration *ad, Scope *sc); 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: @@ -84,6 +97,8 @@ 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) @@ -274,8 +289,6 @@ public: 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 diff --git a/gcc/d/dmd/dclass.c b/gcc/d/dmd/dclass.c index 4609d6a9f54..a2009a604a5 100644 --- a/gcc/d/dmd/dclass.c +++ b/gcc/d/dmd/dclass.c @@ -240,12 +240,10 @@ ClassDeclaration::ClassDeclaration(Loc loc, Identifier *id, BaseClasses *basecla } com = false; - cpp = false; isscope = false; isabstract = ABSfwdref; inuse = 0; baseok = BASEOKnone; - isobjc = false; cpp_type_info_ptr_sym = NULL; } @@ -389,7 +387,7 @@ void ClassDeclaration::semantic(Scope *sc) userAttribDecl = sc->userAttribDecl; if (sc->linkage == LINKcpp) - cpp = true; + classKind = ClassKind::cpp; if (sc->linkage == LINKobjc) objc()->setObjc(this); } @@ -555,7 +553,7 @@ void ClassDeclaration::semantic(Scope *sc) 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); @@ -583,7 +581,7 @@ void ClassDeclaration::semantic(Scope *sc) if (baseClass->isCOMclass()) com = true; if (baseClass->isCPPclass()) - cpp = true; + classKind = ClassKind::cpp; if (baseClass->isscope) isscope = true; enclosing = baseClass->enclosing; @@ -600,7 +598,7 @@ void ClassDeclaration::semantic(Scope *sc) // 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()); @@ -675,7 +673,7 @@ Lancestorsdone: // 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()); } @@ -1087,7 +1085,7 @@ void ClassDeclaration::finalizeSize() 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()) @@ -1102,7 +1100,7 @@ void ClassDeclaration::finalizeSize() { alignsize = Target::ptrsize; structsize = Target::ptrsize; // allow room for __vptr - if (!cpp) + if (!isCPPclass()) structsize += Target::ptrsize; // allow room for __monitor } @@ -1299,7 +1297,7 @@ bool ClassDeclaration::isCOMinterface() const bool ClassDeclaration::isCPPclass() const { - return cpp; + return classKind == ClassKind::cpp; } bool ClassDeclaration::isCPPinterface() const @@ -1378,7 +1376,7 @@ bool ClassDeclaration::isAbstract() int ClassDeclaration::vtblOffset() const { - return cpp ? 0 : 1; + return classKind == ClassKind::cpp ? 0 : 1; } /**************************************** @@ -1405,7 +1403,7 @@ InterfaceDeclaration::InterfaceDeclaration(Loc loc, Identifier *id, BaseClasses 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 } } @@ -1422,9 +1420,9 @@ Scope *InterfaceDeclaration::newScope(Scope *sc) 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; } @@ -1523,7 +1521,7 @@ void InterfaceDeclaration::semantic(Scope *sc) } if (!baseclasses->dim && sc->linkage == LINKcpp) - cpp = true; + classKind = ClassKind::cpp; if (sc->linkage == LINKobjc) objc()->setObjc(this); @@ -1605,7 +1603,7 @@ void InterfaceDeclaration::semantic(Scope *sc) if (b->sym->isCOMinterface()) com = true; if (b->sym->isCPPinterface()) - cpp = true; + classKind = ClassKind::cpp; } interfaceSemantic(sc); @@ -1817,7 +1815,7 @@ bool InterfaceDeclaration::isCOMinterface() const bool InterfaceDeclaration::isCPPinterface() const { - return cpp; + return classKind == ClassKind::cpp; } /******************************************* diff --git a/gcc/d/dmd/declaration.c b/gcc/d/dmd/declaration.c index 806e29d6907..2ad6af2d410 100644 --- a/gcc/d/dmd/declaration.c +++ b/gcc/d/dmd/declaration.c @@ -2174,7 +2174,7 @@ Expression *VarDeclaration::callScopeDtor(Scope *) // 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; } diff --git a/gcc/d/dmd/dstruct.c b/gcc/d/dmd/dstruct.c index 10771c95a07..0a33cc23935 100644 --- a/gcc/d/dmd/dstruct.c +++ b/gcc/d/dmd/dstruct.c @@ -194,6 +194,7 @@ AggregateDeclaration::AggregateDeclaration(Loc loc, Identifier *id) sizeok = SIZEOKnone; // size not determined yet deferred = NULL; isdeprecated = false; + classKind = ClassKind::d; inv = NULL; aggNew = NULL; aggDelete = NULL; @@ -1071,6 +1072,9 @@ void StructDeclaration::semantic(Scope *sc) if (storage_class & STCabstract) error("structs, unions cannot be abstract"); userAttribDecl = sc->userAttribDecl; + + if (sc->linkage == LINKcpp) + classKind = ClassKind::cpp; } else if (symtab && !scx) { diff --git a/gcc/d/dmd/func.c b/gcc/d/dmd/func.c index ab74dc5328b..621405eef3e 100644 --- a/gcc/d/dmd/func.c +++ b/gcc/d/dmd/func.c @@ -876,7 +876,7 @@ void FuncDeclaration::semantic(Scope *sc) /* 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 @@ -902,7 +902,7 @@ void FuncDeclaration::semantic(Scope *sc) { //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; diff --git a/gcc/d/dmd/opover.c b/gcc/d/dmd/opover.c index b3ea6cf4671..e1ff5e9913b 100644 --- a/gcc/d/dmd/opover.c +++ b/gcc/d/dmd/opover.c @@ -962,7 +962,7 @@ Expression *op_overload(Expression *e, Scope *sc) ClassDeclaration *cd1 = t1->isClassHandle(); ClassDeclaration *cd2 = t2->isClassHandle(); - if (!(cd1->cpp || cd2->cpp)) + if (!(cd1->isCPPclass() || cd2->isCPPclass())) { /* Rewrite as: * .object.opEquals(e1, e2) diff --git a/gcc/d/dmd/traits.c b/gcc/d/dmd/traits.c index 04726c36473..535893feffb 100644 --- a/gcc/d/dmd/traits.c +++ b/gcc/d/dmd/traits.c @@ -1135,12 +1135,32 @@ Expression *semanticTraits(TraitsExp *e, Scope *sc) { 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(linkage)); diff --git a/gcc/testsuite/gdc.test/compilable/test17419.d b/gcc/testsuite/gdc.test/compilable/test17419.d index 219ed4f712e..d67c5b96d5a 100644 --- a/gcc/testsuite/gdc.test/compilable/test17419.d +++ b/gcc/testsuite/gdc.test/compilable/test17419.d @@ -35,3 +35,21 @@ void bar() 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"); +} -- 2.30.2