d/dmd: Merge dmd upstream ed71446aa

Backports support for extern(C++, "namespace"), which makes the
core.stdcpp package compilable.

Added predefined condition for CppRuntime_Gcc unconditionally, as it is
unlikely that D code will be linking to anything other than libstdc++
when extern(C++) is used.

Reviewed-on: https://github.com/dlang/dmd/pull/9371

gcc/d/ChangeLog:

2019-03-01  Iain Buclaw  <ibuclaw@gdcproject.org>

	* d-builtins.cc (d_init_versions): Add CppRuntime_Gcc as predefined
	version condition.

From-SVN: r269304
This commit is contained in:
Iain Buclaw 2019-03-01 10:21:54 +00:00 committed by Iain Buclaw
parent c6b363486f
commit 9503d7b1ff
16 changed files with 229 additions and 24 deletions

View File

@ -1,3 +1,8 @@
2019-03-01 Iain Buclaw <ibuclaw@gdcproject.org>
* d-builtins.cc (d_init_versions): Add CppRuntime_Gcc as predefined
version condition.
2019-02-14 Maya Rashish <coypu@sdf.org>
* d-system.h: NetBSD is POSIX.

View File

@ -452,6 +452,8 @@ d_init_versions (void)
/* Emit all target-specific version identifiers. */
targetdm.d_cpu_versions ();
targetdm.d_os_versions ();
VersionCondition::addPredefinedGlobalIdent ("CppRuntime_Gcc");
}
/* A helper for d_build_builtins_module. Return a new ALIAS for TYPE.

View File

@ -1,4 +1,4 @@
39edbe17e7b5c761d780c9d1d4376a06df7bf3d8
ed71446aaa2bd0e548c3bf2154a638826dfe3db0
The first line of this file holds the git revision number of the last
merge done from the dlang/dmd repository.

View File

@ -171,6 +171,8 @@ static bool isReserved(const char *ident)
"SysV4",
"Hurd",
"Android",
"PlayStation",
"PlayStation4",
"Cygwin",
"MinGW",
"FreeStanding",
@ -197,8 +199,11 @@ static bool isReserved(const char *ident)
"MIPS_EABI",
"MIPS_SoftFloat",
"MIPS_HardFloat",
"MSP430",
"NVPTX",
"NVPTX64",
"RISCV32",
"RISCV64",
"SPARC",
"SPARC_V8Plus",
"SPARC_SoftFloat",
@ -219,6 +224,13 @@ static bool isReserved(const char *ident)
"CRuntime_Digitalmars",
"CRuntime_Glibc",
"CRuntime_Microsoft",
"CRuntime_Musl",
"CRuntime_UClibc",
"CppRuntime_Clang",
"CppRuntime_DigitalMars",
"CppRuntime_Gcc",
"CppRuntime_Microsoft",
"CppRuntime_Sun",
"D_Coverage",
"D_Ddoc",
"D_InlineAsm_X86",

View File

@ -196,8 +196,8 @@ class CppMangleVisitor : public Visitor
Expression *e = isExpression(o);
if (d && d->isFuncDeclaration())
{
bool is_nested = d->toParent() &&
!d->toParent()->isModule() &&
bool is_nested = d->toParent3() &&
!d->toParent3()->isModule() &&
((TypeFunction*)d->isFuncDeclaration()->type)->linkage == LINKcpp;
if (is_nested)
buf->writeByte('X');
@ -271,7 +271,7 @@ class CppMangleVisitor : public Visitor
*/
Dsymbol *getInstance(Dsymbol *s)
{
Dsymbol *p = s->toParent();
Dsymbol *p = s->toParent3();
if (p)
{
if (TemplateInstance *ti = p->isTemplateInstance())
@ -292,7 +292,7 @@ class CppMangleVisitor : public Visitor
*/
static Dsymbol *getQualifier(Dsymbol *s)
{
Dsymbol *p = s->toParent();
Dsymbol *p = s->toParent3();
return (p && !p->isModule()) ? p : NULL;
}
@ -324,7 +324,7 @@ class CppMangleVisitor : public Visitor
Dsymbol *s = ((TypeStruct*)t)->toDsymbol(NULL);
if (s->ident != ident)
return false;
Dsymbol *p = s->toParent();
Dsymbol *p = s->toParent3();
if (!p)
return false;
TemplateInstance *ti = p->isTemplateInstance();
@ -427,7 +427,7 @@ class CppMangleVisitor : public Visitor
void cpp_mangle_name(Dsymbol *s, bool qualified)
{
//printf("cpp_mangle_name(%s, %d)\n", s->toChars(), qualified);
Dsymbol *p = s->toParent();
Dsymbol *p = s->toParent3();
Dsymbol *se = s;
bool write_prefix = true;
if (p && p->isTemplateInstance())
@ -435,7 +435,7 @@ class CppMangleVisitor : public Visitor
se = p;
if (find(p->isTemplateInstance()->tempdecl) >= 0)
write_prefix = false;
p = p->toParent();
p = p->toParent3();
}
if (p && !p->isModule())
@ -521,7 +521,7 @@ class CppMangleVisitor : public Visitor
fatal();
}
Dsymbol *p = d->toParent();
Dsymbol *p = d->toParent3();
if (p && !p->isModule()) //for example: char Namespace1::beta[6] should be mangled as "_ZN10Namespace14betaE"
{
buf->writestring("_ZN");
@ -561,7 +561,7 @@ class CppMangleVisitor : public Visitor
*/
TemplateInstance *ti = d->parent->isTemplateInstance();
assert(ti);
Dsymbol *p = ti->toParent();
Dsymbol *p = ti->toParent3();
if (p && !p->isModule() && tf->linkage == LINKcpp)
{
buf->writeByte('N');
@ -581,7 +581,7 @@ class CppMangleVisitor : public Visitor
}
else
{
Dsymbol *p = d->toParent();
Dsymbol *p = d->toParent3();
if (p && !p->isModule() && tf->linkage == LINKcpp)
{
/* <nested-name> ::= N [<CV-qualifiers>] <prefix> <unqualified-name> E
@ -997,7 +997,7 @@ public:
else
{
Dsymbol *s = t->toDsymbol(NULL);
Dsymbol *p = s->toParent();
Dsymbol *p = s->toParent3();
if (p && p->isTemplateInstance())
{
/* https://issues.dlang.org/show_bug.cgi?id=17947
@ -1044,7 +1044,7 @@ public:
{
Dsymbol *s = t->toDsymbol(NULL);
Dsymbol *p = s->toParent();
Dsymbol *p = s->toParent3();
if (p && p->isTemplateInstance())
{
/* https://issues.dlang.org/show_bug.cgi?id=17947

View File

@ -30,6 +30,7 @@
#include "attrib.h"
#include "enum.h"
#include "lexer.h"
#include "nspace.h"
bool symbolIsVisible(Dsymbol *origin, Dsymbol *s);
typedef int (*ForeachDg)(void *ctx, size_t idx, Dsymbol *s);
@ -310,6 +311,14 @@ Dsymbol *Dsymbol::toAlias2()
return toAlias();
}
/**
* `pastMixin` returns the enclosing symbol if this is a template mixin.
*
* `pastMixinAndNspace` does likewise, additionally skipping over Nspaces that
* are mangleOnly.
*
* See also `parent`, `toParent`, `toParent2` and `toParent3`.
*/
Dsymbol *Dsymbol::pastMixin()
{
Dsymbol *s = this;
@ -320,16 +329,31 @@ Dsymbol *Dsymbol::pastMixin()
return s;
}
/// ditto
Dsymbol *Dsymbol::pastMixinAndNspace()
{
//printf("Dsymbol::pastMixinAndNspace() %s\n", toChars());
Nspace *ns = isNspace();
if (!(ns && ns->mangleOnly) && !isTemplateMixin() && !isForwardingAttribDeclaration())
return this;
if (!parent)
return NULL;
return parent->pastMixinAndNspace();
}
/**********************************
* `parent` field returns a lexically enclosing scope symbol this is a member of.
*
* `toParent()` returns a logically enclosing scope symbol this is a member of.
* It skips over TemplateMixin's.
* It skips over TemplateMixin's and Nspaces that are mangleOnly.
*
* `toParent2()` returns an enclosing scope symbol this is living at runtime.
* It skips over both TemplateInstance's and TemplateMixin's.
* It's used when looking for the 'this' pointer of the enclosing function/class.
*
* `toParent3()` returns a logically enclosing scope symbol this is a member of.
* It skips over TemplateMixin's.
*
* Examples:
* module mod;
* template Foo(alias a) { mixin Bar!(); }
@ -352,7 +376,7 @@ Dsymbol *Dsymbol::pastMixin()
*/
Dsymbol *Dsymbol::toParent()
{
return parent ? parent->pastMixin() : NULL;
return parent ? parent->pastMixinAndNspace() : NULL;
}
/// ditto
@ -364,6 +388,12 @@ Dsymbol *Dsymbol::toParent2()
return s;
}
/// ditto
Dsymbol *Dsymbol::toParent3()
{
return parent ? parent->pastMixin() : NULL;
}
TemplateInstance *Dsymbol::isInstantiated()
{
for (Dsymbol *s = parent; s; s = s->parent)

View File

@ -180,8 +180,10 @@ public:
Module *getModule();
Module *getAccessModule();
Dsymbol *pastMixin();
Dsymbol *pastMixinAndNspace();
Dsymbol *toParent();
Dsymbol *toParent2();
Dsymbol *toParent3();
TemplateInstance *isInstantiated();
TemplateInstance *isSpeculative();
Ungag ungagSpeculative();

View File

@ -17,23 +17,29 @@
/* This implements namespaces.
*/
Nspace::Nspace(Loc loc, Identifier *ident, Dsymbols *members)
Nspace::Nspace(Loc loc, Identifier *ident, Dsymbols *members, bool mangleOnly)
: ScopeDsymbol(ident)
{
//printf("Nspace::Nspace(ident = %s)\n", ident->toChars());
this->loc = loc;
this->members = members;
// Determines whether the symbol for this namespace should be included in
// the symbol table.
this->mangleOnly = mangleOnly;
}
Dsymbol *Nspace::syntaxCopy(Dsymbol *)
{
Nspace *ns = new Nspace(loc, ident, NULL);
Nspace *ns = new Nspace(loc, ident, NULL, mangleOnly);
return ScopeDsymbol::syntaxCopy(ns);
}
void Nspace::addMember(Scope *sc, ScopeDsymbol *sds)
{
ScopeDsymbol::addMember(sc, sds);
if (mangleOnly)
parent = sds;
else
ScopeDsymbol::addMember(sc, sds);
if (members)
{
if (!symtab)

View File

@ -19,7 +19,8 @@
class Nspace : public ScopeDsymbol
{
public:
Nspace(Loc loc, Identifier *ident, Dsymbols *members);
bool mangleOnly;
Nspace(Loc loc, Identifier *ident, Dsymbols *members, bool mangleOnly);
Dsymbol *syntaxCopy(Dsymbol *s);
void addMember(Scope *sc, ScopeDsymbol *sds);

View File

@ -676,7 +676,8 @@ Dsymbols *Parser::parseDeclDefs(int once, Dsymbol **pLastDecl, PrefixAttributes
Loc linkLoc = token.loc;
Identifiers *idents = NULL;
CPPMANGLE cppmangle = CPPMANGLEdefault;
LINK link = parseLinkage(&idents, &cppmangle);
bool cppMangleOnly = false;
LINK link = parseLinkage(&idents, &cppmangle, &cppMangleOnly);
if (pAttrs->link != LINKdefault)
{
if (pAttrs->link != link)
@ -709,7 +710,7 @@ Dsymbols *Parser::parseDeclDefs(int once, Dsymbol **pLastDecl, PrefixAttributes
a = new Dsymbols();
a->push(s);
}
s = new Nspace(linkLoc, id, a);
s = new Nspace(linkLoc, id, a, cppMangleOnly);
}
delete idents;
pAttrs->link = LINKdefault;
@ -1271,13 +1272,15 @@ Type *Parser::parseVector()
* Parse:
* extern (linkage)
* extern (C++, namespaces)
* extern (C++, "namespace", "namespaces", ...)
* The parser is on the 'extern' token.
*/
LINK Parser::parseLinkage(Identifiers **pidents, CPPMANGLE *pcppmangle)
LINK Parser::parseLinkage(Identifiers **pidents, CPPMANGLE *pcppmangle, bool *pcppMangleOnly)
{
Identifiers *idents = NULL;
CPPMANGLE cppmangle = CPPMANGLEdefault;
bool cppMangleOnly = false;
LINK link = LINKdefault;
nextToken();
assert(token.value == TOKlparen);
@ -1307,6 +1310,42 @@ LINK Parser::parseLinkage(Identifiers **pidents, CPPMANGLE *pcppmangle)
cppmangle = token.value == TOKclass ? CPPMANGLEclass : CPPMANGLEstruct;
nextToken();
}
else if (token.value == TOKstring) // extern(C++, "namespace", "namespaces")
{
cppMangleOnly = true;
idents = new Identifiers();
while (1)
{
StringExp *stringExp = (StringExp *)parsePrimaryExp();
const char *name = stringExp->toPtr();
if (stringExp->len == 0)
{
error("invalid zero length C++ namespace");
idents = NULL;
break;
}
else if (!Identifier::isValidIdentifier(name))
{
error("expected valid identifer for C++ namespace but got `%s`", name);
idents = NULL;
break;
}
idents->push(Identifier::idPool(name));
if (token.value == TOKcomma)
{
nextToken();
if (token.value != TOKstring)
{
error("string expected following `,` for C++ namespace, not `%s`", token.toChars());
idents = NULL;
break;
}
}
else
break;
}
}
else
{
idents = new Identifiers();
@ -1368,6 +1407,7 @@ LINK Parser::parseLinkage(Identifiers **pidents, CPPMANGLE *pcppmangle)
check(TOKrparen);
*pidents = idents;
*pcppmangle = cppmangle;
*pcppMangleOnly = cppMangleOnly;
return link;
}
@ -3604,7 +3644,8 @@ void Parser::parseStorageClasses(StorageClass &storage_class, LINK &link,
sawLinkage = true;
Identifiers *idents = NULL;
CPPMANGLE cppmangle = CPPMANGLEdefault;
link = parseLinkage(&idents, &cppmangle);
bool cppMangleOnly = false;
link = parseLinkage(&idents, &cppmangle, &cppMangleOnly);
if (idents)
{
error("C++ name spaces not allowed here");

View File

@ -88,7 +88,7 @@ public:
StaticAssert *parseStaticAssert();
TypeQualified *parseTypeof();
Type *parseVector();
LINK parseLinkage(Identifiers **, CPPMANGLE *);
LINK parseLinkage(Identifiers **, CPPMANGLE *, bool *);
Identifiers *parseQualifiedIdentifier(const char *entity);
Condition *parseDebugCondition();
Condition *parseVersionCondition();

View File

@ -0,0 +1,37 @@
module cppmangle3;
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");
struct Foo
{
extern(C++, "namespace")
{
static void bar();
}
}
alias Alias(alias a) = a;
alias Alias(T) = T;
static assert(is(Alias!(__traits(parent, bar)) == Foo));

View File

@ -0,0 +1,18 @@
static assert( Foo(10).bar.value == 10 );
extern(C++, "ns") {
struct Foo {
Bar!Foo bar;
this( int v ) {
bar.value = v;
}
}
}
extern(C++, "ns") {
struct Bar(T) {
int value;
}
}

View File

@ -0,0 +1,20 @@
/*
TEST_OUTPUT:
---
fail_compilation/cppmangle.d(10): Error: invalid zero length C++ namespace
fail_compilation/cppmangle.d(14): Error: expected valid identifer for C++ namespace but got `0num`
fail_compilation/cppmangle.d(18): Error: string expected following `,` for C++ namespace, not `)`
---
*/
extern(C++, "")
{
}
extern(C++, "0num")
{
}
extern(C++, "std", )
{
}

View File

@ -97,11 +97,17 @@ fail_compilation/reserved_version.d(196): Error: version identifier `D_Version2`
fail_compilation/reserved_version.d(197): Error: version identifier `D_NoBoundsChecks` is reserved and cannot be set
fail_compilation/reserved_version.d(200): Error: version identifier `all` is reserved and cannot be set
fail_compilation/reserved_version.d(201): Error: version identifier `none` is reserved and cannot be set
fail_compilation/reserved_version.d(202): Error: version identifier `CppRuntime_Clang` is reserved and cannot be set
fail_compilation/reserved_version.d(203): Error: version identifier `CppRuntime_DigitalMars` is reserved and cannot be set
fail_compilation/reserved_version.d(204): Error: version identifier `CppRuntime_Gcc` is reserved and cannot be set
fail_compilation/reserved_version.d(205): Error: version identifier `CppRuntime_Microsoft` is reserved and cannot be set
fail_compilation/reserved_version.d(206): Error: version identifier `CppRuntime_Sun` is reserved and cannot be set
---
*/
// Some extra empty lines to help fixup the manual line numbering after adding new version identifiers
#line 105
version = MSP430;
version = D_P16;
version = DigitalMars;
@ -199,6 +205,11 @@ version = D_NoBoundsChecks;
//version = assert;
version = all;
version = none;
version = CppRuntime_Clang;
version = CppRuntime_DigitalMars;
version = CppRuntime_Gcc;
version = CppRuntime_Microsoft;
version = CppRuntime_Sun;
// This should work though
debug = DigitalMars;
@ -278,6 +289,11 @@ debug = CRuntime_Glibc;
debug = CRuntime_Microsoft;
debug = CRuntime_Musl;
debug = CRuntime_UClibc;
debug = CppRuntime_Clang;
debug = CppRuntime_DigitalMars;
debug = CppRuntime_Gcc;
debug = CppRuntime_Microsoft;
debug = CppRuntime_Sun;
debug = D_Coverage;
debug = D_Ddoc;
debug = D_InlineAsm_X86;

View File

@ -77,6 +77,11 @@
// REQUIRED_ARGS: -version=CRuntime_Microsoft
// REQUIRED_ARGS: -version=CRuntime_Musl
// REQUIRED_ARGS: -version=CRuntime_UClibc
// REQUIRED_ARGS: -version=CppRuntime_Clang
// REQUIRED_ARGS: -version=CppRuntime_DigitalMars
// REQUIRED_ARGS: -version=CppRuntime_Gcc
// REQUIRED_ARGS: -version=CppRuntime_Microsoft
// REQUIRED_ARGS: -version=CppRuntime_Sun
// REQUIRED_ARGS: -version=D_Coverage
// REQUIRED_ARGS: -version=D_Ddoc
// REQUIRED_ARGS: -version=D_InlineAsm_X86
@ -168,6 +173,11 @@
// REQUIRED_ARGS: -debug=CRuntime_Microsoft
// REQUIRED_ARGS: -debug=CRuntime_Musl
// REQUIRED_ARGS: -debug=CRuntime_UClibc
// REQUIRED_ARGS: -debug=CppRuntime_Clang
// REQUIRED_ARGS: -debug=CppRuntime_DigitalMars
// REQUIRED_ARGS: -debug=CppRuntime_Gcc
// REQUIRED_ARGS: -debug=CppRuntime_Microsoft
// REQUIRED_ARGS: -debug=CppRuntime_Sun
// REQUIRED_ARGS: -debug=D_Coverage
// REQUIRED_ARGS: -debug=D_Ddoc
// REQUIRED_ARGS: -debug=D_InlineAsm_X86
@ -264,6 +274,11 @@ Error: version identifier `CRuntime_Glibc` is reserved and cannot be set
Error: version identifier `CRuntime_Microsoft` is reserved and cannot be set
Error: version identifier `CRuntime_Musl` is reserved and cannot be set
Error: version identifier `CRuntime_UClibc` is reserved and cannot be set
Error: version identifier `CppRuntime_Clang` is reserved and cannot be set
Error: version identifier `CppRuntime_DigitalMars` is reserved and cannot be set
Error: version identifier `CppRuntime_Gcc` is reserved and cannot be set
Error: version identifier `CppRuntime_Microsoft` is reserved and cannot be set
Error: version identifier `CppRuntime_Sun` is reserved and cannot be set
Error: version identifier `D_Coverage` is reserved and cannot be set
Error: version identifier `D_Ddoc` is reserved and cannot be set
Error: version identifier `D_InlineAsm_X86` is reserved and cannot be set