From c533ad157cfabb09a503074c4453b5a7d27920db 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 On the long run, it looks like we should just move the setScope to AttribDeclaration, but this is a simple bugfix to target stable. --- src/dmd/attrib.d | 7 +++++++ src/dmd/attrib.h | 1 + src/dmd/typesem.d | 13 ++++++++----- test/compilable/cppmangle.d | 13 +++++++++++++ 4 files changed, 29 insertions(+), 5 deletions(-) diff --git a/src/dmd/attrib.d b/src/dmd/attrib.d index 7035ec3eba03..9c5978e8d059 100644 --- a/src/dmd/attrib.d +++ b/src/dmd/attrib.d @@ -435,6 +435,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 40fa3940d5ad..f7e87b6105cd 100644 --- a/src/dmd/attrib.h +++ b/src/dmd/attrib.h @@ -88,6 +88,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/typesem.d b/src/dmd/typesem.d index 98ee6c440693..714c74931abd 100644 --- a/src/dmd/typesem.d +++ b/src/dmd/typesem.d @@ -1810,13 +1810,16 @@ extern(C++) Type typeSemantic(Type t, const ref Loc loc, Scope* sc) Type visitStruct(TypeStruct mtype) { //printf("TypeStruct::semantic('%s')\n", mtype.toChars()); + // If this is called via a forward reference, + // use the dsymbol's scope so that `extern(C++ class|struct)` applies + // https://issues.dlang.org/show_bug.cgi?id=20700 + auto cppmangle = (mtype.sym && mtype.sym._scope) ? + mtype.sym._scope.cppmangle : sc.cppmangle; + if (mtype.deco) { - if (sc && sc.cppmangle != CPPMANGLE.def) - { - if (mtype.cppmangle == CPPMANGLE.def) - mtype.cppmangle = sc.cppmangle; - } + assert(cppmangle == CPPMANGLE.def || + cppmangle == mtype.cppmangle); return mtype; } diff --git a/test/compilable/cppmangle.d b/test/compilable/cppmangle.d index 1a84059a56e8..c2ce610cc920 100644 --- a/test/compilable/cppmangle.d +++ b/test/compilable/cppmangle.d @@ -1251,3 +1251,16 @@ extern(C++, `bar`) { void func19542(T)(); } + +// https://issues.dlang.org/show_bug.cgi?id=20700 +version (Windows) +extern(C++) +{ + void test20700_1(const ref Struct20700); + extern(C++, class) struct Struct20700 {} + void test20700_2(const ref Struct20700); + + // Note: Needs to be `BV` (`class`), not `BU` (`struct`) + static assert(test20700_1.mangleof == `?test20700_1@@YAXABVStruct20700@@@Z`); + static assert(test20700_2.mangleof == `?test20700_2@@YAXABVStruct20700@@@Z`); +}