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;
-3982604c54e8770585985a33577fbf19b9b5c9ce
+93108bb9ea6216d67fa97bb4842fb59f26f6bfc7
The first line of this file holds the git revision number of the last
merge done from the dlang/dmd repository.
-v2.098.0
+v2.098.1-beta.1
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;
}
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())
{
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
{
/* 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_))
{
// 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));
}
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());
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);
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()
{
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
{
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)
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.
*/
// 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_)
{
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();
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;
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.
void deprecation(const char *format, ...);
bool checkDeprecated(const Loc &loc, Scope *sc);
Module *getModule();
+ bool isCsymbol();
Module *getAccessModule();
Dsymbol *pastMixin();
Dsymbol *toParent();
import dmd.globals;
import dmd.id;
import dmd.identifier;
+import dmd.importc;
import dmd.init;
import dmd.initsem;
import dmd.hdrgen;
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 &&
{
// 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());
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;
}
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());
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
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();
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());
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))
{
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.
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);
}
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;
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;
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;
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.
}
else if (t.isTypeFunction())
{
- e = e.addressOf();
+ e = new AddrExp(e.loc, e);
}
else
return e;
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;
+ }
+ }
+}
+
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.");
}
bool overflow = false;
bool anyBinaryDigitsNoSingleUS = false;
bool anyHexDigitsNoSingleUS = false;
+ char errorDigit = 0;
dchar c = *p;
if (c == '0')
{
case '8':
case '9':
- if (Ccompile)
- error("octal digit expected, not `%c`", c);
+ errorDigit = cast(char) c;
base = 8;
break;
case 'x':
// 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)
}
}
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");
{
// 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)
*/
/* 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;
+ }
}
}
}
import dmd.globals;
import dmd.init;
import dmd.mtype;
+import dmd.printast;
import dmd.root.ctfloat;
import dmd.sideeffect;
import dmd.tokens;
*/
Expression Expression_optimize(Expression e, int result, bool keepLvalue)
{
+ //printf("Expression_optimize() %s\n", e.toChars());
Expression ret = e;
void error()
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
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;
}
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);
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);
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());
{
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)
- {
- VarExp ve = cast(VarExp)e;
- VarDeclaration v = ve.var.isVarDeclaration();
- Type t = cs.exp.type.toBasetype();
- if (v && (t.isintegral() || t.ty == Tclass))
+ // 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())
+ {
+ 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())
- {
- 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;
- }
-
- /* 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)
+ VarExp ve = cast(VarExp)e;
+ VarDeclaration v = ve.var.isVarDeclaration();
+ Type t = cs.exp.type.toBasetype();
+ if (v && (t.isintegral() || t.ty == Tclass))
{
- if (scx.enclosing && scx.enclosing.sw == sw)
- continue;
- assert(scx.sw == sw);
+ /* 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())
+ {
+ cs.error("`case` variables have to be `const` or `immutable`");
+ }
- if (!scx.search(cs.exp.loc, v.ident, null))
+ if (sw.isFinal)
{
- cs.error("`case` variable `%s` declared at %s cannot be declared in `switch` body",
- v.toChars(), v.loc.toChars());
+ 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;
}
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());
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.
*/
rs.exp = null;
}
if (e0)
+ {
+ e0 = e0.optimize(WANTvalue);
e0 = checkGC(sc, e0);
+ }
}
if (rs.exp)
/// 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
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
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,
index,
is_,
- leftShift = 64,
+ leftShift,
rightShift,
leftShiftAssign,
rightShiftAssign,
preMinusMinus,
// Numeric literals
- int32Literal = 104,
+ int32Literal,
uns32Literal,
int64Literal,
uns64Literal,
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,
bool_,
// Aggregates
- struct_ = 151,
+ struct_,
class_,
interface_,
union_,
immutable_,
// Statements
- if_ = 181,
+ if_,
else_,
while_,
for_,
onScopeSuccess,
// Contracts
- invariant_ = 205,
+ invariant_,
// Testing
unittest_,
ref_,
macro_,
- parameters = 210,
+ parameters,
traits,
overloadSet,
pure_,
vector,
pound,
- interval = 229,
- voidExpression,
- cantExpression,
- showCtfeContext,
-
- objcClassReference,
- vectorArray,
-
arrow, // ->
colonColon, // ::
wchar_tLiteral,
- compoundLiteral, // ( type-name ) { initializer-list }
// C only keywords
inline,
// 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",
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",
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
hexadecimalString,
this_,
super_,
- halt,
tuple,
error,
vector,
pound,
- interval, // 229
- voidExpression,
- cantExpression,
- showCtfeContext,
-
- objcClassReference,
- vectorArray,
-
arrow, // ->
colonColon, // ::
wchar_tLiteral,
- compoundLiteral, // ( type-name ) { initializer-list }
// C only keywords
inline_,
}
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(
* 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)
{
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:
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);
}
{
//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));
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)
@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
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
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)
-{
- 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)
+version (CppMangle_MSVC)
{
- 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");
+ }
}
/****************************************/
assert(i == 8);
}
-version (Posix)
+version (CppMangle_Itanium)
{
static assert (getD.mangleof == "_Z4getDv");
static assert (D.bar.mangleof == "_ZN1D3barEiii");
assert(i == 8);
}
-version (Posix)
+version (CppMangle_Itanium)
{
static assert (callE.mangleof == "_Z5callEP1E");
static assert (E.bar.mangleof == "_ZN1E3barEiii");
foo4(null);
}
-version (Posix)
+version (CppMangle_Itanium)
{
static assert(foo4.mangleof == "_Z4foo4Pc");
}
assert(f.p == cast(void*)b);
}
-version (Posix)
+version (CppMangle_Itanium)
{
static assert(bar5.getFoo.mangleof == "_ZN4bar56getFooEi");
static assert (newBar.mangleof == "_Z6newBarv");
assert(f.d == 2.5);
}
-version (Posix)
+version (CppMangle_Itanium)
{
static assert (foo6.mangleof == "_Z4foo6v");
}
foo8(&c);
}
-version (Posix)
+version (CppMangle_Itanium)
{
static assert(foo8.mangleof == "_Z4foo8PKc");
}
foobar9(a, a);
}
-version (Posix)
+version (CppMangle_Itanium)
{
static assert(foobar9.mangleof == "_Z7foobar9P5elem9S0_");
}
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");
static void test11696d(Loc, Expression*, Expression*);
}
-version (Posix)
+version (CppMangle_Itanium)
{
static assert(CallExp.test11696a.mangleof == "_ZN7CallExp10test11696aE3LocP10ExpressionS2_");
static assert(CallExp.test11696b.mangleof == "_ZN7CallExp10test11696bE3LocP10ExpressionPS2_");
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");
}
}
-version (Posix)
+version (CppMangle_Itanium)
{
static assert(Struct7030.foo.mangleof == "_ZNK10Struct70303fooEi");
static assert(Struct7030.bar.mangleof == "_ZN10Struct70303barEi");
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_");
extern (C++) void test36(T36, T36*) { }
-version (Posix)
+version (CppMangle_Itanium)
{
static assert(test36.mangleof == "_Z6test36PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPiPS12_");
}
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");
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");
}
~this();
}
-version(Posix)
+version (CppMangle_Itanium)
{
static assert(Test14086.__ctor.mangleof == "_ZN9Test14086C1Ev");
static assert(Test14086.__dtor.mangleof == "_ZN9Test14086D1Ev");
static assert(Test14086_S.__ctor.mangleof == "_ZN11Test14086_SC1Ei");
static assert(Test14086_S.__dtor.mangleof == "_ZN11Test14086_SD1Ev");
}
-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)
+version (CppMangle_MSVC)
{
- 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");
+ }
}
/**************************************/
alias I = T18888!(arg!int);
}
-version(Posix)
+version (CppMangle_Itanium)
{
static assert(S18888!().I.fun.mangleof == "_ZN6T18888IS_IiEE3funEv");
}
-version(Win32)
-{
- static assert(S18888!().I.fun.mangleof == "?fun@?$T18888@U?$T18888@H@@@@QAEXXZ");
-}
-version(Win64)
+version (CppMangle_MSVC)
{
- 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");
+ }
}
/**************************************/
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");
+ }
}
/**************************************/
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");
+ }
}
/**************************************/
int opAssign(int);
}
-version (Posix)
+version (CppMangle_Itanium)
{
static assert(TestOperators.opUnary!"*".mangleof == "_ZN13TestOperatorsdeEv");
static assert(TestOperators.opUnary!"++".mangleof == "_ZN13TestOperatorsppEv");
static assert(TestOperators.opIndex.mangleof == "_ZN13TestOperatorsixEi");
static assert(TestOperators.opCall.mangleof == "_ZN13TestOperatorsclEif");
}
-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");
+version (CppMangle_MSVC)
+{
+ 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;
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");
// 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
/+
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 ==
// 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;
{
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");
// 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);
}
// https://github.com/dlang/dmd/pull/10021#discussion_r294095749
-version (Posix)
+version (CppMangle_Itanium)
{
extern(C++, "a", "b")
struct PR10021_Struct2
}
/// 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);
}
// https://issues.dlang.org/show_bug.cgi?id=20094
-version (Posix)
+version (CppMangle_Itanium)
{
extern(C++, "ns20094")
{
}
// https://issues.dlang.org/show_bug.cgi?id=20223
-version (Posix)
+version (CppMangle_Itanium)
{
extern(C++)
{
}
// 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
/**************************************/
-version (Posix)
+version (CppMangle_Itanium)
{
extern (C++) struct Loc2 {};
extern (C++) class FuncDeclaration
// 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 {}
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");
+ }
}
// 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")
{
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
{
--- /dev/null
+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");
+}
--- /dev/null
+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 {}
--- /dev/null
+enum E:char[4]{ str = "abcd" }
+enum x = {
+ int[char[4]] aa;
+ aa[E.str] = 1;
+ foreach(key,val; aa) {}
+ return aa["abcd"];
+}();
--- /dev/null
+// 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);
+ }
+}
--- /dev/null
+// 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();
+}
--- /dev/null
+// 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;
+}
--- /dev/null
+// 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");
/* 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`
---
*/
/*
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)`
---
*/
--- /dev/null
+/*
+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;
+}
--- /dev/null
+// 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;
+}
--- /dev/null
+// 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);
+}
--- /dev/null
+/++
+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 = { (){} };
+}
--- /dev/null
+//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)
+{
+
+}
--- /dev/null
+/++
+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;
+
+ }
+}
}
/************************************************/
+// 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()
{
test20400();
test21878();
test20133();
+ test22530();
printf("Success\n");
return 0;
--- /dev/null
+// 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();
+ }
+}
--- /dev/null
+/+
+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");
+}
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);
+ }
}
}
{
}
- // 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)
+ {
+ extern (C++, __cxx11)
+ {
+ struct basic_string(T, C = char_traits!T, A = allocator!T)
+ {
+ }
+ }
+ }
+ else
{
- struct basic_string(T, C = char_traits!T, A = allocator!T)
+ extern (C++, class) struct basic_string(T, C = char_traits!T, A = allocator!T)
{
}
}
-/*
-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>
# Libdruntime / phobos soname version
-libtool_VERSION=2:0:0
+libtool_VERSION=3:0:0
# Set default flags (after DRUNTIME_WERROR!)
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!)
-bc58b1e9ea68051af9094651a26313371297b79f
+6364e010bc87f3621028c8ac648133535c126fb3
The first line of this file holds the git revision number of the last
merge done from the dlang/druntime repository.
}
// 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...)
// 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)
// {
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;
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
{
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
{
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);
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;
{
++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);
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)
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*);
}
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;
}
else
{
- c_long[3] st_pad2;
- c_long st_size;
+ uint[3] st_pad2;
+ off_t st_size;
}
static if (__USE_MISC || __USE_XOPEN2K8)
{
}
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)
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;
* 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;
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)
{
-12329adb67fb43891d6e4e543e7257bc34db0aa7
+575b67a9b4f78415f96ca77ad50b2de4c667cc74
The first line of this file holds the git revision number of the last
merge done from the dlang/phobos repository.
*/
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);
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");
/// 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
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)
if (!tzName.extension().empty ||
!tzName.startsWith(subName) ||
baseName(tzName) == "leapseconds" ||
- tzName == "+VERSION")
+ tzName == "+VERSION" ||
+ tzName == "SECURITY")
{
continue;
}
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];
}
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.
...
// 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");
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)
{
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);
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)");
--- /dev/null
+// 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() {}
--- /dev/null
+# 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