diff --git a/src/dmd/aggregate.d b/src/dmd/aggregate.d index f1e6c631675f..622e92324fe8 100644 --- a/src/dmd/aggregate.d +++ b/src/dmd/aggregate.d @@ -85,6 +85,10 @@ extern (C++) abstract class AggregateDeclaration : ScopeDsymbol /// specifies whether this is a D, C++, Objective-C or anonymous struct/class/interface ClassKind classKind; + /// Specify whether to mangle the aggregate as a `class` or a `struct` + /// This information is used by the MSVC mangler + /// Only valid for class and struct. TODO: Merge with ClassKind ? + CPPMANGLE cppmangle; /* !=null if is nested * pointing to the dsymbol that directly enclosing it. diff --git a/src/dmd/aggregate.h b/src/dmd/aggregate.h index fc450a8a214f..717b53f69765 100644 --- a/src/dmd/aggregate.h +++ b/src/dmd/aggregate.h @@ -84,6 +84,7 @@ class AggregateDeclaration : public ScopeDsymbol Dsymbol *deferred; // any deferred semantic2() or semantic3() symbol ClassKind::Type classKind; // specifies the linkage type + CPPMANGLE cppmangle; /* !=NULL if is nested * pointing to the dsymbol that directly enclosing it. diff --git a/src/dmd/attrib.d b/src/dmd/attrib.d index a7deb81d2c63..80ceef53283b 100644 --- a/src/dmd/attrib.d +++ b/src/dmd/attrib.d @@ -442,6 +442,13 @@ extern (C++) final class CPPMangleDeclaration : AttribDeclaration sc.aligndecl, sc.inlining); } + override void setScope(Scope* sc) + { + if (decl) + Dsymbol.setScope(sc); // for forward reference + return AttribDeclaration.setScope(sc); + } + override const(char)* toChars() const { return toString().ptr; diff --git a/src/dmd/attrib.h b/src/dmd/attrib.h index b0367b4c6953..2795db270b1e 100644 --- a/src/dmd/attrib.h +++ b/src/dmd/attrib.h @@ -87,6 +87,7 @@ class CPPMangleDeclaration : public AttribDeclaration Dsymbol *syntaxCopy(Dsymbol *s); Scope *newScope(Scope *sc); + void setScope(Scope *sc); const char *toChars() const; void accept(Visitor *v) { v->visit(this); } }; diff --git a/src/dmd/cppmanglewin.d b/src/dmd/cppmanglewin.d index 863f827aa2e6..918367488264 100644 --- a/src/dmd/cppmanglewin.d +++ b/src/dmd/cppmanglewin.d @@ -16,8 +16,10 @@ import core.stdc.stdio; import dmd.arraytypes; import dmd.cppmangle : isPrimaryDtor, isCppOperator, CppOperator; +import dmd.dclass; import dmd.declaration; import dmd.denum : isSpecialEnumIdent; +import dmd.dstruct; import dmd.dsymbol; import dmd.dtemplate; import dmd.errors; @@ -385,11 +387,12 @@ public: return; //printf("visit(TypeStruct); is_not_top_type = %d\n", (int)(flags & IS_NOT_TOP_TYPE)); mangleModifier(type); - if (type.sym.isUnionDeclaration()) + auto agg = cast(StructDeclaration) type.sym; + if (agg.isUnionDeclaration()) buf.writeByte('T'); else - buf.writeByte(type.cppmangle == CPPMANGLE.asClass ? 'V' : 'U'); - mangleIdent(type.sym); + buf.writeByte(agg.cppmangle == CPPMANGLE.asClass ? 'V' : 'U'); + mangleIdent(agg); flags &= ~IS_NOT_TOP_TYPE; flags &= ~IGNORE_CONST; } @@ -456,8 +459,9 @@ public: buf.writeByte('E'); flags |= IS_NOT_TOP_TYPE; mangleModifier(type); - buf.writeByte(type.cppmangle == CPPMANGLE.asStruct ? 'U' : 'V'); - mangleIdent(type.sym); + auto cldecl = cast(ClassDeclaration) type.sym; + buf.writeByte(cldecl.cppmangle == CPPMANGLE.asStruct ? 'U' : 'V'); + mangleIdent(cldecl); flags &= ~IS_NOT_TOP_TYPE; flags &= ~IGNORE_CONST; } diff --git a/src/dmd/dsymbolsem.d b/src/dmd/dsymbolsem.d index e25090cb2b44..dd79f34dc047 100644 --- a/src/dmd/dsymbolsem.d +++ b/src/dmd/dsymbolsem.d @@ -4639,6 +4639,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor if (sc.linkage == LINK.cpp) sd.classKind = ClassKind.cpp; sd.cppnamespace = sc.namespace; + sd.cppmangle = sc.cppmangle; } else if (sd.symtab && !scx) return; @@ -4857,6 +4858,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor if (sc.linkage == LINK.cpp) cldec.classKind = ClassKind.cpp; cldec.cppnamespace = sc.namespace; + cldec.cppmangle = sc.cppmangle; if (sc.linkage == LINK.objc) objc.setObjc(cldec); } diff --git a/src/dmd/mtype.h b/src/dmd/mtype.h index a79a62126a1f..c05483dcaf7d 100644 --- a/src/dmd/mtype.h +++ b/src/dmd/mtype.h @@ -725,7 +725,6 @@ class TypeStruct : public Type public: StructDeclaration *sym; AliasThisRec att; - CPPMANGLE cppmangle; static TypeStruct *create(StructDeclaration *sym); const char *kind(); diff --git a/src/dmd/typesem.d b/src/dmd/typesem.d index 5baf7ee39cad..4b7238b10445 100644 --- a/src/dmd/typesem.d +++ b/src/dmd/typesem.d @@ -1812,14 +1812,7 @@ extern(C++) Type typeSemantic(Type t, Loc loc, Scope* sc) { //printf("TypeStruct::semantic('%s')\n", mtype.toChars()); if (mtype.deco) - { - if (sc && sc.cppmangle != CPPMANGLE.def) - { - if (mtype.cppmangle == CPPMANGLE.def) - mtype.cppmangle = sc.cppmangle; - } return mtype; - } /* Don't semantic for sym because it should be deferred until * sizeof needed or its members accessed. @@ -1830,11 +1823,6 @@ extern(C++) Type typeSemantic(Type t, Loc loc, Scope* sc) if (mtype.sym.type.ty == Terror) return error(); - if (sc && sc.cppmangle != CPPMANGLE.def) - mtype.cppmangle = sc.cppmangle; - else - mtype.cppmangle = CPPMANGLE.asStruct; - return merge(mtype); } @@ -1848,14 +1836,7 @@ extern(C++) Type typeSemantic(Type t, Loc loc, Scope* sc) { //printf("TypeClass::semantic(%s)\n", mtype.toChars()); if (mtype.deco) - { - if (sc && sc.cppmangle != CPPMANGLE.def) - { - if (mtype.cppmangle == CPPMANGLE.def) - mtype.cppmangle = sc.cppmangle; - } return mtype; - } /* Don't semantic for sym because it should be deferred until * sizeof needed or its members accessed. @@ -1866,11 +1847,6 @@ extern(C++) Type typeSemantic(Type t, Loc loc, Scope* sc) if (mtype.sym.type.ty == Terror) return error(); - if (sc && sc.cppmangle != CPPMANGLE.def) - mtype.cppmangle = sc.cppmangle; - else - mtype.cppmangle = CPPMANGLE.asClass; - return merge(mtype); } diff --git a/test/compilable/cppmangle.d b/test/compilable/cppmangle.d index 50102e66f74e..739ca5cbad66 100644 --- a/test/compilable/cppmangle.d +++ b/test/compilable/cppmangle.d @@ -1251,3 +1251,15 @@ extern(C++, `bar`) { void func19542(T)(); } + +// https://issues.dlang.org/show_bug.cgi?id=20700 +version (Windows) extern(C++) +{ + void test20700_1(Struct20700); + extern(C++, class) struct Struct20700 {} + void test20700_2(Struct20700); + + // Note: Needs to be `BV` (`class`), not `BU` (`struct`) + static assert(test20700_1.mangleof == `?test20700_1@@YAXVStruct20700@@@Z`); + static assert(test20700_2.mangleof == `?test20700_2@@YAXVStruct20700@@@Z`); +}