Skip to content

Commit

Permalink
Fix issue 20700 - Fwd refs leads to extern(C++, class|struct) being i…
Browse files Browse the repository at this point in the history
…gnored

`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.
  • Loading branch information
Geod24 committed Apr 3, 2020
1 parent 6026443 commit 350ee80
Show file tree
Hide file tree
Showing 9 changed files with 36 additions and 30 deletions.
4 changes: 4 additions & 0 deletions src/dmd/aggregate.d
Expand Up @@ -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.
Expand Down
1 change: 1 addition & 0 deletions src/dmd/aggregate.h
Expand Up @@ -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.
Expand Down
7 changes: 7 additions & 0 deletions src/dmd/attrib.d
Expand Up @@ -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;
Expand Down
1 change: 1 addition & 0 deletions src/dmd/attrib.h
Expand Up @@ -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); }
};
Expand Down
14 changes: 9 additions & 5 deletions src/dmd/cppmanglewin.d
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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;
}
Expand Down
2 changes: 2 additions & 0 deletions src/dmd/dsymbolsem.d
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
}
Expand Down
1 change: 0 additions & 1 deletion src/dmd/mtype.h
Expand Up @@ -725,7 +725,6 @@ class TypeStruct : public Type
public:
StructDeclaration *sym;
AliasThisRec att;
CPPMANGLE cppmangle;

static TypeStruct *create(StructDeclaration *sym);
const char *kind();
Expand Down
24 changes: 0 additions & 24 deletions src/dmd/typesem.d
Expand Up @@ -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.
Expand All @@ -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);
}

Expand All @@ -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.
Expand All @@ -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);
}

Expand Down
12 changes: 12 additions & 0 deletions test/compilable/cppmangle.d
Expand Up @@ -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`);
}

0 comments on commit 350ee80

Please sign in to comment.