Skip to content

Commit

Permalink
Merge pull request #8332 from Geod24/fix18922
Browse files Browse the repository at this point in the history
 Fix issue 18922: No substitutions for C++ namespaces in different module/file
merged-on-behalf-of: Razvan Nitu <RazvanN7@users.noreply.github.com>
  • Loading branch information
dlang-bot committed Jun 6, 2018
2 parents 4eb9160 + 9a1b446 commit 7518fac
Show file tree
Hide file tree
Showing 4 changed files with 117 additions and 51 deletions.
149 changes: 98 additions & 51 deletions src/dmd/cppmangle.d
Expand Up @@ -36,6 +36,7 @@ import dmd.globals;
import dmd.id;
import dmd.identifier;
import dmd.mtype;
import dmd.nspace;
import dmd.root.outbuffer;
import dmd.root.rootobject;
import dmd.target;
Expand Down Expand Up @@ -124,12 +125,24 @@ private final class CppMangleVisitor : Visitor

/******
* See if `p` exists in components[]
*
* Note that components can contain `null` entries,
* as the index used in mangling is based on the index in the array.
*
* If called with an object whose dynamic type is `Nspace`,
* calls the `find(Nspace)` overload.
*
* Returns:
* index if found, -1 if not
*/
int find(RootObject p)
{
//printf("find %p %d %s\n", p, p.dyncast(), p ? p.toChars() : null);

if (p.dyncast() == DYNCAST.dsymbol)
if (auto ns = (cast(Dsymbol)p).isNspace())
return find(ns);

foreach (i, component; components)
{
if (p == component)
Expand All @@ -138,6 +151,40 @@ private final class CppMangleVisitor : Visitor
return -1;
}

/**
* Overload which accepts a Namespace
*
* It is very common for large C++ projects to have multiple files sharing
* the same `namespace`. If any D project adopts the same approach
* (e.g. separating data structures from functions), it will lead to two
* `Nspace` objects being instantiated, with different addresses.
* At the same time, we cannot compare just any Dsymbol via identifier,
* because it messes with templates.
*
* See_Also:
* https://issues.dlang.org/show_bug.cgi?id=18922
*
* Params:
* ns = C++ namespace to do substitution for
*
* Returns:
* Index of the entry, if found, or `-1` otherwise
*/
int find(Nspace ns)
{
foreach (i, component; components)
{
if (ns == component)
return cast(int)i;

if (component && component.dyncast() == DYNCAST.dsymbol)
if (auto ons = (cast(Dsymbol)component).isNspace())
if (ns.equals(ons))
return cast(int)i;
}
return -1;
}

/*********************
* Append p to components[]
*/
Expand Down Expand Up @@ -400,70 +447,70 @@ private final class CppMangleVisitor : Visitor
void prefix_name(Dsymbol s)
{
//printf("prefix_name(%s)\n", s.toChars());
if (!substitute(s))
if (substitute(s))
return;

auto si = getInstance(s);
Dsymbol p = getQualifier(si);
if (p)
{
auto si = getInstance(s);
Dsymbol p = getQualifier(si);
if (p)
if (isStd(p))
{
if (isStd(p))
TemplateInstance ti = si.isTemplateInstance();
if (ti)
{
TemplateInstance ti = si.isTemplateInstance();
if (ti)
if (s.ident == Id.allocator)
{
if (s.ident == Id.allocator)
{
buf.writestring("Sa");
template_args(ti);
append(ti);
return;
}
if (s.ident == Id.basic_string)
buf.writestring("Sa");
template_args(ti);
append(ti);
return;
}
if (s.ident == Id.basic_string)
{
// ::std::basic_string<char, ::std::char_traits<char>, ::std::allocator<char>>
if (ti.tiargs.dim == 3 &&
isChar((*ti.tiargs)[0]) &&
isChar_traits_char((*ti.tiargs)[1]) &&
isAllocator_char((*ti.tiargs)[2]))

{
// ::std::basic_string<char, ::std::char_traits<char>, ::std::allocator<char>>
if (ti.tiargs.dim == 3 &&
isChar((*ti.tiargs)[0]) &&
isChar_traits_char((*ti.tiargs)[1]) &&
isAllocator_char((*ti.tiargs)[2]))

{
buf.writestring("Ss");
return;
}
buf.writestring("Sb"); // ::std::basic_string
template_args(ti);
append(ti);
buf.writestring("Ss");
return;
}
buf.writestring("Sb"); // ::std::basic_string
template_args(ti);
append(ti);
return;
}

// ::std::basic_istream<char, ::std::char_traits<char>>
if (s.ident == Id.basic_istream &&
char_std_char_traits_char(ti, "Si"))
return;
// ::std::basic_istream<char, ::std::char_traits<char>>
if (s.ident == Id.basic_istream &&
char_std_char_traits_char(ti, "Si"))
return;

// ::std::basic_ostream<char, ::std::char_traits<char>>
if (s.ident == Id.basic_ostream &&
char_std_char_traits_char(ti, "So"))
return;
// ::std::basic_ostream<char, ::std::char_traits<char>>
if (s.ident == Id.basic_ostream &&
char_std_char_traits_char(ti, "So"))
return;

// ::std::basic_iostream<char, ::std::char_traits<char>>
if (s.ident == Id.basic_iostream &&
char_std_char_traits_char(ti, "Sd"))
return;
}
buf.writestring("St");
// ::std::basic_iostream<char, ::std::char_traits<char>>
if (s.ident == Id.basic_iostream &&
char_std_char_traits_char(ti, "Sd"))
return;
}
else
prefix_name(p);
buf.writestring("St");
}
source_name(si);
if (!isStd(si))
/* Do this after the source_name() call to keep components[]
* in the right order.
* https://issues.dlang.org/show_bug.cgi?id=17947
*/
append(si);
else
prefix_name(p);
}
source_name(si);
if (!isStd(si))
/* Do this after the source_name() call to keep components[]
* in the right order.
* https://issues.dlang.org/show_bug.cgi?id=17947
*/
append(si);
}


Expand Down
2 changes: 2 additions & 0 deletions src/dmd/dsymbol.d
Expand Up @@ -243,6 +243,8 @@ extern (C++) class Dsymbol : RootObject
{
if (this == o)
return true;
if (o.dyncast() != DYNCAST.dsymbol)
return false;
Dsymbol s = cast(Dsymbol)o;
// Overload sets don't have an ident
if (s && ident && s.ident && ident.equals(s.ident))
Expand Down
11 changes: 11 additions & 0 deletions test/compilable/cppmangle.d
Expand Up @@ -689,3 +689,14 @@ version (Win64)
static assert(TestOperators.opIndex.mangleof == "??ATestOperators@@QEAAH_K@Z");
static assert(TestOperators.opCall.mangleof == "??RTestOperators@@QEAAHHM@Z");
}

extern(C++, Namespace18922)
{
import cppmangle2;
void func18922(Struct18922) {}

version (Posix)
static assert(func18922.mangleof == "_ZN14Namespace189229func18922ENS_11Struct18922E");
else version(Windows)
static assert(func18922.mangleof == "?func18922@Namespace18922@@YAXUStruct18922@1@@Z");
}
6 changes: 6 additions & 0 deletions test/compilable/cppmangle2.d
@@ -0,0 +1,6 @@
module cppmangle2;

extern(C++, Namespace18922)
{
struct Struct18922 { int i; }
}

0 comments on commit 7518fac

Please sign in to comment.