+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.
/* 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.
-39edbe17e7b5c761d780c9d1d4376a06df7bf3d8
+ed71446aaa2bd0e548c3bf2154a638826dfe3db0
The first line of this file holds the git revision number of the last
merge done from the dlang/dmd repository.
"SysV4",
"Hurd",
"Android",
+ "PlayStation",
+ "PlayStation4",
"Cygwin",
"MinGW",
"FreeStanding",
"MIPS_EABI",
"MIPS_SoftFloat",
"MIPS_HardFloat",
+ "MSP430",
"NVPTX",
"NVPTX64",
+ "RISCV32",
+ "RISCV64",
"SPARC",
"SPARC_V8Plus",
"SPARC_SoftFloat",
"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",
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');
*/
Dsymbol *getInstance(Dsymbol *s)
{
- Dsymbol *p = s->toParent();
+ Dsymbol *p = s->toParent3();
if (p)
{
if (TemplateInstance *ti = p->isTemplateInstance())
*/
static Dsymbol *getQualifier(Dsymbol *s)
{
- Dsymbol *p = s->toParent();
+ Dsymbol *p = s->toParent3();
return (p && !p->isModule()) ? p : NULL;
}
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();
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())
se = p;
if (find(p->isTemplateInstance()->tempdecl) >= 0)
write_prefix = false;
- p = p->toParent();
+ p = p->toParent3();
}
if (p && !p->isModule())
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");
*/
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');
}
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
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
{
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
#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);
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;
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!(); }
*/
Dsymbol *Dsymbol::toParent()
{
- return parent ? parent->pastMixin() : NULL;
+ return parent ? parent->pastMixinAndNspace() : NULL;
}
/// ditto
return s;
}
+/// ditto
+Dsymbol *Dsymbol::toParent3()
+{
+ return parent ? parent->pastMixin() : NULL;
+}
+
TemplateInstance *Dsymbol::isInstantiated()
{
for (Dsymbol *s = parent; s; s = s->parent)
Module *getModule();
Module *getAccessModule();
Dsymbol *pastMixin();
+ Dsymbol *pastMixinAndNspace();
Dsymbol *toParent();
Dsymbol *toParent2();
+ Dsymbol *toParent3();
TemplateInstance *isInstantiated();
TemplateInstance *isSpeculative();
Ungag ungagSpeculative();
/* 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)
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);
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)
a = new Dsymbols();
a->push(s);
}
- s = new Nspace(linkLoc, id, a);
+ s = new Nspace(linkLoc, id, a, cppMangleOnly);
}
delete idents;
pAttrs->link = LINKdefault;
* 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);
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();
check(TOKrparen);
*pidents = idents;
*pcppmangle = cppmangle;
+ *pcppMangleOnly = cppMangleOnly;
return 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");
StaticAssert *parseStaticAssert();
TypeQualified *parseTypeof();
Type *parseVector();
- LINK parseLinkage(Identifiers **, CPPMANGLE *);
+ LINK parseLinkage(Identifiers **, CPPMANGLE *, bool *);
Identifiers *parseQualifiedIdentifier(const char *entity);
Condition *parseDebugCondition();
Condition *parseVersionCondition();
--- /dev/null
+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));
--- /dev/null
+
+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;
+ }
+}
--- /dev/null
+/*
+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", )
+{
+}
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;
//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;
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;
// 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
// 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
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