d: Merge upstream dmd 93108bb9e, druntime 6364e010, phobos 575b67a9b.

D front-end changes:

    - Import dmd v2.098.1-beta.1.
    - Default extern(C++) compatibility to C++17.

Druntime changes:

    - Import druntime v2.098.1-beta.1.
    - Fix definition of stat_t on MIPS64 (PR103604)

Phobos changes:

    - Import phobos v2.098.1-beta.1.

gcc/d/ChangeLog:

	* d-lang.cc (d_init_options): Set default -fextern-std= to C++17.
	* dmd/MERGE: Merge upstream dmd 93108bb9e.
	* gdc.texi (Runtime Options): Document the default for -fextern-std=.

libphobos/ChangeLog:

	PR d/103604
	* configure: Regenerate.
	* configure.ac (libtool_VERSION): Update to 3:0:0.
	* libdruntime/MERGE: Merge upstream druntime 6364e010.
	* src/MERGE: Merge upstream phobos 575b67a9b.
	* testsuite/libphobos.traits/all_satisfy.d: New test.
	* testsuite/libphobos.traits/traits.exp: New test.
This commit is contained in:
Iain Buclaw 2021-12-15 19:47:02 +01:00
parent 639ece7abf
commit fd43568cc5
68 changed files with 1660 additions and 673 deletions

View File

@ -297,8 +297,8 @@ d_init_options (unsigned int, cl_decoded_option *decoded_options)
global.params.argv0 = xstrdup (decoded_options[0].arg);
global.params.errorLimit = flag_max_errors;
/* Default extern(C++) mangling to C++14. */
global.params.cplusplus = CppStdRevisionCpp14;
/* Default extern(C++) mangling to C++17. */
global.params.cplusplus = CppStdRevisionCpp17;
/* Warnings and deprecations are disabled by default. */
global.params.useDeprecated = DIAGNOSTICinform;

View File

@ -1,4 +1,4 @@
3982604c54e8770585985a33577fbf19b9b5c9ce
93108bb9ea6216d67fa97bb4842fb59f26f6bfc7
The first line of this file holds the git revision number of the last
merge done from the dlang/dmd repository.

View File

@ -1 +1 @@
v2.098.0
v2.098.1-beta.1

View File

@ -1054,6 +1054,12 @@ UnionExp Cast(const ref Loc loc, Type type, Type to, Expression e1)
emplaceExp!(UnionExp)(&ue, ex);
return ue;
}
if (e1.type.toBasetype.equals(type) && type.equals(to))
{
emplaceExp!(UnionExp)(&ue, e1);
ue.exp().type = type;
return ue;
}
if (e1.type.implicitConvTo(to) >= MATCH.constant || to.implicitConvTo(e1.type) >= MATCH.constant)
{
goto L1;
@ -1087,7 +1093,19 @@ UnionExp Cast(const ref Loc loc, Type type, Type to, Expression e1)
}
else if (tb.ty == Tbool)
{
emplaceExp!(IntegerExp)(&ue, loc, e1.toInteger() != 0, type);
bool val = void;
const opt = e1.toBool();
if (opt.hasValue(true))
val = true;
else if (opt.hasValue(false))
val = false;
else
{
cantExp(ue);
return ue;
}
emplaceExp!(IntegerExp)(&ue, loc, val, type);
}
else if (type.isintegral())
{

View File

@ -975,12 +975,17 @@ final class CParser(AST) : Parser!AST
token.value == TOK.leftParenthesis &&
!isCastExpression(pt))
{
/* this might actually be a function
* call that looks like `(a)(b)` or even `(a)(b,c)`
/* (t)(...)... might be a cast expression or a function call,
* with different grammars: a cast would be cparseCastExp(),
* a function call would be cparsePostfixExp(CallExp(cparseArguments())).
* We can't know until t is known. So, parse it as a function call
* and let semantic() rewrite the AST as a CastExp if it turns out
* to be a type.
*/
auto ie = new AST.IdentifierExp(loc, t.isTypeIdentifier().ident);
ie.parens = true; // disambiguate it from being a declaration
return new AST.CallExp(loc, ie, cparseArguments());
ie.parens = true; // let semantic know it might be a CastExp
AST.Expression e = new AST.CallExp(loc, ie, cparseArguments());
return cparsePostfixOperators(e);
}
else
{
@ -1483,9 +1488,12 @@ final class CParser(AST) : Parser!AST
/* If a declarator does not follow, it is unnamed
*/
if (token.value == TOK.semicolon && tspec)
if (token.value == TOK.semicolon)
{
nextToken();
if (!tspec)
return; // accept empty declaration as an extension
auto tt = tspec.isTypeTag();
if (!tt ||
!tt.id && (tt.tok == TOK.struct_ || tt.tok == TOK.union_))
@ -1662,7 +1670,8 @@ final class CParser(AST) : Parser!AST
{
// Give non-extern variables an implicit void initializer
// if one has not been explicitly set.
if (!hasInitializer && !(specifier.scw & SCW.xextern))
if (!hasInitializer &&
!(specifier.scw & (SCW.xextern | SCW.xstatic | SCW.x_Thread_local) || level == LVL.global))
initializer = new AST.VoidInitializer(token.loc);
s = new AST.VarDeclaration(token.loc, dt, id, initializer, specifiersToSTC(level, specifier));
}
@ -2492,7 +2501,18 @@ final class CParser(AST) : Parser!AST
return t;
}
t = constApply(t);
if (declarator == DTR.xparameter &&
t.isTypePointer())
{
/* Because there are instances in .h files of "const pointer to mutable",
* skip applying transitive `const`
* https://issues.dlang.org/show_bug.cgi?id=22534
*/
auto tn = cast(AST.TypeNext)t;
tn.next = constApply(tn.next);
}
else
t = constApply(t);
}
//printf("result: %s\n", t.toChars());
@ -2610,6 +2630,8 @@ final class CParser(AST) : Parser!AST
Identifier id;
auto t = cparseDeclarator(DTR.xparameter, tspec, id, specifier);
if (token.value == TOK.__attribute__)
cparseGnuAttributes(specifier);
if (specifier.mod & MOD.xconst)
t = toConst(t);
auto param = new AST.Parameter(STC.parameter, t, id, null, null);

View File

@ -1574,7 +1574,7 @@ Expression ctfeIndex(UnionExp* pue, const ref Loc loc, Type type, Expression e1,
assert(0);
}
Expression ctfeCast(UnionExp* pue, const ref Loc loc, Type type, Type to, Expression e)
Expression ctfeCast(UnionExp* pue, const ref Loc loc, Type type, Type to, Expression e, bool explicitCast = false)
{
Expression paint()
{
@ -1587,9 +1587,12 @@ Expression ctfeCast(UnionExp* pue, const ref Loc loc, Type type, Type to, Expres
if (e.op == EXP.classReference)
{
// Disallow reinterpreting class casts. Do this by ensuring that
// the original class can implicitly convert to the target class
ClassDeclaration originalClass = (cast(ClassReferenceExp)e).originalClass();
if (originalClass.type.implicitConvTo(to.mutableOf()))
// the original class can implicitly convert to the target class.
// Also do not check 'alias this' for explicit cast expressions.
auto tclass = (cast(ClassReferenceExp)e).originalClass().type.isTypeClass();
auto match = explicitCast ? tclass.implicitConvToWithoutAliasThis(to.mutableOf())
: tclass.implicitConvTo(to.mutableOf());
if (match)
return paint();
else
{

View File

@ -6068,7 +6068,7 @@ public:
result = pue.exp();
return;
}
result = ctfeCast(pue, e.loc, e.type, e.to, e1);
result = ctfeCast(pue, e.loc, e.type, e.to, e1, true);
}
override void visit(AssertExp e)

View File

@ -462,6 +462,21 @@ extern (C++) class Dsymbol : ASTNode
return null;
}
/**************************************
* Does this Dsymbol come from a C file?
* Returns:
* true if it does
*/
final bool isCsymbol()
{
if (Module m = getModule())
{
if (m.isCFile)
return true;
}
return false;
}
/**********************************
* Determine which Module a Dsymbol is in, as far as access rights go.
*/
@ -1783,7 +1798,7 @@ extern (C++) final class WithScopeSymbol : ScopeDsymbol
// Acts as proxy to the with class declaration
Dsymbol s = null;
Expression eold = null;
for (Expression e = withstate.exp; e != eold; e = resolveAliasThis(_scope, e))
for (Expression e = withstate.exp; e && e != eold; e = resolveAliasThis(_scope, e, true))
{
if (e.op == EXP.scope_)
{
@ -2426,7 +2441,9 @@ Dsymbol handleSymbolRedeclarations(ref Scope sc, Dsymbol s, Dsymbol s2, ScopeDsy
auto vd2 = s2.isVarDeclaration(); // existing declaration
if (vd && vd2)
{
// if one is `static` and the other isn't
/* if one is `static` and the other isn't, the result is undefined
* behavior, C11 6.2.2.7
*/
if ((vd.storage_class ^ vd2.storage_class) & STC.static_)
return collision();
@ -2437,7 +2454,10 @@ Dsymbol handleSymbolRedeclarations(ref Scope sc, Dsymbol s, Dsymbol s2, ScopeDsy
return collision(); // can't both have initializers
if (i1)
return vd;
{
vd2._init = vd._init;
vd._init = null;
}
/* BUG: the types should match, which needs semantic() to be run on it
* extern int x;
@ -2454,15 +2474,38 @@ Dsymbol handleSymbolRedeclarations(ref Scope sc, Dsymbol s, Dsymbol s2, ScopeDsy
auto fd2 = s2.isFuncDeclaration(); // existing declaration
if (fd && fd2)
{
// if one is `static` and the other isn't
if ((fd.storage_class ^ fd2.storage_class) & STC.static_)
/* if one is `static` and the other isn't, the result is undefined
* behavior, C11 6.2.2.7
* However, match what gcc allows:
* static int sun1(); int sun1() { return 0; }
* and:
* static int sun2() { return 0; } int sun2();
* Both produce a static function.
*
* Both of these should fail:
* int sun3(); static int sun3() { return 0; }
* and:
* int sun4() { return 0; } static int sun4();
*/
// if adding `static`
if ( fd.storage_class & STC.static_ &&
!(fd2.storage_class & STC.static_))
{
return collision();
}
if (fd.fbody && fd2.fbody)
return collision(); // can't both have bodies
if (fd.fbody)
return fd;
{
fd2.fbody = fd.fbody; // transfer body to existing declaration
fd.fbody = null;
auto tf = fd.type.toTypeFunction();
auto tf2 = fd2.type.toTypeFunction();
tf2.parameterList = tf.parameterList; // transfer parameter list.
}
/* BUG: just like with VarDeclaration, the types should match, which needs semantic() to be run on it.
* FuncDeclaration::semantic2() can detect this, but it relies overnext being set.

View File

@ -199,6 +199,7 @@ public:
void deprecation(const char *format, ...);
bool checkDeprecated(const Loc &loc, Scope *sc);
Module *getModule();
bool isCsymbol();
Module *getAccessModule();
Dsymbol *pastMixin();
Dsymbol *toParent();

View File

@ -46,6 +46,7 @@ import dmd.func;
import dmd.globals;
import dmd.id;
import dmd.identifier;
import dmd.importc;
import dmd.init;
import dmd.initsem;
import dmd.hdrgen;
@ -891,6 +892,10 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
bool isBlit = false;
d_uns64 sz;
if (sc.flags & SCOPE.Cfile && !dsym._init)
{
addDefaultCInitializer(dsym);
}
if (!dsym._init &&
!(dsym.storage_class & (STC.static_ | STC.gshared | STC.extern_)) &&
fd &&
@ -900,7 +905,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
{
// Provide a default initializer
//printf("Providing default initializer for '%s'\n", toChars());
//printf("Providing default initializer for '%s'\n", dsym.toChars());
if (sz == SIZE_INVALID && dsym.type.ty != Terror)
dsym.error("size of type `%s` is invalid", dsym.type.toChars());

View File

@ -5529,6 +5529,20 @@ extern (C++) final class TemplateValueParameter : TemplateParameter
override bool declareParameter(Scope* sc)
{
/*
Do type semantic earlier.
This means for certain erroneous value parameters
their "type" can be known earlier and thus a better
error message given.
For example:
`template test(x* x) {}`
now yields "undefined identifier" rather than the opaque
"variable `x` is used as a type".
*/
if (valType)
valType = valType.typeSemantic(loc, sc);
auto v = new VarDeclaration(loc, valType, ident, null);
v.storage_class = STC.templateparameter;
return sc.insert(v) !is null;

View File

@ -3985,7 +3985,7 @@ extern (C++) final class FuncExp : Expression
}
else
{
assert(tok == TOK.function_ || tok == TOK.reserved && type.ty == Tpointer);
assert(tok == TOK.function_ || tok == TOK.reserved && type.ty == Tpointer || fd.errors);
tx = tfx.pointerTo();
}
//printf("\ttx = %s, to = %s\n", tx.toChars(), to.toChars());

View File

@ -316,6 +316,9 @@ Expression resolveOpDollar(Scope* sc, ArrayExp ae, IntervalExp ie, Expression* p
ie.lwr = sem(ie.lwr);
ie.upr = sem(ie.upr);
if (ie.lwr.isErrorExp() || ie.upr.isErrorExp())
errors = true;
if (lengthVar != ae.lengthVar && sc.func)
{
// If $ was used, declare it now
@ -536,16 +539,16 @@ private Expression resolveUFCS(Scope* sc, CallExp ce)
ce.e1 = ey;
if (isDotOpDispatch(ey))
{
uint errors = global.startGagging();
e = ce.syntaxCopy().expressionSemantic(sc);
if (!global.endGagging(errors))
return e;
// even opDispatch and UFCS must have valid arguments,
// so now that we've seen indication of a problem,
// check them for issues.
Expressions* originalArguments = Expression.arraySyntaxCopy(ce.arguments);
uint errors = global.startGagging();
e = ce.expressionSemantic(sc);
if (!global.endGagging(errors))
return e;
if (arrayExpressionSemantic(originalArguments, sc))
return ErrorExp.get();
@ -2792,6 +2795,8 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
exp.error("undefined identifier `%s`, did you mean %s `%s`?", exp.ident.toChars(), s2.kind(), s2.toChars());
else if (const p = Scope.search_correct_C(exp.ident))
exp.error("undefined identifier `%s`, did you mean `%s`?", exp.ident.toChars(), p);
else if (exp.ident == Id.dollar)
exp.error("undefined identifier `$`");
else
exp.error("undefined identifier `%s`", exp.ident.toChars());
@ -4244,6 +4249,16 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
return;
}
}
if (sc.flags & SCOPE.Cfile)
{
/* See if need to rewrite the AST because of cast/call ambiguity
*/
if (auto e = castCallAmbiguity(exp, sc))
{
result = expressionSemantic(e, sc);
return;
}
}
if (Expression ex = resolveUFCS(sc, exp))
{
@ -4425,24 +4440,6 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
else if (exp.e1.op == EXP.type && (sc && sc.flags & SCOPE.Cfile))
{
const numArgs = exp.arguments ? exp.arguments.length : 0;
if (e1org.parens && numArgs >= 1)
{
/* Ambiguous cases arise from CParser where there is not enough
* information to determine if we have a function call or a cast.
* ( type-name ) ( identifier ) ;
* ( identifier ) ( identifier ) ;
* If exp.e1 is a type-name, then this is a cast.
*/
Expression arg;
foreach (a; (*exp.arguments)[])
{
arg = arg ? new CommaExp(a.loc, arg, a) : a;
}
auto t = exp.e1.isTypeExp().type;
auto e = new CastExp(exp.loc, arg, t);
result = e.expressionSemantic(sc);
return;
}
/* Ambiguous cases arise from CParser where there is not enough
* information to determine if we have a function call or declaration.
@ -6406,6 +6403,18 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
printf("DotIdExp::semantic(this = %p, '%s')\n", exp, exp.toChars());
//printf("e1.op = %d, '%s'\n", e1.op, Token::toChars(e1.op));
}
if (sc.flags & SCOPE.Cfile)
{
/* See if need to rewrite the AST because of cast/call ambiguity
*/
if (auto e = castCallAmbiguity(exp, sc))
{
result = expressionSemantic(e, sc);
return;
}
}
if (exp.arrow) // ImportC only
exp.e1 = exp.e1.expressionSemantic(sc).arrayFuncConv(sc);
@ -8059,6 +8068,17 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
}
assert(!exp.type);
if (sc.flags & SCOPE.Cfile)
{
/* See if need to rewrite the AST because of cast/call ambiguity
*/
if (auto e = castCallAmbiguity(exp, sc))
{
result = expressionSemantic(e, sc);
return;
}
}
result = exp.carraySemantic(sc); // C semantics
if (result)
return;
@ -8452,6 +8472,17 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
return;
}
if (sc.flags & SCOPE.Cfile)
{
/* See if need to rewrite the AST because of cast/call ambiguity
*/
if (auto e = castCallAmbiguity(exp, sc))
{
result = expressionSemantic(e, sc);
return;
}
}
if (Expression ex = binSemantic(exp, sc))
{
result = ex;
@ -13050,7 +13081,7 @@ private bool fit(StructDeclaration sd, const ref Loc loc, Scope* sc, Expressions
e = resolveProperties(sc, e);
if (i >= nfields)
{
if (i <= sd.fields.dim && e.op == EXP.null_)
if (i < sd.fields.dim && e.op == EXP.null_)
{
// CTFE sometimes creates null as hidden pointer; we'll allow this.
continue;

View File

@ -15,13 +15,18 @@ module dmd.importc;
import core.stdc.stdio;
import dmd.astenums;
import dmd.dcast;
import dmd.declaration;
import dmd.dscope;
import dmd.dsymbol;
import dmd.expression;
import dmd.expressionsem;
import dmd.identifier;
import dmd.init;
import dmd.mtype;
import dmd.tokens;
import dmd.typesem;
/**************************************
* C11 does not allow array or function parameters.
@ -84,7 +89,7 @@ Expression arrayFuncConv(Expression e, Scope* sc)
}
else if (t.isTypeFunction())
{
e = e.addressOf();
e = new AddrExp(e.loc, e);
}
else
return e;
@ -169,3 +174,89 @@ Expression carraySemantic(ArrayExp ae, Scope* sc)
auto ep = new PtrExp(ae.loc, new AddExp(ae.loc, e1, e2));
return ep.expressionSemantic(sc);
}
/******************************************
* Determine default initializer for const global symbol.
*/
void addDefaultCInitializer(VarDeclaration dsym)
{
//printf("addDefaultCInitializer() %s\n", dsym.toChars());
if (!(dsym.storage_class & (STC.static_ | STC.gshared)))
return;
if (dsym.storage_class & (STC.extern_ | STC.field | STC.in_ | STC.foreach_ | STC.parameter | STC.result))
return;
Type t = dsym.type;
if (t.isTypeSArray() && t.isTypeSArray().isIncomplete())
{
dsym._init = new VoidInitializer(dsym.loc);
return; // incomplete arrays will be diagnosed later
}
if (t.isMutable())
return;
auto e = dsym.type.defaultInit(dsym.loc, true);
dsym._init = new ExpInitializer(dsym.loc, e);
}
/********************************************
* Resolve cast/call grammar ambiguity.
* Params:
* e = expression that might be a cast, might be a call
* sc = context
* Returns:
* null means leave as is, !=null means rewritten AST
*/
Expression castCallAmbiguity(Expression e, Scope* sc)
{
Expression* pe = &e;
while (1)
{
// Walk down the postfix expressions till we find a CallExp or something else
switch ((*pe).op)
{
case EXP.dotIdentifier:
pe = &(*pe).isDotIdExp().e1;
continue;
case EXP.plusPlus:
case EXP.minusMinus:
pe = &(*pe).isPostExp().e1;
continue;
case EXP.array:
pe = &(*pe).isArrayExp().e1;
continue;
case EXP.call:
auto ce = (*pe).isCallExp();
if (ce.e1.parens)
{
ce.e1 = expressionSemantic(ce.e1, sc);
if (ce.e1.op == EXP.type)
{
const numArgs = ce.arguments ? ce.arguments.length : 0;
if (numArgs >= 1)
{
ce.e1.parens = false;
Expression arg;
foreach (a; (*ce.arguments)[])
{
arg = arg ? new CommaExp(a.loc, arg, a) : a;
}
auto t = ce.e1.isTypeExp().type;
*pe = arg;
return new CastExp(ce.loc, e, t);
}
}
}
return null;
default:
return null;
}
}
}

View File

@ -434,11 +434,22 @@ extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Typ
return i;
}
if (sc.flags & SCOPE.Cfile)
{
/* the interpreter turns (char*)"string" into &"string"[0] which then
* it cannot interpret. Resolve that case by doing optimize() first
*/
i.exp = i.exp.optimize(WANTvalue);
i.exp = i.exp.ctfeInterpret();
if (i.exp.isSymOffExp())
{
/* `static variable cannot be read at compile time`
* https://issues.dlang.org/show_bug.cgi?id=22513
* Maybe this would be better addressed in ctfeInterpret()?
*/
needInterpret = NeedInterpret.INITnointerpret;
}
}
if (needInterpret)
i.exp = i.exp.ctfeInterpret();
if (i.exp.op == EXP.voidExpression)
error(i.loc, "variables cannot be initialized with an expression of type `void`. Use `void` initialization instead.");
}

View File

@ -2073,6 +2073,7 @@ class Lexer
bool overflow = false;
bool anyBinaryDigitsNoSingleUS = false;
bool anyHexDigitsNoSingleUS = false;
char errorDigit = 0;
dchar c = *p;
if (c == '0')
{
@ -2093,8 +2094,7 @@ class Lexer
case '8':
case '9':
if (Ccompile)
error("octal digit expected, not `%c`", c);
errorDigit = cast(char) c;
base = 8;
break;
case 'x':
@ -2205,12 +2205,9 @@ class Lexer
// got a digit here, set any necessary flags, check for errors
anyHexDigitsNoSingleUS = true;
anyBinaryDigitsNoSingleUS = true;
if (!err && d >= base)
if (!errorDigit && d >= base)
{
error("%s digit expected, not `%c`", base == 2 ? "binary".ptr :
base == 8 ? "octal".ptr :
"decimal".ptr, c);
err = true;
errorDigit = cast(char) c;
}
// Avoid expensive overflow check if we aren't at risk of overflow
if (n <= 0x0FFF_FFFF_FFFF_FFFFUL)
@ -2224,6 +2221,13 @@ class Lexer
}
}
Ldone:
if (errorDigit)
{
error("%s digit expected, not `%c`", base == 2 ? "binary".ptr :
base == 8 ? "octal".ptr :
"decimal".ptr, errorDigit);
err = true;
}
if (overflow && !err)
{
error("integer overflow");

View File

@ -523,8 +523,14 @@ Expression op_overload(Expression e, Scope* sc, EXP* pop = null)
{
// Deal with $
result = resolveOpDollar(sc, ae, ie, &e0);
if (result.op == EXP.error)
{
if (!e0 && !search_function(ad, Id.dollar)) {
ae.loc.errorSupplemental("Aggregate declaration '%s' does not define 'opDollar'", ae.e1.toChars());
}
return;
}
/* Rewrite a[i..j] as:
* a.opSlice(i, j)
*/
@ -597,11 +603,13 @@ Expression op_overload(Expression e, Scope* sc, EXP* pop = null)
/* Rewrite op(e1) as:
* op(e1.aliasthis)
*/
Expression e1 = resolveAliasThis(sc, e.e1);
result = e.copy();
(cast(UnaExp)result).e1 = e1;
result = result.op_overload(sc);
return;
if (auto e1 = resolveAliasThis(sc, e.e1, true))
{
result = e.copy();
(cast(UnaExp)result).e1 = e1;
result = result.op_overload(sc);
return;
}
}
}
}

View File

@ -26,6 +26,7 @@ import dmd.expressionsem;
import dmd.globals;
import dmd.init;
import dmd.mtype;
import dmd.printast;
import dmd.root.ctfloat;
import dmd.sideeffect;
import dmd.tokens;
@ -270,6 +271,7 @@ package void setLengthVarIfKnown(VarDeclaration lengthVar, Type type)
*/
Expression Expression_optimize(Expression e, int result, bool keepLvalue)
{
//printf("Expression_optimize() %s\n", e.toChars());
Expression ret = e;
void error()
@ -459,6 +461,59 @@ Expression Expression_optimize(Expression e, int result, bool keepLvalue)
return;
}
}
if (e.e1.isDotVarExp())
{
/******************************
* Run down the left side of the a.b.c expression to determine the
* leftmost variable being addressed (`a`), and accumulate the offsets of the `.b` and `.c`.
* Params:
* e = the DotVarExp or VarExp
* var = set to the VarExp at the end, or null if doesn't end in VarExp
* offset = accumulation of all the .var offsets encountered
* Returns: true on error
*/
static bool getVarAndOffset(Expression e, ref VarDeclaration var, ref uint offset)
{
if (e.type.size() == SIZE_INVALID) // trigger computation of v.offset
return true;
if (auto dve = e.isDotVarExp())
{
auto v = dve.var.isVarDeclaration();
if (!v || !v.isField() || v.isBitFieldDeclaration())
return false;
if (getVarAndOffset(dve.e1, var, offset))
return true;
offset += v.offset;
}
else if (auto ve = e.isVarExp())
{
if (!ve.var.isReference() &&
!ve.var.isImportedSymbol() &&
ve.var.isDataseg() &&
ve.var.isCsymbol())
{
var = ve.var.isVarDeclaration();
}
}
return false;
}
uint offset;
VarDeclaration var;
if (getVarAndOffset(e.e1, var, offset))
{
ret = ErrorExp.get();
return;
}
if (var)
{
ret = new SymOffExp(e.loc, var, offset, false);
ret.type = e.type;
return;
}
}
if (auto ae = e.e1.isIndexExp())
{
// Convert &array[n] to &array+n

View File

@ -5758,7 +5758,26 @@ LagainStc:
nextToken();
}
else
check(TOK.semicolon, "statement");
{
/*
* https://issues.dlang.org/show_bug.cgi?id=22529
* Avoid empty declaration error in case of missing semicolon
* followed by another token and another semicolon. E.g.:
*
* foo()
* return;
*
* When the missing `;` error is emitted, token is sitting on return.
* If we simply use `check` to emit the error, the token is advanced
* to `;` and the empty statement error would follow. To avoid that,
* we check if the next token is a semicolon and simply output the error,
* otherwise we fall back on the old path (advancing the token).
*/
if (token.value != TOK.semicolon && peek(&token).value == TOK.semicolon)
error("found `%s` when expecting `;` following statement", token.toChars());
else
check(TOK.semicolon, "statement");
}
s = new AST.ExpStatement(loc, exp);
break;
}

View File

@ -82,6 +82,24 @@ extern (C++) final class PrintASTVisitor : Visitor
printf(".var: %s\n", e.var ? e.var.toChars() : "");
}
override void visit(SymOffExp e)
{
printIndent(indent);
printf("SymOff %s\n", e.type ? e.type.toChars() : "");
printIndent(indent + 2);
printf(".var: %s\n", e.var ? e.var.toChars() : "");
printIndent(indent + 2);
printf(".offset: %llx\n", e.offset);
}
override void visit(VarExp e)
{
printIndent(indent);
printf("Var %s\n", e.type ? e.type.toChars() : "");
printIndent(indent + 2);
printf(".var: %s\n", e.var ? e.var.toChars() : "");
}
override void visit(DsymbolExp e)
{
visit(cast(Expression)e);
@ -120,6 +138,15 @@ extern (C++) final class PrintASTVisitor : Visitor
printAST(e.e1, indent + 2);
}
override void visit(DotVarExp e)
{
printIndent(indent);
printf("DotVar %s\n", e.type ? e.type.toChars() : "");
printIndent(indent + 2);
printf(".var: %s\n", e.var.toChars());
printAST(e.e1, indent + 2);
}
override void visit(BinExp e)
{
visit(cast(Expression)e);

View File

@ -235,6 +235,18 @@ private extern(C++) final class Semantic3Visitor : Visitor
if (funcdecl.errors || isError(funcdecl.parent))
{
funcdecl.errors = true;
// Mark that the return type could not be inferred
if (funcdecl.inferRetType)
{
assert(funcdecl.type);
auto tf = funcdecl.type.isTypeFunction();
// Only change the return type s.t. other analysis is
// still possible e.g. missmatched parameter types
if (tf && !tf.next)
tf.next = Type.terror;
}
return;
}
//printf("FuncDeclaration::semantic3('%s.%s', %p, sc = %p, loc = %s)\n", funcdecl.parent.toChars(), funcdecl.toChars(), funcdecl, sc, funcdecl.loc.toChars());

View File

@ -2471,64 +2471,69 @@ private extern (C++) final class StatementSemanticVisitor : Visitor
{
Expression initialExp = cs.exp;
cs.exp = cs.exp.implicitCastTo(sc, sw.condition.type);
cs.exp = cs.exp.optimize(WANTvalue | WANTexpand);
Expression e = cs.exp;
// Remove all the casts the user and/or implicitCastTo may introduce
// otherwise we'd sometimes fail the check below.
while (e.op == EXP.cast_)
e = (cast(CastExp)e).e1;
/* This is where variables are allowed as case expressions.
*/
if (e.op == EXP.variable)
// The switch'ed value has errors and doesn't provide the actual type
// Don't touch the case to not replace it with an `ErrorExp` even if it is valid
if (sw.condition.type && !sw.condition.type.isTypeError())
{
VarExp ve = cast(VarExp)e;
VarDeclaration v = ve.var.isVarDeclaration();
Type t = cs.exp.type.toBasetype();
if (v && (t.isintegral() || t.ty == Tclass))
cs.exp = cs.exp.implicitCastTo(sc, sw.condition.type);
cs.exp = cs.exp.optimize(WANTvalue | WANTexpand);
Expression e = cs.exp;
// Remove all the casts the user and/or implicitCastTo may introduce
// otherwise we'd sometimes fail the check below.
while (e.op == EXP.cast_)
e = (cast(CastExp)e).e1;
/* This is where variables are allowed as case expressions.
*/
if (e.op == EXP.variable)
{
/* Flag that we need to do special code generation
* for this, i.e. generate a sequence of if-then-else
*/
sw.hasVars = 1;
/* TODO check if v can be uninitialized at that point.
*/
if (!v.isConst() && !v.isImmutable())
VarExp ve = cast(VarExp)e;
VarDeclaration v = ve.var.isVarDeclaration();
Type t = cs.exp.type.toBasetype();
if (v && (t.isintegral() || t.ty == Tclass))
{
cs.error("`case` variables have to be `const` or `immutable`");
}
/* Flag that we need to do special code generation
* for this, i.e. generate a sequence of if-then-else
*/
sw.hasVars = 1;
if (sw.isFinal)
{
cs.error("`case` variables not allowed in `final switch` statements");
errors = true;
}
/* Find the outermost scope `scx` that set `sw`.
* Then search scope `scx` for a declaration of `v`.
*/
for (Scope* scx = sc; scx; scx = scx.enclosing)
{
if (scx.enclosing && scx.enclosing.sw == sw)
continue;
assert(scx.sw == sw);
if (!scx.search(cs.exp.loc, v.ident, null))
/* TODO check if v can be uninitialized at that point.
*/
if (!v.isConst() && !v.isImmutable())
{
cs.error("`case` variable `%s` declared at %s cannot be declared in `switch` body",
v.toChars(), v.loc.toChars());
cs.error("`case` variables have to be `const` or `immutable`");
}
if (sw.isFinal)
{
cs.error("`case` variables not allowed in `final switch` statements");
errors = true;
}
break;
/* Find the outermost scope `scx` that set `sw`.
* Then search scope `scx` for a declaration of `v`.
*/
for (Scope* scx = sc; scx; scx = scx.enclosing)
{
if (scx.enclosing && scx.enclosing.sw == sw)
continue;
assert(scx.sw == sw);
if (!scx.search(cs.exp.loc, v.ident, null))
{
cs.error("`case` variable `%s` declared at %s cannot be declared in `switch` body",
v.toChars(), v.loc.toChars());
errors = true;
}
break;
}
goto L1;
}
goto L1;
}
else
cs.exp = cs.exp.ctfeInterpret();
}
else
cs.exp = cs.exp.ctfeInterpret();
if (StringExp se = cs.exp.toStringExp())
cs.exp = se;
@ -2539,6 +2544,8 @@ private extern (C++) final class StatementSemanticVisitor : Visitor
}
L1:
// // Don't check other cases if this has errors
if (!cs.exp.isErrorExp())
foreach (cs2; *sw.cases)
{
//printf("comparing '%s' with '%s'\n", exp.toChars(), cs.exp.toChars());
@ -2877,9 +2884,6 @@ private extern (C++) final class StatementSemanticVisitor : Visitor
if (rs.exp.op == EXP.call)
rs.exp = valueNoDtor(rs.exp);
if (e0)
e0 = e0.optimize(WANTvalue);
/* Void-return function can have void / noreturn typed expression
* on return statement.
*/
@ -2904,7 +2908,10 @@ private extern (C++) final class StatementSemanticVisitor : Visitor
rs.exp = null;
}
if (e0)
{
e0 = e0.optimize(WANTvalue);
e0 = checkGC(sc, e0);
}
}
if (rs.exp)

View File

@ -323,7 +323,7 @@ struct TargetC
/// https://docs.microsoft.com/en-us/cpp/cpp/cpp-bit-fields?view=msvc-160
Gcc_Clang, /// gcc and clang
}
bool crtDestructorsSupported = true; /// Not all platforms support crt_destructor
ubyte longsize; /// size of a C `long` or `unsigned long` type
ubyte long_doublesize; /// size of a C `long double`
ubyte wchar_tsize; /// size of a C `wchar_t` type

View File

@ -70,6 +70,7 @@ struct TargetC
Gcc_Clang, // gcc and clang
};
uint8_t crtDestructorsSupported; // Not all platforms support crt_destructor
uint8_t longsize; // size of a C 'long' or 'unsigned long' type
uint8_t long_doublesize; // size of a C 'long double'
uint8_t wchar_tsize; // size of a C 'wchar_t' type

View File

@ -52,38 +52,22 @@ enum TOK : ushort
new_,
delete_,
star,
symbolOffset,
variable,
dotVariable,
dotIdentifier,
dotTemplateInstance,
dotType,
slice,
arrayLength,
version_,
module_,
dollar,
template_,
dotTemplateDeclaration,
declaration,
typeof_,
pragma_,
dSymbol,
typeid_,
uadd,
remove,
newAnonymousClass,
comment,
arrayLiteral,
assocArrayLiteral,
structLiteral,
classReference,
thrownException,
delegatePointer,
delegateFunctionPointer,
// Operators
lessThan = 54,
lessThan,
greaterThan,
lessOrEqual,
greaterOrEqual,
@ -94,7 +78,7 @@ enum TOK : ushort
index,
is_,
leftShift = 64,
leftShift,
rightShift,
leftShiftAssign,
rightShiftAssign,
@ -136,7 +120,7 @@ enum TOK : ushort
preMinusMinus,
// Numeric literals
int32Literal = 104,
int32Literal,
uns32Literal,
int64Literal,
uns64Literal,
@ -150,22 +134,21 @@ enum TOK : ushort
imaginary80Literal,
// Char constants
charLiteral = 116,
charLiteral,
wcharLiteral,
dcharLiteral,
// Leaf operators
identifier = 119,
identifier,
string_,
hexadecimalString,
this_,
super_,
halt,
tuple,
error,
// Basic types
void_ = 127,
void_,
int8,
uns8,
int16,
@ -191,7 +174,7 @@ enum TOK : ushort
bool_,
// Aggregates
struct_ = 151,
struct_,
class_,
interface_,
union_,
@ -223,7 +206,7 @@ enum TOK : ushort
immutable_,
// Statements
if_ = 181,
if_,
else_,
while_,
for_,
@ -249,7 +232,7 @@ enum TOK : ushort
onScopeSuccess,
// Contracts
invariant_ = 205,
invariant_,
// Testing
unittest_,
@ -259,7 +242,7 @@ enum TOK : ushort
ref_,
macro_,
parameters = 210,
parameters,
traits,
overloadSet,
pure_,
@ -279,18 +262,9 @@ enum TOK : ushort
vector,
pound,
interval = 229,
voidExpression,
cantExpression,
showCtfeContext,
objcClassReference,
vectorArray,
arrow, // ->
colonColon, // ::
wchar_tLiteral,
compoundLiteral, // ( type-name ) { initializer-list }
// C only keywords
inline,
@ -885,33 +859,17 @@ extern (C++) struct Token
// For debugging
TOK.error: "error",
TOK.dotIdentifier: "dotid",
TOK.dotTemplateDeclaration: "dottd",
TOK.dotTemplateInstance: "dotti",
TOK.dotVariable: "dotvar",
TOK.dotType: "dottype",
TOK.symbolOffset: "symoff",
TOK.arrayLength: "arraylength",
TOK.arrayLiteral: "arrayliteral",
TOK.assocArrayLiteral: "assocarrayliteral",
TOK.structLiteral: "structliteral",
TOK.string_: "string",
TOK.dSymbol: "symbol",
TOK.tuple: "tuple",
TOK.declaration: "declaration",
TOK.onScopeExit: "scope(exit)",
TOK.onScopeSuccess: "scope(success)",
TOK.onScopeFailure: "scope(failure)",
TOK.delegatePointer: "delegateptr",
// Finish up
TOK.reserved: "reserved",
TOK.remove: "remove",
TOK.newAnonymousClass: "newanonclass",
TOK.comment: "comment",
TOK.classReference: "classreference",
TOK.thrownException: "thrownexception",
TOK.delegateFunctionPointer: "delegatefuncptr",
TOK.int32Literal: "int32v",
TOK.uns32Literal: "uns32v",
TOK.int64Literal: "int64v",
@ -928,19 +886,9 @@ extern (C++) struct Token
TOK.wcharLiteral: "wcharv",
TOK.dcharLiteral: "dcharv",
TOK.wchar_tLiteral: "wchar_tv",
TOK.compoundLiteral: "compoundliteral",
TOK.halt: "halt",
TOK.hexadecimalString: "xstring",
TOK.interval: "interval",
TOK.voidExpression: "voidexp",
TOK.cantExpression: "cantexp",
TOK.showCtfeContext : "showCtfeContext",
TOK.objcClassReference: "class",
TOK.vectorArray: "vectorarray",
// C only keywords
TOK.inline : "inline",
TOK.register : "register",

View File

@ -61,35 +61,19 @@ enum class TOK : unsigned short
new_,
delete_,
star,
symbolOffset,
variable,
dotVariable,
dotIdentifier,
dotTemplateInstance,
dotType,
slice,
arrayLength,
version_,
module_,
dollar,
template_,
dotTemplateDeclaration,
declaration,
typeof_,
pragma_,
dSymbol,
typeid_,
uadd,
remove,
newAnonymousClass,
comment,
arrayLiteral,
assocArrayLiteral,
structLiteral,
classReference,
thrownException,
delegatePointer,
delegateFunctionPointer,
// Operators
lessThan, // 54
@ -169,7 +153,6 @@ enum class TOK : unsigned short
hexadecimalString,
this_,
super_,
halt,
tuple,
error,
@ -288,18 +271,9 @@ enum class TOK : unsigned short
vector,
pound,
interval, // 229
voidExpression,
cantExpression,
showCtfeContext,
objcClassReference,
vectorArray,
arrow, // ->
colonColon, // ::
wchar_tLiteral,
compoundLiteral, // ( type-name ) { initializer-list }
// C only keywords
inline_,

View File

@ -1709,13 +1709,22 @@ extern(C++) Type typeSemantic(Type type, const ref Loc loc, Scope* sc)
}
else if (e.op == EXP.variable) // special case: variable is used as a type
{
/*
N.B. This branch currently triggers for the following code
template test(x* x)
{
}
i.e. the compiler prints "variable x is used as a type"
which isn't a particularly good error message (x is a variable?).
*/
Dsymbol varDecl = mtype.toDsymbol(sc);
const(Loc) varDeclLoc = varDecl.getLoc();
Module varDeclModule = varDecl.getModule();
Module varDeclModule = varDecl.getModule(); //This can be null
.error(loc, "variable `%s` is used as a type", mtype.toChars());
if (varDeclModule != sc._module) // variable is imported
//Check for null to avoid https://issues.dlang.org/show_bug.cgi?id=22574
if ((varDeclModule !is null) && varDeclModule != sc._module) // variable is imported
{
const(Loc) varDeclModuleImportLoc = varDeclModule.getLoc();
.errorSupplemental(
@ -4630,11 +4639,12 @@ Expression dotExp(Type mt, Scope* sc, Expression e, Identifier ident, int flag)
* Params:
* mt = the type for which the init expression is returned
* loc = the location where the expression needs to be evaluated
* isCfile = default initializers are different with C
*
* Returns:
* The initialization expression for the type.
*/
extern (C++) Expression defaultInit(Type mt, const ref Loc loc)
extern (C++) Expression defaultInit(Type mt, const ref Loc loc, const bool isCfile = false)
{
Expression visitBasic(TypeBasic mt)
{
@ -4647,12 +4657,12 @@ extern (C++) Expression defaultInit(Type mt, const ref Loc loc)
switch (mt.ty)
{
case Tchar:
value = 0xFF;
value = isCfile ? 0 : 0xFF;
break;
case Twchar:
case Tdchar:
value = 0xFFFF;
value = isCfile ? 0 : 0xFFFF;
break;
case Timaginary32:
@ -4661,14 +4671,15 @@ extern (C++) Expression defaultInit(Type mt, const ref Loc loc)
case Tfloat32:
case Tfloat64:
case Tfloat80:
return new RealExp(loc, target.RealProperties.nan, mt);
return new RealExp(loc, isCfile ? CTFloat.zero : target.RealProperties.nan, mt);
case Tcomplex32:
case Tcomplex64:
case Tcomplex80:
{
// Can't use fvalue + I*fvalue (the im part becomes a quiet NaN).
const cvalue = complex_t(target.RealProperties.nan, target.RealProperties.nan);
const cvalue = isCfile ? complex_t(CTFloat.zero, CTFloat.zero)
: complex_t(target.RealProperties.nan, target.RealProperties.nan);
return new ComplexExp(loc, cvalue, mt);
}
@ -4686,7 +4697,7 @@ extern (C++) Expression defaultInit(Type mt, const ref Loc loc)
{
//printf("TypeVector::defaultInit()\n");
assert(mt.basetype.ty == Tsarray);
Expression e = mt.basetype.defaultInit(loc);
Expression e = mt.basetype.defaultInit(loc, isCfile);
auto ve = new VectorExp(loc, e, mt);
ve.type = mt;
ve.dim = cast(int)(mt.basetype.size(loc) / mt.elementType().size(loc));
@ -4700,9 +4711,9 @@ extern (C++) Expression defaultInit(Type mt, const ref Loc loc)
printf("TypeSArray::defaultInit() '%s'\n", mt.toChars());
}
if (mt.next.ty == Tvoid)
return mt.tuns8.defaultInit(loc);
return mt.tuns8.defaultInit(loc, isCfile);
else
return mt.next.defaultInit(loc);
return mt.next.defaultInit(loc, isCfile);
}
Expression visitFunction(TypeFunction mt)

View File

@ -267,15 +267,16 @@ Sets the C++ name mangling compatibility to the version identified by
@table @samp
@item c++98
@item c++03
Sets @code{__traits(getTargetInfo "cppStd")} to @code{199711}.
Sets @code{__traits(getTargetInfo, "cppStd")} to @code{199711}.
@item c++11
Sets @code{__traits(getTargetInfo "cppStd")} to @code{201103}.
Sets @code{__traits(getTargetInfo, "cppStd")} to @code{201103}.
@item c++14
Sets @code{__traits(getTargetInfo "cppStd")} to @code{201402}.
Sets @code{__traits(getTargetInfo, "cppStd")} to @code{201402}.
@item c++17
Sets @code{__traits(getTargetInfo "cppStd")} to @code{201703}.
Sets @code{__traits(getTargetInfo, "cppStd")} to @code{201703}.
This is the default.
@item c++20
Sets @code{__traits(getTargetInfo "cppStd")} to @code{202002}.
Sets @code{__traits(getTargetInfo, "cppStd")} to @code{202002}.
@end table
@item -fno-invariants

View File

@ -7,6 +7,12 @@
import core.stdc.stdio;
version (CppRuntime_Clang) version = CppMangle_Itanium;
version (CppRuntime_DigitalMars) version = CppMangle_MSVC;
version (CppRuntime_Gcc) version = CppMangle_Itanium;
version (CppRuntime_Microsoft) version = CppMangle_MSVC;
version (CppRuntime_Sun) version = CppMangle_Itanium;
extern (C++) int foob(int i, int j, int k);
class C
@ -45,23 +51,26 @@ void test1()
c.bar(4, 5, 6);
}
version (Posix)
version (CppMangle_Itanium)
{
static assert(foo.mangleof == "_Z3fooiii");
static assert(foob.mangleof == "_Z4foobiii");
static assert(C.bar.mangleof == "_ZN1C3barEiii");
}
version (Win32)
version (CppMangle_MSVC)
{
static assert(foo.mangleof == "?foo@@YAHHHH@Z");
static assert(foob.mangleof == "?foob@@YAHHHH@Z");
static assert(C.bar.mangleof == "?bar@C@@UAEHHHH@Z");
}
version (Win64)
{
static assert(foo.mangleof == "?foo@@YAHHHH@Z");
static assert(foob.mangleof == "?foob@@YAHHHH@Z");
static assert(C.bar.mangleof == "?bar@C@@UEAAHHHH@Z");
version (Win32)
{
static assert(foo.mangleof == "?foo@@YAHHHH@Z");
static assert(foob.mangleof == "?foob@@YAHHHH@Z");
static assert(C.bar.mangleof == "?bar@C@@UAEHHHH@Z");
}
version (Win64)
{
static assert(foo.mangleof == "?foo@@YAHHHH@Z");
static assert(foob.mangleof == "?foob@@YAHHHH@Z");
static assert(C.bar.mangleof == "?bar@C@@UEAAHHHH@Z");
}
}
/****************************************/
@ -81,7 +90,7 @@ void test2()
assert(i == 8);
}
version (Posix)
version (CppMangle_Itanium)
{
static assert (getD.mangleof == "_Z4getDv");
static assert (D.bar.mangleof == "_ZN1D3barEiii");
@ -118,7 +127,7 @@ void test3()
assert(i == 8);
}
version (Posix)
version (CppMangle_Itanium)
{
static assert (callE.mangleof == "_Z5callEP1E");
static assert (E.bar.mangleof == "_ZN1E3barEiii");
@ -134,7 +143,7 @@ void test4()
foo4(null);
}
version (Posix)
version (CppMangle_Itanium)
{
static assert(foo4.mangleof == "_Z4foo4Pc");
}
@ -160,7 +169,7 @@ void test5()
assert(f.p == cast(void*)b);
}
version (Posix)
version (CppMangle_Itanium)
{
static assert(bar5.getFoo.mangleof == "_ZN4bar56getFooEi");
static assert (newBar.mangleof == "_Z6newBarv");
@ -190,7 +199,7 @@ void test6()
assert(f.d == 2.5);
}
version (Posix)
version (CppMangle_Itanium)
{
static assert (foo6.mangleof == "_Z4foo6v");
}
@ -221,7 +230,7 @@ void test8()
foo8(&c);
}
version (Posix)
version (CppMangle_Itanium)
{
static assert(foo8.mangleof == "_Z4foo8PKc");
}
@ -239,7 +248,7 @@ void test9()
foobar9(a, a);
}
version (Posix)
version (CppMangle_Itanium)
{
static assert(foobar9.mangleof == "_Z7foobar9P5elem9S0_");
}
@ -298,7 +307,7 @@ extern (C++)
void test10058l(void* function(void*), void* function(const (void)*), const(void)* function(void*)) { }
}
version (Posix)
version (CppMangle_Itanium)
{
static assert(test10058a.mangleof == "_Z10test10058aPv");
static assert(test10058b.mangleof == "_Z10test10058bPFvPvE");
@ -329,7 +338,7 @@ class CallExp
static void test11696d(Loc, Expression*, Expression*);
}
version (Posix)
version (CppMangle_Itanium)
{
static assert(CallExp.test11696a.mangleof == "_ZN7CallExp10test11696aE3LocP10ExpressionS2_");
static assert(CallExp.test11696b.mangleof == "_ZN7CallExp10test11696bE3LocP10ExpressionPS2_");
@ -353,7 +362,7 @@ extern(C++, `N13337a`, `N13337b`, `N13337c`)
void foo13337_3(S13337_2 s);
}
version (Posix)
version (CppMangle_Itanium)
{
static assert(foo13337.mangleof == "_ZN7N13337a7N13337b7N13337c8foo13337ENS1_6S13337E");
static assert(foo13337_2.mangleof == "_ZN7N13337a7N13337b7N13337c10foo13337_2ENS1_6S13337E");
@ -383,7 +392,7 @@ extern(C++)
}
}
version (Posix)
version (CppMangle_Itanium)
{
static assert(Struct7030.foo.mangleof == "_ZNK10Struct70303fooEi");
static assert(Struct7030.bar.mangleof == "_ZN10Struct70303barEi");
@ -494,7 +503,7 @@ extern (C++)
void func_20413(pair!(int, float), pair!(float, int));
}
version (Posix)
version (CppMangle_Itanium)
{
// https://issues.dlang.org/show_bug.cgi?id=17947
static assert(std.pair!(void*, void*).swap.mangleof == "_ZNSt4pairIPvS0_E4swapERS1_");
@ -531,7 +540,7 @@ alias T36 = int ********** ********** ********** **********;
extern (C++) void test36(T36, T36*) { }
version (Posix)
version (CppMangle_Itanium)
{
static assert(test36.mangleof == "_Z6test36PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPiPS12_");
}
@ -545,7 +554,7 @@ int test37(T)(){ return 0;}
extern(C++, `SPACE`)
int test37(T)(){ return 0;}
version (Posix) // all non-Windows machines
version (CppMangle_Itanium) // all non-Windows machines
{
static assert(SPACE.test37!int.mangleof == "_ZN5SPACE6test37IiEEiv");
static assert(test37!int.mangleof == "_ZN5SPACE6test37IiEEiv");
@ -556,11 +565,11 @@ version (Posix) // all non-Windows machines
extern (C++) void test15388(typeof(null));
version (Posix)
version (CppMangle_Itanium)
{
static assert(test15388.mangleof == "_Z9test15388Dn");
}
version (Windows)
version (CppMangle_MSVC)
{
static assert(test15388.mangleof == "?test15388@@YAX$$T@Z");
}
@ -583,7 +592,7 @@ extern (C++) struct Test14086_S
~this();
}
version(Posix)
version (CppMangle_Itanium)
{
static assert(Test14086.__ctor.mangleof == "_ZN9Test14086C1Ev");
static assert(Test14086.__dtor.mangleof == "_ZN9Test14086D1Ev");
@ -591,21 +600,24 @@ version(Posix)
static assert(Test14086_S.__ctor.mangleof == "_ZN11Test14086_SC1Ei");
static assert(Test14086_S.__dtor.mangleof == "_ZN11Test14086_SD1Ev");
}
version(Win32)
version (CppMangle_MSVC)
{
static assert(Test14086.__ctor.mangleof == "??0Test14086@@QAE@XZ");
static assert(Test14086.__dtor.mangleof == "??1Test14086@@UAE@XZ");
static assert(Test14086_2.__dtor.mangleof == "??1Test14086_2@@QAE@XZ");
static assert(Test14086_S.__ctor.mangleof == "??0Test14086_S@@QAE@H@Z");
static assert(Test14086_S.__dtor.mangleof == "??1Test14086_S@@QAE@XZ");
}
version(Win64)
{
static assert(Test14086.__ctor.mangleof == "??0Test14086@@QEAA@XZ");
static assert(Test14086.__dtor.mangleof == "??1Test14086@@UEAA@XZ");
static assert(Test14086_2.__dtor.mangleof == "??1Test14086_2@@QEAA@XZ");
static assert(Test14086_S.__ctor.mangleof == "??0Test14086_S@@QEAA@H@Z");
static assert(Test14086_S.__dtor.mangleof == "??1Test14086_S@@QEAA@XZ");
version (Win32)
{
static assert(Test14086.__ctor.mangleof == "??0Test14086@@QAE@XZ");
static assert(Test14086.__dtor.mangleof == "??1Test14086@@UAE@XZ");
static assert(Test14086_2.__dtor.mangleof == "??1Test14086_2@@QAE@XZ");
static assert(Test14086_S.__ctor.mangleof == "??0Test14086_S@@QAE@H@Z");
static assert(Test14086_S.__dtor.mangleof == "??1Test14086_S@@QAE@XZ");
}
version (Win64)
{
static assert(Test14086.__ctor.mangleof == "??0Test14086@@QEAA@XZ");
static assert(Test14086.__dtor.mangleof == "??1Test14086@@UEAA@XZ");
static assert(Test14086_2.__dtor.mangleof == "??1Test14086_2@@QEAA@XZ");
static assert(Test14086_S.__ctor.mangleof == "??0Test14086_S@@QEAA@H@Z");
static assert(Test14086_S.__dtor.mangleof == "??1Test14086_S@@QEAA@XZ");
}
}
/**************************************/
@ -623,17 +635,20 @@ struct S18888(alias arg = T18888)
alias I = T18888!(arg!int);
}
version(Posix)
version (CppMangle_Itanium)
{
static assert(S18888!().I.fun.mangleof == "_ZN6T18888IS_IiEE3funEv");
}
version(Win32)
version (CppMangle_MSVC)
{
static assert(S18888!().I.fun.mangleof == "?fun@?$T18888@U?$T18888@H@@@@QAEXXZ");
}
version(Win64)
{
static assert(S18888!().I.fun.mangleof == "?fun@?$T18888@U?$T18888@H@@@@QEAAXXZ");
version (Win32)
{
static assert(S18888!().I.fun.mangleof == "?fun@?$T18888@U?$T18888@H@@@@QAEXXZ");
}
version (Win64)
{
static assert(S18888!().I.fun.mangleof == "?fun@?$T18888@U?$T18888@H@@@@QEAAXXZ");
}
}
/**************************************/
@ -653,26 +668,29 @@ extern (C++) class C18890_2
Agg s;
}
version (Posix)
version (CppMangle_Itanium)
{
static assert(C18890.__dtor.mangleof == "_ZN6C18890D1Ev");
static assert(C18890.__xdtor.mangleof == "_ZN6C18890D1Ev");
static assert(C18890_2.__dtor.mangleof == "_ZN8C18890_26__dtorEv");
static assert(C18890_2.__xdtor.mangleof == "_ZN8C18890_2D1Ev");
}
version (Win32)
version (CppMangle_MSVC)
{
static assert(C18890.__dtor.mangleof == "??1C18890@@UAE@XZ");
static assert(C18890.__xdtor.mangleof == "??_GC18890@@UAEPAXI@Z");
static assert(C18890_2.__dtor.mangleof == "?__dtor@C18890_2@@UAEXXZ");
static assert(C18890_2.__xdtor.mangleof == "??_GC18890_2@@UAEPAXI@Z");
}
version (Win64)
{
static assert(C18890.__dtor.mangleof == "??1C18890@@UEAA@XZ");
static assert(C18890.__xdtor.mangleof == "??_GC18890@@UEAAPEAXI@Z");
static assert(C18890_2.__dtor.mangleof == "?__dtor@C18890_2@@UEAAXXZ");
static assert(C18890_2.__xdtor.mangleof == "??_GC18890_2@@UEAAPEAXI@Z");
version (Win32)
{
static assert(C18890.__dtor.mangleof == "??1C18890@@UAE@XZ");
static assert(C18890.__xdtor.mangleof == "??_GC18890@@UAEPAXI@Z");
static assert(C18890_2.__dtor.mangleof == "?__dtor@C18890_2@@UAEXXZ");
static assert(C18890_2.__xdtor.mangleof == "??_GC18890_2@@UAEPAXI@Z");
}
version (Win64)
{
static assert(C18890.__dtor.mangleof == "??1C18890@@UEAA@XZ");
static assert(C18890.__xdtor.mangleof == "??_GC18890@@UEAAPEAXI@Z");
static assert(C18890_2.__dtor.mangleof == "?__dtor@C18890_2@@UEAAXXZ");
static assert(C18890_2.__xdtor.mangleof == "??_GC18890_2@@UEAAPEAXI@Z");
}
}
/**************************************/
@ -688,20 +706,23 @@ extern (C++) class C18891
Agg s;
}
version (Posix)
version (CppMangle_Itanium)
{
static assert(C18891.__dtor.mangleof == "_ZN6C18891D1Ev");
static assert(C18891.__xdtor.mangleof == "_ZN6C18891D1Ev");
}
version (Win32)
version (CppMangle_MSVC)
{
static assert(C18891.__dtor.mangleof == "??1C18891@@UAE@XZ");
static assert(C18891.__xdtor.mangleof == "??_GC18891@@UAEPAXI@Z");
}
version (Win64)
{
static assert(C18891.__dtor.mangleof == "??1C18891@@UEAA@XZ");
static assert(C18891.__xdtor.mangleof == "??_GC18891@@UEAAPEAXI@Z");
version (Win32)
{
static assert(C18891.__dtor.mangleof == "??1C18891@@UAE@XZ");
static assert(C18891.__xdtor.mangleof == "??_GC18891@@UAEPAXI@Z");
}
version (Win64)
{
static assert(C18891.__dtor.mangleof == "??1C18891@@UEAA@XZ");
static assert(C18891.__xdtor.mangleof == "??_GC18891@@UEAAPEAXI@Z");
}
}
/**************************************/
@ -719,7 +740,7 @@ extern (C++) struct TestOperators
int opAssign(int);
}
version (Posix)
version (CppMangle_Itanium)
{
static assert(TestOperators.opUnary!"*".mangleof == "_ZN13TestOperatorsdeEv");
static assert(TestOperators.opUnary!"++".mangleof == "_ZN13TestOperatorsppEv");
@ -753,73 +774,76 @@ version (Posix)
static assert(TestOperators.opIndex.mangleof == "_ZN13TestOperatorsixEi");
static assert(TestOperators.opCall.mangleof == "_ZN13TestOperatorsclEif");
}
version (Win32)
version (CppMangle_MSVC)
{
static assert(TestOperators.opUnary!"*".mangleof == "??DTestOperators@@QAEHXZ");
static assert(TestOperators.opUnary!"++".mangleof == "??ETestOperators@@QAEHXZ");
static assert(TestOperators.opUnary!"--".mangleof == "??FTestOperators@@QAEHXZ");
static assert(TestOperators.opUnary!"-".mangleof == "??GTestOperators@@QAEHXZ");
static assert(TestOperators.opUnary!"+".mangleof == "??HTestOperators@@QAEHXZ");
static assert(TestOperators.opUnary!"~".mangleof == "??STestOperators@@QAEHXZ");
static assert(TestOperators.opBinary!">>".mangleof == "??5TestOperators@@QAEHH@Z");
static assert(TestOperators.opBinary!"<<".mangleof == "??6TestOperators@@QAEHH@Z");
static assert(TestOperators.opBinary!"*".mangleof == "??DTestOperators@@QAEHH@Z");
static assert(TestOperators.opBinary!"-".mangleof == "??GTestOperators@@QAEHH@Z");
static assert(TestOperators.opBinary!"+".mangleof == "??HTestOperators@@QAEHH@Z");
static assert(TestOperators.opBinary!"&".mangleof == "??ITestOperators@@QAEHH@Z");
static assert(TestOperators.opBinary!"/".mangleof == "??KTestOperators@@QAEHH@Z");
static assert(TestOperators.opBinary!"%".mangleof == "??LTestOperators@@QAEHH@Z");
static assert(TestOperators.opBinary!"^".mangleof == "??TTestOperators@@QAEHH@Z");
static assert(TestOperators.opBinary!"|".mangleof == "??UTestOperators@@QAEHH@Z");
static assert(TestOperators.opOpAssign!"*".mangleof == "??XTestOperators@@QAEHH@Z");
static assert(TestOperators.opOpAssign!"+".mangleof == "??YTestOperators@@QAEHH@Z");
static assert(TestOperators.opOpAssign!"-".mangleof == "??ZTestOperators@@QAEHH@Z");
static assert(TestOperators.opOpAssign!"/".mangleof == "??_0TestOperators@@QAEHH@Z");
static assert(TestOperators.opOpAssign!"%".mangleof == "??_1TestOperators@@QAEHH@Z");
static assert(TestOperators.opOpAssign!">>".mangleof == "??_2TestOperators@@QAEHH@Z");
static assert(TestOperators.opOpAssign!"<<".mangleof == "??_3TestOperators@@QAEHH@Z");
static assert(TestOperators.opOpAssign!"&".mangleof == "??_4TestOperators@@QAEHH@Z");
static assert(TestOperators.opOpAssign!"|".mangleof == "??_5TestOperators@@QAEHH@Z");
static assert(TestOperators.opOpAssign!"^".mangleof == "??_6TestOperators@@QAEHH@Z");
static assert(TestOperators.opCast!int.mangleof == "??BTestOperators@@QAEHXZ");
static assert(TestOperators.opAssign.mangleof == "??4TestOperators@@QAEHH@Z");
static assert(TestOperators.opEquals.mangleof == "??8TestOperators@@QAE_NH@Z");
static assert(TestOperators.opIndex.mangleof == "??ATestOperators@@QAEHH@Z");
static assert(TestOperators.opCall.mangleof == "??RTestOperators@@QAEHHM@Z");
}
version (Win64)
{
static assert(TestOperators.opUnary!"*".mangleof == "??DTestOperators@@QEAAHXZ");
static assert(TestOperators.opUnary!"++".mangleof == "??ETestOperators@@QEAAHXZ");
static assert(TestOperators.opUnary!"--".mangleof == "??FTestOperators@@QEAAHXZ");
static assert(TestOperators.opUnary!"-".mangleof == "??GTestOperators@@QEAAHXZ");
static assert(TestOperators.opUnary!"+".mangleof == "??HTestOperators@@QEAAHXZ");
static assert(TestOperators.opUnary!"~".mangleof == "??STestOperators@@QEAAHXZ");
static assert(TestOperators.opBinary!">>".mangleof == "??5TestOperators@@QEAAHH@Z");
static assert(TestOperators.opBinary!"<<".mangleof == "??6TestOperators@@QEAAHH@Z");
static assert(TestOperators.opBinary!"*".mangleof == "??DTestOperators@@QEAAHH@Z");
static assert(TestOperators.opBinary!"-".mangleof == "??GTestOperators@@QEAAHH@Z");
static assert(TestOperators.opBinary!"+".mangleof == "??HTestOperators@@QEAAHH@Z");
static assert(TestOperators.opBinary!"&".mangleof == "??ITestOperators@@QEAAHH@Z");
static assert(TestOperators.opBinary!"/".mangleof == "??KTestOperators@@QEAAHH@Z");
static assert(TestOperators.opBinary!"%".mangleof == "??LTestOperators@@QEAAHH@Z");
static assert(TestOperators.opBinary!"^".mangleof == "??TTestOperators@@QEAAHH@Z");
static assert(TestOperators.opBinary!"|".mangleof == "??UTestOperators@@QEAAHH@Z");
static assert(TestOperators.opOpAssign!"*".mangleof == "??XTestOperators@@QEAAHH@Z");
static assert(TestOperators.opOpAssign!"+".mangleof == "??YTestOperators@@QEAAHH@Z");
static assert(TestOperators.opOpAssign!"-".mangleof == "??ZTestOperators@@QEAAHH@Z");
static assert(TestOperators.opOpAssign!"/".mangleof == "??_0TestOperators@@QEAAHH@Z");
static assert(TestOperators.opOpAssign!"%".mangleof == "??_1TestOperators@@QEAAHH@Z");
static assert(TestOperators.opOpAssign!">>".mangleof == "??_2TestOperators@@QEAAHH@Z");
static assert(TestOperators.opOpAssign!"<<".mangleof == "??_3TestOperators@@QEAAHH@Z");
static assert(TestOperators.opOpAssign!"&".mangleof == "??_4TestOperators@@QEAAHH@Z");
static assert(TestOperators.opOpAssign!"|".mangleof == "??_5TestOperators@@QEAAHH@Z");
static assert(TestOperators.opOpAssign!"^".mangleof == "??_6TestOperators@@QEAAHH@Z");
static assert(TestOperators.opCast!int.mangleof == "??BTestOperators@@QEAAHXZ");
static assert(TestOperators.opAssign.mangleof == "??4TestOperators@@QEAAHH@Z");
static assert(TestOperators.opEquals.mangleof == "??8TestOperators@@QEAA_NH@Z");
static assert(TestOperators.opIndex.mangleof == "??ATestOperators@@QEAAHH@Z");
static assert(TestOperators.opCall.mangleof == "??RTestOperators@@QEAAHHM@Z");
version (Win32)
{
static assert(TestOperators.opUnary!"*".mangleof == "??DTestOperators@@QAEHXZ");
static assert(TestOperators.opUnary!"++".mangleof == "??ETestOperators@@QAEHXZ");
static assert(TestOperators.opUnary!"--".mangleof == "??FTestOperators@@QAEHXZ");
static assert(TestOperators.opUnary!"-".mangleof == "??GTestOperators@@QAEHXZ");
static assert(TestOperators.opUnary!"+".mangleof == "??HTestOperators@@QAEHXZ");
static assert(TestOperators.opUnary!"~".mangleof == "??STestOperators@@QAEHXZ");
static assert(TestOperators.opBinary!">>".mangleof == "??5TestOperators@@QAEHH@Z");
static assert(TestOperators.opBinary!"<<".mangleof == "??6TestOperators@@QAEHH@Z");
static assert(TestOperators.opBinary!"*".mangleof == "??DTestOperators@@QAEHH@Z");
static assert(TestOperators.opBinary!"-".mangleof == "??GTestOperators@@QAEHH@Z");
static assert(TestOperators.opBinary!"+".mangleof == "??HTestOperators@@QAEHH@Z");
static assert(TestOperators.opBinary!"&".mangleof == "??ITestOperators@@QAEHH@Z");
static assert(TestOperators.opBinary!"/".mangleof == "??KTestOperators@@QAEHH@Z");
static assert(TestOperators.opBinary!"%".mangleof == "??LTestOperators@@QAEHH@Z");
static assert(TestOperators.opBinary!"^".mangleof == "??TTestOperators@@QAEHH@Z");
static assert(TestOperators.opBinary!"|".mangleof == "??UTestOperators@@QAEHH@Z");
static assert(TestOperators.opOpAssign!"*".mangleof == "??XTestOperators@@QAEHH@Z");
static assert(TestOperators.opOpAssign!"+".mangleof == "??YTestOperators@@QAEHH@Z");
static assert(TestOperators.opOpAssign!"-".mangleof == "??ZTestOperators@@QAEHH@Z");
static assert(TestOperators.opOpAssign!"/".mangleof == "??_0TestOperators@@QAEHH@Z");
static assert(TestOperators.opOpAssign!"%".mangleof == "??_1TestOperators@@QAEHH@Z");
static assert(TestOperators.opOpAssign!">>".mangleof == "??_2TestOperators@@QAEHH@Z");
static assert(TestOperators.opOpAssign!"<<".mangleof == "??_3TestOperators@@QAEHH@Z");
static assert(TestOperators.opOpAssign!"&".mangleof == "??_4TestOperators@@QAEHH@Z");
static assert(TestOperators.opOpAssign!"|".mangleof == "??_5TestOperators@@QAEHH@Z");
static assert(TestOperators.opOpAssign!"^".mangleof == "??_6TestOperators@@QAEHH@Z");
static assert(TestOperators.opCast!int.mangleof == "??BTestOperators@@QAEHXZ");
static assert(TestOperators.opAssign.mangleof == "??4TestOperators@@QAEHH@Z");
static assert(TestOperators.opEquals.mangleof == "??8TestOperators@@QAE_NH@Z");
static assert(TestOperators.opIndex.mangleof == "??ATestOperators@@QAEHH@Z");
static assert(TestOperators.opCall.mangleof == "??RTestOperators@@QAEHHM@Z");
}
version (Win64)
{
static assert(TestOperators.opUnary!"*".mangleof == "??DTestOperators@@QEAAHXZ");
static assert(TestOperators.opUnary!"++".mangleof == "??ETestOperators@@QEAAHXZ");
static assert(TestOperators.opUnary!"--".mangleof == "??FTestOperators@@QEAAHXZ");
static assert(TestOperators.opUnary!"-".mangleof == "??GTestOperators@@QEAAHXZ");
static assert(TestOperators.opUnary!"+".mangleof == "??HTestOperators@@QEAAHXZ");
static assert(TestOperators.opUnary!"~".mangleof == "??STestOperators@@QEAAHXZ");
static assert(TestOperators.opBinary!">>".mangleof == "??5TestOperators@@QEAAHH@Z");
static assert(TestOperators.opBinary!"<<".mangleof == "??6TestOperators@@QEAAHH@Z");
static assert(TestOperators.opBinary!"*".mangleof == "??DTestOperators@@QEAAHH@Z");
static assert(TestOperators.opBinary!"-".mangleof == "??GTestOperators@@QEAAHH@Z");
static assert(TestOperators.opBinary!"+".mangleof == "??HTestOperators@@QEAAHH@Z");
static assert(TestOperators.opBinary!"&".mangleof == "??ITestOperators@@QEAAHH@Z");
static assert(TestOperators.opBinary!"/".mangleof == "??KTestOperators@@QEAAHH@Z");
static assert(TestOperators.opBinary!"%".mangleof == "??LTestOperators@@QEAAHH@Z");
static assert(TestOperators.opBinary!"^".mangleof == "??TTestOperators@@QEAAHH@Z");
static assert(TestOperators.opBinary!"|".mangleof == "??UTestOperators@@QEAAHH@Z");
static assert(TestOperators.opOpAssign!"*".mangleof == "??XTestOperators@@QEAAHH@Z");
static assert(TestOperators.opOpAssign!"+".mangleof == "??YTestOperators@@QEAAHH@Z");
static assert(TestOperators.opOpAssign!"-".mangleof == "??ZTestOperators@@QEAAHH@Z");
static assert(TestOperators.opOpAssign!"/".mangleof == "??_0TestOperators@@QEAAHH@Z");
static assert(TestOperators.opOpAssign!"%".mangleof == "??_1TestOperators@@QEAAHH@Z");
static assert(TestOperators.opOpAssign!">>".mangleof == "??_2TestOperators@@QEAAHH@Z");
static assert(TestOperators.opOpAssign!"<<".mangleof == "??_3TestOperators@@QEAAHH@Z");
static assert(TestOperators.opOpAssign!"&".mangleof == "??_4TestOperators@@QEAAHH@Z");
static assert(TestOperators.opOpAssign!"|".mangleof == "??_5TestOperators@@QEAAHH@Z");
static assert(TestOperators.opOpAssign!"^".mangleof == "??_6TestOperators@@QEAAHH@Z");
static assert(TestOperators.opCast!int.mangleof == "??BTestOperators@@QEAAHXZ");
static assert(TestOperators.opAssign.mangleof == "??4TestOperators@@QEAAHH@Z");
static assert(TestOperators.opEquals.mangleof == "??8TestOperators@@QEAA_NH@Z");
static assert(TestOperators.opIndex.mangleof == "??ATestOperators@@QEAAHH@Z");
static assert(TestOperators.opCall.mangleof == "??RTestOperators@@QEAAHHM@Z");
}
}
import cppmangle2;
@ -839,14 +863,14 @@ extern(C++, `Namespace18922`)
void func18922_3(Struct18922) {}
}
version (Posix)
version (CppMangle_Itanium)
{
static assert(func18922.mangleof == "_ZN14Namespace189229func18922ENS_11Struct18922E");
static assert(func18922_1.mangleof == "_ZN14Namespace1892211func18922_1ENS_11Struct18922E");
static assert(func18922_2.mangleof == "_ZN14Namespace1892211func18922_2ENS_11Struct18922E");
static assert(func18922_3.mangleof == "_ZN14Namespace1892211func18922_3ENS_11Struct18922E");
}
else version(Windows)
else version (CppMangle_MSVC)
{
static assert(func18922.mangleof == "?func18922@Namespace18922@@YAXUStruct18922@1@@Z");
static assert(func18922_1.mangleof == "?func18922_1@Namespace18922@@YAXUStruct18922@1@@Z");
@ -858,7 +882,7 @@ else version(Windows)
// https://issues.dlang.org/show_bug.cgi?id=18957
// extern(C++) doesn't mangle 'std' correctly on posix systems
version (Posix)
version (CppMangle_Itanium)
{
// https://godbolt.org/z/C5T2LQ
/+
@ -881,7 +905,7 @@ extern(C++) struct test19043(T) {}
extern(C++) void test19043a(test19043!(const(char)) a) {}
extern(C++) void test19043b(T)(T a) {}
version(Windows)
version (CppMangle_MSVC)
{
static assert(test19043a.mangleof == "?test19043a@@YAXU?$test19043@$$CBD@@@Z");
static assert(test19043b!(test19043!(const(char))).mangleof ==
@ -890,7 +914,7 @@ version(Windows)
// https://issues.dlang.org/show_bug.cgi?id=16479
// Missing substitution while mangling C++ template parameter for functions
version (Posix) extern (C++)
version (CppMangle_Itanium) extern (C++)
{
// Make sure aliases are still resolved
alias Alias16479 = int;
@ -1084,15 +1108,18 @@ extern(C++, (AliasSeq!(Tup, "yay")))
{
void test19278_4();
}
version(Win64)
version (CppMangle_MSVC)
{
static assert(test19278.mangleof == "?test19278@helloworld@@YAXXZ");
static assert(test19278_2.mangleof == "?test19278_2@lookup@@YAXXZ");
static assert(test19278_3.mangleof == "?test19278_3@world@hello@@YAXXZ");
static assert(test19278_4.mangleof == "?test19278_4@yay@world@hello@@YAXXZ");
static assert(test19278_var.mangleof == "?test19278_var@world@hello@@3_KA");
version (Win64)
{
static assert(test19278.mangleof == "?test19278@helloworld@@YAXXZ");
static assert(test19278_2.mangleof == "?test19278_2@lookup@@YAXXZ");
static assert(test19278_3.mangleof == "?test19278_3@world@hello@@YAXXZ");
static assert(test19278_4.mangleof == "?test19278_4@yay@world@hello@@YAXXZ");
static assert(test19278_var.mangleof == "?test19278_var@world@hello@@3_KA");
}
}
else version(Posix)
else version (CppMangle_Itanium)
{
static assert(test19278.mangleof == "_ZN10helloworld9test19278Ev");
static assert(test19278_2.mangleof == "_ZN6lookup11test19278_2Ev");
@ -1105,23 +1132,26 @@ else version(Posix)
// https://issues.dlang.org/show_bug.cgi?id=18958
// Issue 18958 - extern(C++) wchar, dchar mangling not correct
version(Posix)
version (Posix)
enum __c_wchar_t : dchar;
else version(Windows)
else version (Windows)
enum __c_wchar_t : wchar;
alias wchar_t = __c_wchar_t;
extern (C++) void test_char_mangling(char, wchar, dchar, wchar_t);
version (Posix)
version (CppMangle_Itanium)
{
static assert(test_char_mangling.mangleof == "_Z18test_char_manglingcDsDiw");
}
version (Win64)
version (CppMangle_MSVC)
{
static assert(test_char_mangling.mangleof == "?test_char_mangling@@YAXD_S_U_W@Z");
version (Win64)
{
static assert(test_char_mangling.mangleof == "?test_char_mangling@@YAXD_S_U_W@Z");
}
}
// https://github.com/dlang/dmd/pull/10021/files#r294055424
version (Posix)
version (CppMangle_Itanium)
{
extern(C++, PR10021_NS) struct PR10021_Struct(T){}
extern(C++) void PR10021_fun(int i)(PR10021_Struct!int);
@ -1129,7 +1159,7 @@ version (Posix)
}
// https://github.com/dlang/dmd/pull/10021#discussion_r294095749
version (Posix)
version (CppMangle_Itanium)
{
extern(C++, "a", "b")
struct PR10021_Struct2
@ -1142,7 +1172,7 @@ version (Posix)
}
/// https://issues.dlang.org/show_bug.cgi?id=20022
version (Posix)
version (CppMangle_Itanium)
{
extern(C++, `ns20022`) enum Enum20022_1 { A = 1, }
extern(C++) void fun20022_1(Enum20022_1);
@ -1167,7 +1197,7 @@ version (Posix)
}
// https://issues.dlang.org/show_bug.cgi?id=20094
version (Posix)
version (CppMangle_Itanium)
{
extern(C++, "ns20094")
{
@ -1180,7 +1210,7 @@ version (Posix)
}
// https://issues.dlang.org/show_bug.cgi?id=20223
version (Posix)
version (CppMangle_Itanium)
{
extern(C++)
{
@ -1206,7 +1236,7 @@ version (Posix)
}
// https://issues.dlang.org/show_bug.cgi?id=20224
version (Posix)
version (CppMangle_Itanium)
{
extern(C++) public int test20224_1(T)(set20224!T set); // ok
extern(C++) public int test20224_2(T)(ref set20224!T set); // segfault
@ -1228,7 +1258,7 @@ version (Posix)
/**************************************/
version (Posix)
version (CppMangle_Itanium)
{
extern (C++) struct Loc2 {};
extern (C++) class FuncDeclaration
@ -1251,7 +1281,7 @@ extern(C++, `bar`)
// https://issues.dlang.org/show_bug.cgi?id=20700
// Only testing on WIn64 because the mangling includes 'E',
// and the bug can be tested on either platform
version (Win64) extern(C++)
version (CppMangle_MSVC) version (Win64) extern(C++)
{
void test20700_1(Struct20700);
extern(C++, class) struct Struct20700 {}
@ -1285,12 +1315,15 @@ extern (C++)
alias fpcpp = noreturn function();
int funccpp(fpcpp);
version (Posix)
version (CppMangle_Itanium)
static assert(funccpp.mangleof == "_Z7funccppPFvvE");
version (Win32)
static assert(funccpp.mangleof == "?funccpp@@YAHP6AXXZ@Z");
version (CppMangle_MSVC)
{
version (Win32)
static assert(funccpp.mangleof == "?funccpp@@YAHP6AXXZ@Z");
version (Win64)
static assert(funccpp.mangleof == "?funccpp@@YAHP6AXXZ@Z");
version (Win64)
static assert(funccpp.mangleof == "?funccpp@@YAHP6AXXZ@Z");
}
}

View File

@ -3,6 +3,11 @@
// https://issues.dlang.org/show_bug.cgi?id=19920
module cppmangle3;
version (CppRuntime_Clang) version = CppMangle_Itanium;
version (CppRuntime_DigitalMars) version = CppMangle_MSVC;
version (CppRuntime_Gcc) version = CppMangle_Itanium;
version (CppRuntime_Microsoft) version = CppMangle_MSVC;
version (CppRuntime_Sun) version = CppMangle_Itanium;
extern(C++, "true")
{
@ -23,8 +28,8 @@ extern(C++, "std", "chrono")
void func();
}
version(Windows) static assert(func.mangleof == "?func@chrono@std@@YAXXZ");
else static assert(func.mangleof == "_ZNSt6chrono4funcEv");
version(CppMangle_MSVC) static assert(func.mangleof == "?func@chrono@std@@YAXXZ");
else static assert(func.mangleof == "_ZNSt6chrono4funcEv");
struct Foo
{

View File

@ -0,0 +1,210 @@
version (CppRuntime_Clang) version = CppMangle_Itanium;
version (CppRuntime_Gcc) version = CppMangle_Itanium;
version (CppRuntime_Sun) version = CppMangle_Itanium;
template ScopeClass(C , string name = C.stringof)
//if (is(C == class) && __traits(getLinkage, C) == "C++")
{
//enum name = C.stringof;
enum ns = __traits(getCppNamespaces,C);
extern(C++, class)
{
extern(C++,(ns))
{
pragma(mangle, C, name)
struct ScopeClass
{
char[__traits(classInstanceSize, C)] buffer;
//... all the things ...
}
}
}
}
// Basic tests
extern(C++)
{
class MyClassA {}
void funa(ScopeClass!MyClassA); // mangles MyClass
void funb(const ScopeClass!MyClassA); // mangles const MyClass
void func(ref ScopeClass!MyClassA); // mangles MyClass&
void fund(ref const ScopeClass!MyClassA); // mangles const MyClass&
void fune(const(ScopeClass!MyClassA)*);
}
version (CppMangle_Itanium)
{
static assert(funa.mangleof == "_Z4funa8MyClassA");
static assert(funb.mangleof == "_Z4funb8MyClassA");
static assert(func.mangleof == "_Z4funcR8MyClassA");
static assert(fund.mangleof == "_Z4fundRK8MyClassA");
static assert(fune.mangleof == "_Z4funePK8MyClassA");
}
else version (CppRuntime_Microsoft)
{
static assert(funa.mangleof == "?funa@@YAXVMyClassA@@@Z");
static assert(funb.mangleof == "?funb@@YAXVMyClassA@@@Z");
static if (size_t.sizeof == ulong.sizeof)
{
static assert(func.mangleof == "?func@@YAXAEAVMyClassA@@@Z");
static assert(fund.mangleof == "?fund@@YAXAEBVMyClassA@@@Z");
static assert(fune.mangleof == "?fune@@YAXPEBVMyClassA@@@Z");
}
else
{
static assert(func.mangleof == "?func@@YAXAAVMyClassA@@@Z");
static assert(fund.mangleof == "?fund@@YAXABVMyClassA@@@Z");
static assert(fune.mangleof == "?fune@@YAXPBVMyClassA@@@Z");
}
}
//Basic tests with a namespace
extern(C++, "ns")
{
class MyClassB {}
void funf(ScopeClass!MyClassB); // mangles MyClass
void fung(const ScopeClass!MyClassB); // mangles const MyClass
void funh(ref ScopeClass!MyClassB); // mangles MyClass&
void funi(ref const ScopeClass!MyClassB); // mangles const MyClass&
void funj(const(ScopeClass!MyClassB)*);
}
version (CppMangle_Itanium)
{
static assert(funf.mangleof == "_ZN2ns4funfENS_8MyClassBE");
static assert(fung.mangleof == "_ZN2ns4fungENS_8MyClassBE");
static assert(funh.mangleof == "_ZN2ns4funhERNS_8MyClassBE");
static assert(funi.mangleof == "_ZN2ns4funiERKNS_8MyClassBE");
static assert(funj.mangleof == "_ZN2ns4funjEPKNS_8MyClassBE");
}
else version (CppRuntime_Microsoft)
{
static assert(funf.mangleof == "?funf@ns@@YAXVMyClassB@1@@Z");
static assert(fung.mangleof == "?fung@ns@@YAXVMyClassB@1@@Z");
static if (size_t.sizeof == ulong.sizeof)
{
static assert(funh.mangleof == "?funh@ns@@YAXAEAVMyClassB@1@@Z");
static assert(funi.mangleof == "?funi@ns@@YAXAEBVMyClassB@1@@Z");
static assert(funj.mangleof == "?funj@ns@@YAXPEBVMyClassB@1@@Z");
}
else
{
static assert(funh.mangleof == "?funh@ns@@YAXAAVMyClassB@1@@Z");
static assert(funi.mangleof == "?funi@ns@@YAXABVMyClassB@1@@Z");
static assert(funj.mangleof == "?funj@ns@@YAXPBVMyClassB@1@@Z");
}
}
//Templates
extern(C++)
{
void funTempl(T)();
class MyClassC {}
alias funTemplA = funTempl!(ScopeClass!MyClassC);
alias funTemplB = funTempl!(const ScopeClass!MyClassC);
alias funTemplC = funTempl!(const(ScopeClass!MyClassC)*);
// N.B funTempl!([const] ref ScopeClass!MyClassC) is not permissable in D
}
version (CppMangle_Itanium)
{
static assert(funTemplA.mangleof == "_Z8funTemplI8MyClassCEvv");
static assert(funTemplB.mangleof == "_Z8funTemplIK8MyClassCEvv");
static assert(funTemplC.mangleof == "_Z8funTemplIPK8MyClassCEvv");
}
else version (CppRuntime_Microsoft)
{
static assert(funTemplA.mangleof == "??$funTempl@VMyClassC@@@@YAXXZ");
static assert(funTemplB.mangleof == "??$funTempl@$$CBVMyClassC@@@@YAXXZ");
static if (size_t.sizeof == ulong.sizeof)
static assert(funTemplC.mangleof == "??$funTempl@PEBVMyClassC@@@@YAXXZ");
else
static assert(funTemplC.mangleof == "??$funTempl@PBVMyClassC@@@@YAXXZ");
}
template _function(F)
{
extern(C++, "std")
{
extern(C++, struct)
pragma(mangle, "function")
class _function
{
}
}
}
template FunctionOf(F)
{
F f;
alias FunctionOf = typeof(*f);
}
extern(C++) void funk(ScopeClass!(_function!(FunctionOf!(void function(int))),"function") a ){ }
version (CppMangle_Itanium)
{
static assert(funk.mangleof == "_Z4funkSt8functionIFviEE");
}
else version (CppRuntime_Microsoft)
{
static assert(funk.mangleof == "?funk@@YAXV?$function@$$A6AXH@Z@std@@@Z");
}
extern(C++, "ns")
{
pragma(mangle, "function")
class _function2
{
public final void test();
}
}
version (CppMangle_Itanium)
{
static assert(_function2.test.mangleof == "_ZN2ns8function4testEv");
}
else version (CppRuntime_Microsoft)
{
static if (size_t.sizeof == ulong.sizeof)
static assert(_function2.test.mangleof == "?test@function@ns@@QEAAXXZ");
else
static assert(_function2.test.mangleof == "?test@function@ns@@QAEXXZ");
}
extern(C++, "ns")
{
template _function3(T)
{
pragma(mangle, _function3, "function")
class _function3
{
public final void test();
}
}
}
version (CppMangle_Itanium)
{
static assert(_function3!(int).test.mangleof == "_ZN2ns8functionIiE4testEv");
}
else version (CppRuntime_Microsoft)
{
static if (size_t.sizeof == ulong.sizeof)
static assert(_function3!(int).test.mangleof == "?test@?$function@H@ns@@QEAAXXZ");
else
static assert(_function3!(int).test.mangleof == "?test@?$function@H@ns@@QAEXXZ");
}
extern(C++)
{
struct Foo {}
pragma(mangle, Foo) struct Foo_Doppelganger {}
void funl(Foo_Doppelganger f);
}
version (CppMangle_Itanium)
{
static assert(funl.mangleof == "_Z4funl3Foo");
}
else version (CppRuntime_Microsoft)
{
static assert(funl.mangleof == "?funl@@YAXUFoo@@@Z");
}

View File

@ -0,0 +1,38 @@
version (CppRuntime_Clang) version = CppMangle_Itanium;
version (CppRuntime_Gcc) version = CppMangle_Itanium;
version (CppRuntime_Sun) version = CppMangle_Itanium;
template ScopeClass(C)
if (is(C == class) && __traits(getLinkage, C) == "C++")
{
extern(C++, class)
extern(C++, __traits(getCppNamespaces,C))
extern(C++, (ns))
class ScopeClass { }
}
extern(C++) class Foo {}
extern(C++) void test(ScopeClass!Foo)
{
}
version(CppMangle_Itanium)
{
static assert (test.mangleof == "_Z4testP10ScopeClassIP3FooE");
}
else version (CppRuntime_Microsoft)
{
version (Win32)
{
static assert (test.mangleof == "?test@@YAXPAV?$ScopeClass@PAVFoo@@@@@Z");
}
version (Win64)
{
static assert (test.mangleof == "?test@@YAXPEAV?$ScopeClass@PEAVFoo@@@@@Z");
}
}
alias AliasSeq(T...) = T;
alias ns = AliasSeq!();
immutable ns2 = AliasSeq!();
extern(C++,(ns)) class Bar {}
extern(C++,) class Baz {}
extern(C++, (ns2)) class Quux {}

View File

@ -0,0 +1,7 @@
enum E:char[4]{ str = "abcd" }
enum x = {
int[char[4]] aa;
aa[E.str] = 1;
foreach(key,val; aa) {}
return aa["abcd"];
}();

View File

@ -0,0 +1,22 @@
// https://issues.dlang.org/show_bug.cgi?id=20236
/*
TEST_OUTPUT:
---
---
*/
struct X
{
alias y this;
deprecated int y() { return 5; }
int x() { return 5; }
}
void main()
{
static void func(int) {}
with(X.init) {
func(x);
}
}

View File

@ -0,0 +1,16 @@
// https://issues.dlang.org/show_bug.cgi?id=20860
struct A
{
this(int a) {}
///
void opDispatch(string methodName, Params...)(Params params) {
}
~this() {}
}
void main()
{
A(3).test();
}

View File

@ -0,0 +1,16 @@
// https://issues.dlang.org/show_bug.cgi?id=21073
class C
{
auto internal() const
{
return 5;
}
alias internal this;
}
void main() pure
{
const c = new C;
auto r = cast(C)c;
}

View File

@ -0,0 +1,13 @@
// https://issues.dlang.org/show_bug.cgi?id=21414
struct State
{
string s;
immutable this(string s)
{
this.s = s;
}
}
immutable rootState = new immutable State("b");

View File

@ -1,6 +1,6 @@
/* TEST_OUTPUT:
---
fail_compilation/b15875.d(9): Error: circular reference to variable `a`
fail_compilation/b15875.d(9): Error: undefined identifier `a`
fail_compilation/b15875.d(10): Error: circular reference to `b15875.f`
---
*/

View File

@ -1,7 +1,7 @@
/*
TEST_OUTPUT:
---
fail_compilation/fail116.d(11): Error: circular `typeof` definition
fail_compilation/fail116.d(11): Error: undefined identifier `x`
fail_compilation/fail116.d(16): Error: template instance `square!1.2` does not match template declaration `square(_error_ x)`
---
*/

View File

@ -0,0 +1,26 @@
/*
TEST_OUTPUT:
---
fail_compilation/fail20616.d(16): Error: undefined identifier `$`
fail_compilation/fail20616.d(16): Aggregate declaration 'X()' does not define 'opDollar'
fail_compilation/fail20616.d(18): Error: undefined identifier `$`
fail_compilation/fail20616.d(18): Aggregate declaration 'b' does not define 'opDollar'
---
*/
module fail20616;
void g() {
struct X {
auto opSlice(size_t a, size_t b) { return ""; }
}
auto x = X()[0 .. $];
auto b = X();
auto c = b[0 .. $ - 1];
auto v = [1, 2, 3];
auto d = v[$.. $];
}
int main() {
g();
return 0;
}

View File

@ -0,0 +1,14 @@
// https://issues.dlang.org/show_bug.cgi?id=22529
/*
TEST_OUTPUT:
---
fail_compilation/fail22529.d(13): Error: found `return` when expecting `;` following statement
---
*/
void main()
{
foo()
return;
}

View File

@ -0,0 +1,21 @@
// https://issues.dlang.org/show_bug.cgi?id=22570
/*
TEST_OUTPUT:
---
fail_compilation/fail22570.d(19): Error: more initializers than fields (1) of `S`
fail_compilation/fail22570.d(20): Error: more initializers than fields (1) of `S`
---
*/
struct S
{
Object o1;
}
void main() @safe
{
S[] s;
s = [S(null, null)];
s ~= S(null, null);
}

View File

@ -0,0 +1,21 @@
/++
https://issues.dlang.org/show_bug.cgi?id=22516
TEST_OUTPUT:
---
fail_compilation/ice22516.d(18): Error: undefined identifier `X`
---
+/
struct Data
{
void function() eval;
}
struct Builtins
{
X x;
Data myData = { (){} };
}

View File

@ -0,0 +1,12 @@
//https://issues.dlang.org/show_bug.cgi?id=22574
/*
TEST_OUTPUT:
---
fail_compilation/test22574.d(100): Error: undefined identifier `x`
---
*/
#line 100
template test(x* x)
{
}

View File

@ -0,0 +1,101 @@
/++
https://issues.dlang.org/show_bug.cgi?id=22514
TEST_OUTPUT:
---
fail_compilation/test_switch_error.d(13): Error: undefined identifier `doesNotExist`
fail_compilation/test_switch_error.d(16): Error: undefined identifier `alsoDoesNotExits`
fail_compilation/test_switch_error.d(19): Error: duplicate `case 2` in `switch` statement
---
++/
void test1()
{
switch (doesNotExist)
{
case 1:
alsoDoesNotExits();
break;
case 2: break;
case 2: break;
}
}
/++
TEST_OUTPUT:
---
fail_compilation/test_switch_error.d(105): Error: undefined identifier `doesNotExist`
---
++/
#line 100
enum foo = 1;
void test2()
{
switch (doesNotExist)
{
case foo: break;
}
}
/++
TEST_OUTPUT:
---
fail_compilation/test_switch_error.d(206): Error: undefined identifier `a`
fail_compilation/test_switch_error.d(207): Error: undefined identifier `b`
---
++/
#line 200
void test3()
{
switch (1)
{
case a: break;
case b: break;
}
}
/++
TEST_OUTPUT:
---
fail_compilation/test_switch_error.d(303): Error: undefined identifier `doesNotExits`
---
++/
#line 300
void test4()
{
auto foo = doesNotExits();
switch (1)
{
case foo: break;
case foo: break;
}
}
/++
TEST_OUTPUT:
---
fail_compilation/test_switch_error.d(405): Error: `case` variables have to be `const` or `immutable`
fail_compilation/test_switch_error.d(412): Error: `case` variables not allowed in `final switch` statements
---
++/
#line 400
void test5(int i)
{
switch (i)
{
case i: break;
default: break;
}
const int j = i;
final switch (i)
{
case j: break;
}
}

View File

@ -3660,6 +3660,28 @@ void test20133()
auto rtest2 = fun20133_2();
}
/************************************************/
// https://issues.dlang.org/show_bug.cgi?id=22530
class D22530 { }
class C22530
{
D22530 y = new D22530;
alias y this;
}
void test22530()
{
// fixed
static assert(cast(D22530)(new C22530) is null);
static assert((1 ? cast(D22530)(new C22530) : new D22530) is null);
// runtime version already works
assert(cast(D22530)(new C22530) is null);
assert((1 ? cast(D22530)(new C22530) : new D22530) is null);
}
/************************************************/
int main()
@ -3789,6 +3811,7 @@ int main()
test20400();
test21878();
test20133();
test22530();
printf("Success\n");
return 0;

View File

@ -0,0 +1,57 @@
// REQUIRED_ARGS: -unittest
// PERMUTE_ARGS:
// https://issues.dlang.org/show_bug.cgi?id=16579
struct Thing
{
enum Instance = Thing();
int a = 42;
void iter()
{
assert(this.a == 42);
}
}
void main()
{
return Thing.Instance.iter; // Added 'return'
}
// From https://issues.dlang.org/show_bug.cgi?id=16576
alias a = test2!();
alias b = test3!();
template test2()
{
struct Thing{
static enum Instance = Thing([0, 1, 2, 3]);
int[] array;
void iter(in string str) const{
foreach(j, tup; this.array) assert(tup == j);
assert(this.array && this.array.length == 4);
}
}
unittest{
auto test(in string str){return Thing.Instance.iter(str);}
test("?");
}
}
template test3()
{
struct Thing{
static enum Instance = Thing([0, 1, 2, 3]);
int[] array;
void iter() const{
foreach(j, tup; this.array) assert(tup == j);
assert(this.array && this.array.length == 4);
}
}
unittest{
auto test(){return Thing.Instance.iter();}
test();
}
}

View File

@ -0,0 +1,41 @@
/+
REQUIRED_ARGS: -d
RUN_OUTPUT:
---
float: 1 == 1
double: 1 == 1
real: 1 == 1
ifloat: 1 == 1
idouble: 1 == 1
ireal: 1 == 1
cfloat: 1 == 1
cdouble: 1 == 1
creal: 1 == 1
---
+/
import core.stdc.stdio : printf;
void test(T, string lit)()
{
T d = mixin(lit);
bool runtime = cast(bool) d;
bool folded = cast(bool) mixin(lit);
printf((T.stringof ~ ": %d == %d\n\0").ptr, runtime, folded);
}
void main()
{
test!(float, "0.5f");
test!(double, "0.5" );
test!(real, "0.5L");
test!(ifloat, "0.5i");
test!(idouble, "0.5i");
test!(ireal, "0.5i");
test!(cfloat, "0.3 + 0.5i");
test!(cdouble, "0.3 + 0.5i");
test!(creal, "0.3 + 0.5i");
}

View File

@ -442,28 +442,54 @@ void test13161()
version (linux)
{
extern(C++, __gnu_cxx)
static if (__traits(getTargetInfo, "cppStd") < 201703)
{
struct new_allocator(T)
// See note on std::allocator below.
extern(C++, __gnu_cxx)
{
alias size_type = size_t;
static if (is(T : char))
void deallocate(T*, size_type) { }
else
void deallocate(T*, size_type);
struct new_allocator(T)
{
alias size_type = size_t;
static if (is(T : char))
void deallocate(T*, size_type) { }
else
void deallocate(T*, size_type);
}
}
}
}
extern (C++, std)
{
version (linux)
{
static if (__traits(getTargetInfo, "cppStd") >= 201703)
{
// std::allocator no longer derives from __gnu_cxx::new_allocator,
// it derives from std::__new_allocator instead.
struct __new_allocator(T)
{
alias size_type = size_t;
static if (is(T : char))
void deallocate(T*, size_type) { }
else
void deallocate(T*, size_type);
}
}
}
extern (C++, class) struct allocator(T)
{
version (linux)
{
alias size_type = size_t;
void deallocate(T* p, size_type sz)
{ (cast(__gnu_cxx.new_allocator!T*)&this).deallocate(p, sz); }
{
static if (__traits(getTargetInfo, "cppStd") >= 201703)
(cast(std.__new_allocator!T*)&this).deallocate(p, sz);
else
(cast(__gnu_cxx.new_allocator!T*)&this).deallocate(p, sz);
}
}
}
@ -476,12 +502,21 @@ extern (C++, std)
{
}
// https://gcc.gnu.org/onlinedocs/libstdc++/manual/using_dual_abi.html
version (none)
version (CppRuntime_Gcc)
{
extern (C++, __cxx11)
// https://gcc.gnu.org/onlinedocs/libstdc++/manual/using_dual_abi.html
static if (__traits(getTargetInfo, "cppStd") >= 201103)
{
struct basic_string(T, C = char_traits!T, A = allocator!T)
extern (C++, __cxx11)
{
struct basic_string(T, C = char_traits!T, A = allocator!T)
{
}
}
}
else
{
extern (C++, class) struct basic_string(T, C = char_traits!T, A = allocator!T)
{
}
}

View File

@ -1,36 +1,3 @@
/*
GCC 5.1 introduced new implementations of std::string and std::list:
https://gcc.gnu.org/onlinedocs/libstdc++/manual/using_dual_abi.html
This causes e.g. std::string to be actually defined as
std::__cxx11::string.
On machines with GCC 5.1, this manifests as a linker error when
running the cppa.d / cppb.cpp test:
cppa.o: In function `_D4cppa6test14FZv':
cppa.d:(.text._D4cppa6test14FZv+0x11): undefined reference to `foo14a(std::string*)'
cppa.d:(.text._D4cppa6test14FZv+0x18): undefined reference to `foo14b(std::basic_string<int, std::char_traits<int>, std::allocator<int> >*)'
cppa.d:(.text._D4cppa6test14FZv+0x3a): undefined reference to `foo14f(std::char_traits<char>*, std::string*, std::string*)'
cppa.o: In function `_D4cppa7testeh3FZv':
cppa.d:(.text._D4cppa7testeh3FZv+0x19): undefined reference to `throwle()'
collect2: error: ld returned 1 exit status
--- errorlevel 1
When the .cpp file is compiled with g++ 5.3.0, the actual function
signatures in the cppb.o object file are:
foo14a(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*)
foo14b(std::__cxx11::basic_string<int, std::char_traits<int>, std::allocator<int> >*)
foo14f(std::char_traits<char>*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*)
Fortunately, it is easily possible to disable the new feature
by defining _GLIBCXX_USE_CXX11_ABI as 0 before including any standard
headers.
*/
#define _GLIBCXX_USE_CXX11_ABI 0
#include <stdio.h>
#include <stdint.h>
#include <assert.h>

2
libphobos/configure vendored
View File

@ -15566,7 +15566,7 @@ SPEC_PHOBOS_DEPS="$LIBS"
# Libdruntime / phobos soname version
libtool_VERSION=2:0:0
libtool_VERSION=3:0:0
# Set default flags (after DRUNTIME_WERROR!)

View File

@ -265,7 +265,7 @@ SPEC_PHOBOS_DEPS="$LIBS"
AC_SUBST(SPEC_PHOBOS_DEPS)
# Libdruntime / phobos soname version
libtool_VERSION=2:0:0
libtool_VERSION=3:0:0
AC_SUBST(libtool_VERSION)
# Set default flags (after DRUNTIME_WERROR!)

View File

@ -1,4 +1,4 @@
bc58b1e9ea68051af9094651a26313371297b79f
6364e010bc87f3621028c8ac648133535c126fb3
The first line of this file holds the git revision number of the last
merge done from the dlang/druntime repository.

View File

@ -185,22 +185,38 @@ template dtorIsNothrow(T)
}
// taken from std.meta.allSatisfy
enum allSatisfy(alias pred, items...) =
template allSatisfy(alias F, T...)
{
static foreach (item; items)
static if (!pred!item)
if (__ctfe) return false;
return true;
}();
static foreach (Ti; T)
{
static if (!is(typeof(allSatisfy) == bool) && // not yet defined
!F!(Ti))
{
enum allSatisfy = false;
}
}
static if (!is(typeof(allSatisfy) == bool)) // if not yet defined
{
enum allSatisfy = true;
}
}
// taken from std.meta.anySatisfy
enum anySatisfy(alias pred, items...) =
template anySatisfy(alias F, Ts...)
{
static foreach (item; items)
static if (pred!item)
if (__ctfe) return true;
return false;
}();
static foreach (T; Ts)
{
static if (!is(typeof(anySatisfy) == bool) && // not yet defined
F!T)
{
enum anySatisfy = true;
}
}
static if (!is(typeof(anySatisfy) == bool)) // if not yet defined
{
enum anySatisfy = false;
}
}
// simplified from std.traits.maxAlignment
template maxAlignment(Ts...)

View File

@ -2111,9 +2111,6 @@ private T trustedMoveImpl(T)(return scope ref T source) @trusted
// target must be first-parameter, because in void-functions DMD + dip1000 allows it to take the place of a return-scope
private void moveEmplaceImpl(T)(scope ref T target, return scope ref T source)
{
import core.stdc.string : memcpy, memset;
import core.internal.traits;
// TODO: this assert pulls in half of phobos. we need to work out an alternative assert strategy.
// static if (!is(T == class) && hasAliasing!T) if (!__ctfe)
// {
@ -2124,11 +2121,16 @@ private void moveEmplaceImpl(T)(scope ref T target, return scope ref T source)
static if (is(T == struct))
{
import core.internal.traits;
// Unsafe when compiling without -preview=dip1000
assert((() @trusted => &source !is &target)(), "source and target must not be identical");
static if (hasElaborateAssign!T || !isAssignable!T)
{
import core.stdc.string : memcpy;
() @trusted { memcpy(&target, &source, T.sizeof); }();
}
else
target = source;
@ -2146,15 +2148,21 @@ private void moveEmplaceImpl(T)(scope ref T target, return scope ref T source)
enum sz = T.sizeof;
static if (__traits(isZeroInit, T))
{
import core.stdc.string : memset;
() @trusted { memset(&source, 0, sz); }();
}
else
{
import core.stdc.string : memcpy;
() @trusted { memcpy(&source, __traits(initSymbol, T).ptr, sz); }();
}
}
}
else static if (__traits(isStaticArray, T))
{
for (size_t i = 0; i < source.length; ++i)
move(source[i], target[i]);
moveEmplaceImpl(target[i], source[i]);
}
else
{
@ -2204,6 +2212,34 @@ pure nothrow @nogc @system unittest
assert(val == 0);
}
@betterC
pure nothrow @nogc @system unittest
{
static struct Foo
{
pure nothrow @nogc:
this(int* ptr) { _ptr = ptr; }
~this() { if (_ptr) ++*_ptr; }
int* _ptr;
}
int val;
{
Foo[1] foo1 = void; // uninitialized
Foo[1] foo2 = [Foo(&val)];// initialized
assert(foo2[0]._ptr is &val);
// Using `move(foo2, foo1)` would have an undefined effect because it would destroy
// the uninitialized foo1.
// moveEmplace directly overwrites foo1 without destroying or initializing it first.
moveEmplace(foo2, foo1);
assert(foo1[0]._ptr is &val);
assert(foo2[0]._ptr is null);
assert(val == 0);
}
assert(val == 1);
}
// issue 18913
@safe unittest
{
@ -2222,17 +2258,10 @@ pure nothrow @nogc @system unittest
f(move(ncarray));
}
/**
* This is called for a delete statement where the value
* being deleted is a pointer to a struct with a destructor
* but doesn't have an overloaded delete operator.
*
* Params:
* p = pointer to the value to be deleted
*/
void _d_delstruct(T)(ref T *p)
/// Implementation of `_d_delstruct` and `_d_delstructTrace`
template _d_delstructImpl(T)
{
if (p)
private void _d_delstructImpure(ref T p)
{
debug(PRINTF) printf("_d_delstruct(%p)\n", p);
@ -2242,21 +2271,61 @@ void _d_delstruct(T)(ref T *p)
GC.free(p);
p = null;
}
/**
* This is called for a delete statement where the value being deleted is a
* pointer to a struct with a destructor but doesn't have an overloaded
* `delete` operator.
*
* Params:
* p = pointer to the value to be deleted
*
* Bugs:
* This function template was ported from a much older runtime hook that
* bypassed safety, purity, and throwabilty checks. To prevent breaking
* existing code, this function template is temporarily declared
* `@trusted` until the implementation can be brought up to modern D
* expectations.
*/
void _d_delstruct(ref T p) @trusted @nogc pure nothrow
{
if (p)
{
alias Type = void function(ref T P) @nogc pure nothrow;
(cast(Type) &_d_delstructImpure)(p);
}
}
import core.internal.array.utils : _d_HookTraceImpl;
private enum errorMessage = "Cannot delete struct if compiling without support for runtime type information!";
/**
* TraceGC wrapper around $(REF _d_delstruct, core,lifetime,_d_delstructImpl).
*
* Bugs:
* This function template was ported from a much older runtime hook that
* bypassed safety, purity, and throwabilty checks. To prevent breaking
* existing code, this function template is temporarily declared
* `@trusted` until the implementation can be brought up to modern D
* expectations.
*/
alias _d_delstructTrace = _d_HookTraceImpl!(T, _d_delstruct, errorMessage);
}
@system unittest
@system pure nothrow unittest
{
int dtors = 0;
struct S { ~this() { ++dtors; } }
S *s = new S();
_d_delstruct(s);
_d_delstructImpl!(typeof(s))._d_delstruct(s);
assert(s == null);
assert(dtors == 1);
}
@system unittest
@system pure unittest
{
int innerDtors = 0;
int outerDtors = 0;
@ -2277,16 +2346,16 @@ void _d_delstruct(T)(ref T *p)
{
++outerDtors;
_d_delstruct(i1);
_d_delstructImpl!(typeof(i1))._d_delstruct(i1);
assert(i1 == null);
_d_delstruct(i2);
_d_delstructImpl!(typeof(i2))._d_delstruct(i2);
assert(i2 == null);
}
}
Outer *o = new Outer(0);
_d_delstruct(o);
_d_delstructImpl!(typeof(o))._d_delstruct(o);
assert(o == null);
assert(innerDtors == 2);

View File

@ -798,7 +798,7 @@ else static if (hasExecinfo) private class DefaultTraceInfo : Throwable.TraceInf
enum CALL_INSTRUCTION_SIZE = 1;
static if (__traits(compiles, backtrace((void**).init, int.init)))
numframes = backtrace(this.callstack.ptr, MAXFRAMES);
numframes = cast(int) backtrace(this.callstack.ptr, MAXFRAMES);
// Backtrace succeeded, adjust the frame to point to the caller
if (numframes >= 2)
foreach (ref elem; this.callstack)

View File

@ -11,137 +11,10 @@ module core.sys.openbsd.execinfo;
version (OpenBSD):
extern (C):
nothrow:
@nogc:
version (GNU)
version = BacktraceExternal;
version (BacktraceExternal)
{
size_t backtrace(void**, size_t);
char** backtrace_symbols(const(void*)*, size_t);
void backtrace_symbols_fd(const(void*)*, size_t, int);
char** backtrace_symbols_fmt(const(void*)*, size_t, const char*);
int backtrace_symbols_fd_fmt(const(void*)*, size_t, int, const char*);
}
else
{
import core.sys.openbsd.dlfcn;
// Use extern (D) so that these functions don't collide with libexecinfo.
extern (D) int backtrace(void** buffer, int size)
{
import core.thread : thread_stackBottom;
void** p, pend=cast(void**)thread_stackBottom();
version (D_InlineAsm_X86)
asm nothrow @trusted { mov p[EBP], EBP; }
else version (D_InlineAsm_X86_64)
asm nothrow @trusted { mov p[RBP], RBP; }
else
static assert(false, "Architecture not supported.");
int i;
for (; i < size && p < pend; ++i)
{
buffer[i] = *(p + 1);
auto pnext = cast(void**)*p;
if (pnext <= p) break;
p = pnext;
}
return i;
}
extern (D) char** backtrace_symbols(const(void*)* buffer, int size)
{
static void* realloc(void* p, size_t len) nothrow
{
static import cstdlib=core.stdc.stdlib;
auto res = cstdlib.realloc(p, len);
if (res is null) cstdlib.free(p);
return res;
}
if (size <= 0) return null;
size_t pos = size * (char*).sizeof;
char** p = cast(char**)realloc(null, pos);
if (p is null) return null;
Dl_info info;
foreach (i, addr; buffer[0 .. size])
{
if (dladdr(addr, &info) == 0)
(cast(ubyte*)&info)[0 .. info.sizeof] = 0;
fixupDLInfo(addr, info);
immutable len = formatStackFrame(null, 0, addr, info);
assert(len > 0);
p = cast(char**)realloc(p, pos + len);
if (p is null) return null;
formatStackFrame(cast(char*)p + pos, len, addr, info) == len || assert(0);
p[i] = cast(char*)pos;
pos += len;
}
foreach (i; 0 .. size)
{
pos = cast(size_t)p[i];
p[i] = cast(char*)p + pos;
}
return p;
}
extern (D) void backtrace_symbols_fd(const(void*)* buffer, int size, int fd)
{
import core.sys.posix.unistd : write;
import core.stdc.stdlib : alloca;
if (size <= 0) return;
Dl_info info;
foreach (i, addr; buffer[0 .. size])
{
if (dladdr(addr, &info) == 0)
(cast(ubyte*)&info)[0 .. info.sizeof] = 0;
fixupDLInfo(addr, info);
enum maxAlloca = 1024;
enum min = (size_t a, size_t b) => a <= b ? a : b;
immutable len = min(formatStackFrame(null, 0, addr, info), maxAlloca);
assert(len > 0);
auto p = cast(char*)alloca(len);
if (p is null) return;
formatStackFrame(p, len, addr, info) >= len || assert(0);
p[len - 1] = '\n';
write(fd, p, len);
}
}
private void fixupDLInfo(const(void)* addr, ref Dl_info info)
{
if (info.dli_fname is null) info.dli_fname = "???";
if (info.dli_fbase is null) info.dli_fbase = null;
if (info.dli_sname is null) info.dli_sname = "???";
if (info.dli_saddr is null) info.dli_saddr = cast(void*)addr;
}
private size_t formatStackFrame(char* p, size_t plen, const(void)* addr, const ref Dl_info info)
{
import core.stdc.stdio : snprintf;
immutable off = addr - info.dli_saddr;
immutable len = snprintf(p, plen, "%p <%s+%zd> at %s",
addr, info.dli_sname, off, info.dli_fname);
assert(len > 0);
return cast(size_t)len + 1; // + '\0'
}
}
size_t backtrace(void**, size_t);
char** backtrace_symbols(const(void*)*, size_t);
void backtrace_symbols_fd(const(void*)*, size_t, int);
char** backtrace_symbols_fmt(const(void*)*, size_t, const char*);
int backtrace_symbols_fd_fmt(const(void*)*, size_t, int, const char*);

View File

@ -340,26 +340,23 @@ version (CRuntime_Glibc)
}
c_long[14] st_pad5;
}
static if (!__USE_FILE_OFFSET64)
static assert(stat_t.sizeof == 144);
else
static assert(stat_t.sizeof == 160);
}
else version (MIPS64)
{
struct stat_t
{
c_ulong st_dev;
dev_t st_dev;
int[3] st_pad1;
static if (!__USE_FILE_OFFSET64)
{
ino_t st_ino;
}
else
{
c_ulong st_ino;
}
ino_t st_ino;
mode_t st_mode;
nlink_t st_nlink;
uid_t st_uid;
gid_t st_gid;
c_ulong st_rdev;
dev_t st_rdev;
static if (!__USE_FILE_OFFSET64)
{
uint[2] st_pad2;
@ -368,8 +365,8 @@ version (CRuntime_Glibc)
}
else
{
c_long[3] st_pad2;
c_long st_size;
uint[3] st_pad2;
off_t st_size;
}
static if (__USE_MISC || __USE_XOPEN2K8)
{
@ -394,15 +391,26 @@ version (CRuntime_Glibc)
}
blksize_t st_blksize;
uint st_pad4;
blkcnt_t st_blocks;
int[14] st_pad5;
}
version (MIPS_N32)
{
static if (!__USE_FILE_OFFSET64)
{
blkcnt_t st_blocks;
}
static assert(stat_t.sizeof == 160);
else
{
c_long st_blocks;
}
c_long[14] st_pad5;
static assert(stat_t.sizeof == 176);
}
else version (MIPS_O64)
{
static if (!__USE_FILE_OFFSET64)
static assert(stat_t.sizeof == 160);
else
static assert(stat_t.sizeof == 176);
}
else
{
static assert(stat_t.sizeof == 216);
}
}
else version (PPC)

View File

@ -4651,7 +4651,7 @@ public import core.internal.array.construction : _d_arrayctor;
public import core.internal.array.construction : _d_arraysetctor;
public import core.internal.array.capacity: _d_arraysetlengthTImpl;
public import core.lifetime : _d_delstruct;
public import core.lifetime : _d_delstructImpl;
public import core.internal.dassert: _d_assert_fail;

View File

@ -6,10 +6,6 @@
* Authors: Walter Bright, Sean Kelly, Martin Nowak
* Source: $(DRUNTIMESRC rt/_monitor_.d)
*/
/* NOTE: This file has been patched from the original DMD distribution to
* work with the GDC compiler.
*/
module rt.monitor_;
import core.atomic, core.stdc.stdlib, core.stdc.string;
@ -175,37 +171,7 @@ package:
alias IMonitor = Object.Monitor;
alias DEvent = void delegate(Object);
version (GNU)
{
import gcc.config;
static if (GNU_Thread_Model == ThreadModel.Single)
version = SingleThreaded;
// Ignore ThreadModel, we don't want posix threads on windows and
// will always use native threading instead.
}
version (SingleThreaded)
{
@nogc:
alias Mutex = int;
void initMutex(Mutex* mtx)
{
}
void destroyMutex(Mutex* mtx)
{
}
void lockMutex(Mutex* mtx)
{
}
void unlockMutex(Mutex* mtx)
{
}
}
else version (Windows)
version (Windows)
{
version (CRuntime_DigitalMars)
{

View File

@ -1,4 +1,4 @@
12329adb67fb43891d6e4e543e7257bc34db0aa7
575b67a9b4f78415f96ca77ad50b2de4c667cc74
The first line of this file holds the git revision number of the last
merge done from the dlang/phobos repository.

View File

@ -638,7 +638,7 @@ Returns:
*/
size_t count(alias pred = "a == b", Range, E)(Range haystack, E needle)
if (isInputRange!Range && !isInfinite!Range &&
is(typeof(binaryFun!pred(haystack.front, needle)) : bool))
is(typeof(binaryFun!pred(haystack.front, needle))))
{
bool pred2(ElementType!Range a) { return binaryFun!pred(a, needle); }
return count!pred2(haystack);
@ -693,7 +693,7 @@ if (isInputRange!Range && !isInfinite!Range &&
size_t count(alias pred = "a == b", R1, R2)(R1 haystack, R2 needle)
if (isForwardRange!R1 && !isInfinite!R1 &&
isForwardRange!R2 &&
is(typeof(binaryFun!pred(haystack.front, needle.front)) : bool))
is(typeof(binaryFun!pred(haystack.front, needle.front))))
{
assert(!needle.empty, "Cannot count occurrences of an empty range");
@ -716,7 +716,7 @@ if (isForwardRange!R1 && !isInfinite!R1 &&
/// Ditto
size_t count(alias pred, R)(R haystack)
if (isInputRange!R && !isInfinite!R &&
is(typeof(unaryFun!pred(haystack.front)) : bool))
is(typeof(unaryFun!pred(haystack.front))))
{
size_t result;
alias T = ElementType!R; //For narrow strings forces dchar iteration
@ -745,6 +745,12 @@ if (isInputRange!R && !isInfinite!R)
assert([1, 2, 3].count([2, 3]) == 1);
}
// https://issues.dlang.org/show_bug.cgi?id=22582
@safe unittest
{
assert([1, 2, 3].count!"a & 1" == 2);
}
/++
Counts elements in the given
$(REF_ALTTEXT forward range, isForwardRange, std,range,primitives)

View File

@ -2464,7 +2464,8 @@ public:
if (!tzName.extension().empty ||
!tzName.startsWith(subName) ||
baseName(tzName) == "leapseconds" ||
tzName == "+VERSION")
tzName == "+VERSION" ||
tzName == "SECURITY")
{
continue;
}

View File

@ -2738,7 +2738,7 @@ public:
immutable size_t nBytesNeeded = nWorkUnits * RTask.sizeof;
import core.stdc.stdlib : malloc, free;
if (nBytesNeeded < maxStack)
if (nBytesNeeded <= maxStack)
{
tasks = (cast(RTask*) buf.ptr)[0 .. nWorkUnits];
}
@ -3045,11 +3045,11 @@ public:
Since the underlying data for this struct is heap-allocated, this struct
has reference semantics when passed between functions.
The main uses cases for `WorkerLocalStorageStorage` are:
The main uses cases for `WorkerLocalStorage` are:
1. Performing parallel reductions with an imperative, as opposed to
functional, programming style. In this case, it's useful to treat
`WorkerLocalStorageStorage` as local to each thread for only the parallel
`WorkerLocalStorage` as local to each thread for only the parallel
portion of an algorithm.
2. Recycling temporary buffers across iterations of a parallel foreach loop.

View File

@ -70,7 +70,7 @@ $(TR $(TD Objects) $(TD
...
// multi-pattern regex
auto multi = regex([`\d+,\d+`,`(a-z]+):(\d+)`]);
auto multi = regex([`\d+,\d+`, `([a-z]+):(\d+)`]);
auto m = "abc:43 12,34".matchAll(multi);
assert(m.front.whichPattern == 2);
assert(m.front[1] == "abc");
@ -80,9 +80,17 @@ $(TR $(TD Objects) $(TD
assert(m.front[1] == "12");
...
// The result of the `matchAll/matchFirst` is directly testable with if/assert/while.
// e.g. test if a string consists of letters:
assert(matchFirst("Letter", `^\p{L}+$`));
// The result of `matchAll/matchFirst` is directly testable with `if/assert/while`,
// e.g. test if a string consists of letters only:
assert(matchFirst("LettersOnly", `^\p{L}+$`));
// And we can take advantage of the ability to define a variable in the $(LINK2 https://dlang.org/spec/statement.html#IfCondition `IfCondition`):
if (const auto captures = matchFirst("At l34st one digit, but maybe more...", `((\d)(\d*))`))
{
assert(captures[2] == "3");
assert(captures[3] == "4");
assert(captures[1] == "34");
}
---
$(SECTION Syntax and general information)

View File

@ -829,6 +829,10 @@ private template fqnType(T,
{
enum fqnType = "dstring";
}
else static if (is(T == typeof(null)))
{
enum fqnType = "typeof(null)";
}
else static if (isBasicType!T && !is(T == enum))
{
enum fqnType = chain!((Unqual!T).stringof);
@ -919,6 +923,7 @@ private template fqnType(T,
static assert(fqn!(string) == "string");
static assert(fqn!(wstring) == "wstring");
static assert(fqn!(dstring) == "dstring");
static assert(fqn!(typeof(null)) == "typeof(null)");
static assert(fqn!(void) == "void");
static assert(fqn!(const(void)) == "const(void)");
static assert(fqn!(shared(void)) == "shared(void)");

View File

@ -0,0 +1,24 @@
// https://issues.dlang.org/show_bug.cgi?id=22210
import core.internal.traits : allSatisfy;
enum isHashable(T) = __traits(compiles,
() { T.init; }
);
class A
{
static if (isHashable!B) {}
}
class B
{
static if (isHashable!C) {}
}
class C
{
static if (allSatisfy!(isHashable, int, B)) {}
}
void main() {}

View File

@ -0,0 +1,27 @@
# Copyright (C) 2021 Free Software Foundation, Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with GCC; see the file COPYING3. If not see
# <http://www.gnu.org/licenses/>.
# Initialize dg.
dg-init
# Gather a list of all tests.
set tests [lsort [find $srcdir/$subdir *.d]]
# Main loop.
dg-runtest $tests "" $DEFAULT_DFLAGS
# All done.
dg-finish