From 350ee808a5a2d3c9dba5531d90486b58c38ed191 Mon Sep 17 00:00:00 2001 From: Geod24 Date: Tue, 31 Mar 2020 12:36:30 +0900 Subject: [PATCH] Fix issue 20700 - Fwd refs leads to extern(C++, class|struct) being ignored `Type`-derived AST nodes do not support the same kind of semantic analysis that `Dsymbol`-derived one do. The issue was that in some codes, semantic analysis on the type was performed before it was performed on the declaration, and chasing those cases turned out to be endless, hence the minor refactoring. --- src/dmd/aggregate.d | 4 ++++ src/dmd/aggregate.h | 1 + src/dmd/attrib.d | 7 +++++++ src/dmd/attrib.h | 1 + src/dmd/cppmanglewin.d | 14 +++++++++----- src/dmd/dsymbolsem.d | 2 ++ src/dmd/mtype.h | 1 - src/dmd/typesem.d | 24 ------------------------ test/compilable/cppmangle.d | 12 ++++++++++++ 9 files changed, 36 insertions(+), 30 deletions(-) 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`); +}