mirror of
https://github.com/dlang/dmd.git
synced 2025-04-28 14:10:11 +03:00
Fix Issue 15512 - Implement better C++ name mangling feature.
This commit is contained in:
parent
61fe641e9a
commit
d9747003d4
5 changed files with 94 additions and 14 deletions
|
@ -1159,11 +1159,14 @@ struct ASTBase
|
|||
|
||||
extern (C++) final class Nspace : ScopeDsymbol
|
||||
{
|
||||
extern (D) this(const ref Loc loc, Identifier ident, Dsymbols* members)
|
||||
bool ignoreCppSymbols;
|
||||
|
||||
extern (D) this(const ref Loc loc, Identifier ident, Dsymbols* members, bool ignoreCppSymbols)
|
||||
{
|
||||
super(ident);
|
||||
this.loc = loc;
|
||||
this.members = members;
|
||||
this.ignoreCppSymbols = ignoreCppSymbols;
|
||||
}
|
||||
|
||||
override void accept(Visitor v)
|
||||
|
|
|
@ -273,15 +273,22 @@ nothrow:
|
|||
*/
|
||||
static bool isValidIdentifier(const(char)* p)
|
||||
{
|
||||
size_t len;
|
||||
size_t idx;
|
||||
if (!p || !*p)
|
||||
goto Linvalid;
|
||||
return false;
|
||||
return isValidIdentifier(p[0 .. strlen(p)]);
|
||||
}
|
||||
|
||||
/**********************************
|
||||
* ditto
|
||||
*/
|
||||
extern (D) static bool isValidIdentifier(const(char)[] str)
|
||||
{
|
||||
const(char)* p = str.ptr;
|
||||
size_t len = str.length;
|
||||
size_t idx = 0;
|
||||
if (*p >= '0' && *p <= '9') // beware of isdigit() on signed chars
|
||||
goto Linvalid;
|
||||
len = strlen(p);
|
||||
idx = 0;
|
||||
while (p[idx])
|
||||
while (idx < len)
|
||||
{
|
||||
dchar dc;
|
||||
const q = utf_decodeChar(p, len, idx, dc);
|
||||
|
|
|
@ -30,22 +30,26 @@ private enum LOG = false;
|
|||
*/
|
||||
extern (C++) final class Nspace : ScopeDsymbol
|
||||
{
|
||||
extern (D) this(const ref Loc loc, Identifier ident, Dsymbols* members)
|
||||
bool ignoreCppSymbols;
|
||||
|
||||
extern (D) this(const ref Loc loc, Identifier ident, Dsymbols* members, bool ignoreCppSymbols)
|
||||
{
|
||||
super(ident);
|
||||
//printf("Nspace::Nspace(ident = %s)\n", ident.toChars());
|
||||
this.loc = loc;
|
||||
this.members = members;
|
||||
this.ignoreCppSymbols = ignoreCppSymbols;
|
||||
}
|
||||
|
||||
override Dsymbol syntaxCopy(Dsymbol s)
|
||||
{
|
||||
auto ns = new Nspace(loc, ident, null);
|
||||
auto ns = new Nspace(loc, ident, null, ignoreCppSymbols);
|
||||
return ScopeDsymbol.syntaxCopy(ns);
|
||||
}
|
||||
|
||||
override void addMember(Scope* sc, ScopeDsymbol sds)
|
||||
{
|
||||
if(!ignoreCppSymbols)
|
||||
ScopeDsymbol.addMember(sc, sds);
|
||||
if (members)
|
||||
{
|
||||
|
|
|
@ -870,7 +870,8 @@ final class Parser(AST) : Lexer
|
|||
const linkLoc = token.loc;
|
||||
AST.Identifiers* idents = null;
|
||||
CPPMANGLE cppmangle;
|
||||
const link = parseLinkage(&idents, cppmangle);
|
||||
bool ignoreCppSymbols = false;
|
||||
const link = parseLinkage(&idents, cppmangle, ignoreCppSymbols);
|
||||
if (pAttrs.link != LINK.default_)
|
||||
{
|
||||
if (pAttrs.link != link)
|
||||
|
@ -902,7 +903,7 @@ final class Parser(AST) : Lexer
|
|||
a = new AST.Dsymbols();
|
||||
a.push(s);
|
||||
}
|
||||
s = new AST.Nspace(linkLoc, id, a);
|
||||
s = new AST.Nspace(linkLoc, id, a, ignoreCppSymbols);
|
||||
}
|
||||
pAttrs.link = LINK.default_;
|
||||
}
|
||||
|
@ -2117,10 +2118,13 @@ final class Parser(AST) : Lexer
|
|||
* Parse:
|
||||
* extern (linkage)
|
||||
* extern (C++, namespaces)
|
||||
* extern (C++, "namespace", "namespaces", ...)
|
||||
* The parser is on the 'extern' token.
|
||||
*/
|
||||
LINK parseLinkage(AST.Identifiers** pidents, out CPPMANGLE cppmangle)
|
||||
LINK parseLinkage(AST.Identifiers** pidents, out CPPMANGLE cppmangle, out bool ignoreCppSymbols)
|
||||
{
|
||||
import std.string : toStringz;
|
||||
|
||||
AST.Identifiers* idents = null;
|
||||
cppmangle = CPPMANGLE.def;
|
||||
LINK link = LINK.default_;
|
||||
|
@ -2152,6 +2156,42 @@ final class Parser(AST) : Lexer
|
|||
cppmangle = token.value == TOK.class_ ? CPPMANGLE.asClass : CPPMANGLE.asStruct;
|
||||
nextToken();
|
||||
}
|
||||
else if (token.value == TOK.string_) // extern(C++, "namespace", "namespaces")
|
||||
{
|
||||
ignoreCppSymbols = true;
|
||||
idents = new AST.Identifiers();
|
||||
|
||||
while(1)
|
||||
{
|
||||
AST.StringExp stringExp = cast(AST.StringExp)parsePrimaryExp();
|
||||
const(char)[] name = stringExp.toStringz();
|
||||
if(name.length == 0)
|
||||
{
|
||||
error("invalid zero length C++ namespace");
|
||||
idents = null;
|
||||
break;
|
||||
}
|
||||
else if(!Identifier.isValidIdentifier(name))
|
||||
{
|
||||
error("C++ namespace `%s` is invalid", name.ptr);
|
||||
idents = null;
|
||||
break;
|
||||
}
|
||||
idents.push(Identifier.idPool(name));
|
||||
if(token.value == TOK.comma)
|
||||
{
|
||||
nextToken();
|
||||
if(token.value != TOK.string_)
|
||||
{
|
||||
error("string expected following `,` for C++ namespace");
|
||||
idents = null;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
idents = new AST.Identifiers();
|
||||
|
@ -4212,7 +4252,8 @@ final class Parser(AST) : Lexer
|
|||
sawLinkage = true;
|
||||
AST.Identifiers* idents = null;
|
||||
CPPMANGLE cppmangle;
|
||||
link = parseLinkage(&idents, cppmangle);
|
||||
bool ignoreCppSymbols = false;
|
||||
link = parseLinkage(&idents, cppmangle, ignoreCppSymbols);
|
||||
if (idents)
|
||||
{
|
||||
error("C++ name spaces not allowed here");
|
||||
|
|
25
test/compilable/cppmangle3.d
Normal file
25
test/compilable/cppmangle3.d
Normal file
|
@ -0,0 +1,25 @@
|
|||
|
||||
|
||||
extern(C++, "true")
|
||||
{
|
||||
}
|
||||
|
||||
extern(C++, "__traits")
|
||||
{
|
||||
}
|
||||
|
||||
extern(C++, "foo")
|
||||
{
|
||||
}
|
||||
|
||||
int foo; // no name clashing with above namespace
|
||||
|
||||
extern(C++, "std", "chrono")
|
||||
{
|
||||
void func();
|
||||
}
|
||||
|
||||
version(Windows) static assert(func.mangleof == "?func@chrono@std@@YAXXZ");
|
||||
else static assert(func.mangleof == "_ZNSt6chrono4funcEv");
|
||||
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue