mirror of
https://github.com/dlang/dmd.git
synced 2025-04-26 13:10:12 +03:00
Rebase stable6 (#16967)
* Document template instance duplication status as part of its field documentation. (#16643) * Fix Bugzilla 24599 - Wrongly elided TypeInfo emission (#15868) Reverting #14844, which caused such missing TypeInfos, *and* making sure the special TypeInfo members are fully analyzed and ready for codegen (otherwise hitting an assertion for the real-world project). * Reorganize backend build files to match target and make more similar per line (#16672) * Remove redundant suggestions on linker errors (#16711) * Fix bugzilla 24337 - Segfault when printing an int[] cast from a string (#16729) * Add BitFieldStyle.Gcc_Clang_ARM Required for 32-bit ARM, and non-Apple 64-bit ARM targets. The only difference to `Gcc_Clang` is that anonymous and 0-length bit-fields do contribute to the aggregate alignment. Caught by existing proper C interop tests in runnable_cxx/testbitfields.d on such targets. The hardcoded bad tests in runnable/{bitfieldsposix64.c,dbitfieldsposix64.d} however now fail after the fix, on such targets again. * [refactor to `TargetC.contributesToAggregateAlignment(BitFieldDeclaration)` hook] * Fix Bugzilla Issue 24687 - [REG2.110] Cannot cast string-imports to select overload anymore * Also make deprecationSupplemental adhere to error limit (#16779) Co-authored-by: Dennis Korpel <dennis@sarc.nl> * Fix bugzilla 24699 - [REG2.108] No short-circuit evaluation of mixing template bool argument * Fix bugzilla 24731 - IFTI cannot handle integer expressions (#16822) * Fix Bugzilla Issue 24760 - ICE on variadic after default argument * Fix bugzilla 24790 - -vcg-ast ICE on lowered assign exp (#16914) Co-authored-by: Dennis Korpel <dennis@sarc.nl> * Fix bugzilla 24764 - ICE when -vcg-ast prints imported invariant (#16917) Co-authored-by: Dennis Korpel <dennis@sarc.nl> * Fix bugzilla 24431 - dmd -vcg-ast crashes printing failed template in… (#16916) --------- Co-authored-by: Richard (Rikki) Andrew Cattermole <richard@cattermole.co.nz> Co-authored-by: Martin Kinkelin <kinke@users.noreply.github.com> Co-authored-by: Dennis <dkorpel@users.noreply.github.com> Co-authored-by: Martin Kinkelin <mkinkelin@symmetryinvestments.com> Co-authored-by: Martin Kinkelin <noone@nowhere.com> Co-authored-by: RazvanN7 <razvan.nitu1305@gmail.com> Co-authored-by: Dennis Korpel <dennis@sarc.nl> Co-authored-by: Dennis Korpel <dkorpel@gmail.com>
This commit is contained in:
parent
4c02e46b60
commit
57c5b071af
35 changed files with 361 additions and 148 deletions
|
@ -1581,10 +1581,12 @@ auto sourceFiles()
|
|||
cparse.d
|
||||
"),
|
||||
backendHeaders: fileArray(env["C"], "
|
||||
cc.d cdef.d cgcv.d code.d cv4.d dt.d el.d global.d
|
||||
obj.d oper.d rtlsym.d x86/code_x86.d iasm.d codebuilder.d
|
||||
ty.d type.d mach.d mscoff.d dwarf.d dwarf2.d x86/xmm.d
|
||||
dlist.d melf.d
|
||||
cc.d cdef.d cgcv.d code.d dt.d el.d global.d
|
||||
obj.d oper.d rtlsym.d iasm.d codebuilder.d
|
||||
ty.d type.d dlist.d
|
||||
dwarf.d dwarf2.d cv4.d
|
||||
melf.d mscoff.d mach.d
|
||||
x86/code_x86.d x86/xmm.d
|
||||
"),
|
||||
};
|
||||
foreach (member; __traits(allMembers, DmdSources))
|
||||
|
@ -1620,13 +1622,16 @@ auto sourceFiles()
|
|||
"),
|
||||
backend: fileArray(env["C"], "
|
||||
bcomplex.d evalu8.d divcoeff.d dvec.d go.d gsroa.d glocal.d gdag.d gother.d gflow.d
|
||||
dout.d inliner.d
|
||||
gloop.d cgelem.d cgcs.d ee.d x86/cod4.d x86/cod5.d eh.d x86/nteh.d blockopt.d mem.d cg.d x86/cgreg.d
|
||||
dtype.d debugprint.d fp.d symbol.d symtab.d elem.d dcode.d cgsched.d x86/cg87.d x86/cgxmm.d x86/cgcod.d x86/cod1.d x86/cod2.d
|
||||
x86/cod3.d cv8.d dcgcv.d pdata.d util2.d var.d backconfig.d drtlsym.d dwarfeh.d ptrntab.d
|
||||
dvarstats.d dwarfdbginf.d cgen.d goh.d barray.d cgcse.d elpicpie.d
|
||||
machobj.d elfobj.d mscoffobj.d filespec.d aarray.d x86/disasm86.d arm/disasmarm.d arm/instr.d
|
||||
arm/cod1.d arm/cod2.d arm/cod3.d arm/cod4.d
|
||||
dout.d inliner.d eh.d filespec.d aarray.d
|
||||
gloop.d cgelem.d cgcs.d ee.d blockopt.d mem.d cg.d
|
||||
dtype.d debugprint.d fp.d symbol.d symtab.d elem.d dcode.d cgsched.d
|
||||
pdata.d util2.d var.d backconfig.d drtlsym.d ptrntab.d
|
||||
dvarstats.d cgen.d goh.d barray.d cgcse.d elpicpie.d
|
||||
dwarfeh.d dwarfdbginf.d cv8.d dcgcv.d
|
||||
machobj.d elfobj.d mscoffobj.d
|
||||
x86/nteh.d x86/cgreg.d x86/cg87.d x86/cgxmm.d x86/disasm86.d
|
||||
x86/cgcod.d x86/cod1.d x86/cod2.d x86/cod3.d x86/cod4.d x86/cod5.d
|
||||
arm/disasmarm.d arm/instr.d arm/cod1.d arm/cod2.d arm/cod3.d arm/cod4.d
|
||||
"
|
||||
),
|
||||
};
|
||||
|
|
|
@ -705,7 +705,7 @@ MATCH implicitConvTo(Expression e, Type t)
|
|||
return MATCH.nomatch;
|
||||
m = MATCH.constant;
|
||||
}
|
||||
if (e.hexString && tn.isIntegral && (tn.size == e.sz || (!e.committed && (e.len % tn.size) == 0)))
|
||||
if (e.type != t && e.hexString && tn.isIntegral && (tn.size == e.sz || (!e.committed && (e.len % tn.size) == 0)))
|
||||
{
|
||||
m = MATCH.convert;
|
||||
return m;
|
||||
|
|
|
@ -1832,7 +1832,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
|
|||
{
|
||||
//printf("MixinDeclaration::compileIt(loc = %d) %s\n", cd.loc.linnum, cd.exp.toChars());
|
||||
OutBuffer buf;
|
||||
if (expressionsToString(buf, sc, cd.exps))
|
||||
if (expressionsToString(buf, sc, cd.exps, cd.loc, null, true))
|
||||
return null;
|
||||
|
||||
const errors = global.errors;
|
||||
|
@ -7113,12 +7113,19 @@ private extern(C++) class SetFieldOffsetVisitor : Visitor
|
|||
error(bfd.loc, "bit field width %d is larger than type", bfd.fieldWidth);
|
||||
|
||||
const style = target.c.bitFieldStyle;
|
||||
if (style != TargetC.BitFieldStyle.MS && style != TargetC.BitFieldStyle.Gcc_Clang)
|
||||
assert(0, "unsupported bit-field style");
|
||||
|
||||
const isMicrosoftStyle = style == TargetC.BitFieldStyle.MS;
|
||||
const contributesToAggregateAlignment = target.c.contributesToAggregateAlignment(bfd);
|
||||
|
||||
void startNewField()
|
||||
{
|
||||
if (log) printf("startNewField()\n");
|
||||
uint alignsize;
|
||||
if (style == TargetC.BitFieldStyle.Gcc_Clang)
|
||||
if (isMicrosoftStyle)
|
||||
alignsize = memsize; // not memalignsize
|
||||
else
|
||||
{
|
||||
if (bfd.fieldWidth > 32)
|
||||
alignsize = memalignsize;
|
||||
|
@ -7129,15 +7136,13 @@ private extern(C++) class SetFieldOffsetVisitor : Visitor
|
|||
else
|
||||
alignsize = 1;
|
||||
}
|
||||
else
|
||||
alignsize = memsize; // not memalignsize
|
||||
|
||||
uint dummy;
|
||||
bfd.offset = placeField(bfd.loc,
|
||||
fieldState.offset,
|
||||
memsize, alignsize, bfd.alignment,
|
||||
ad.structsize,
|
||||
(anon && style == TargetC.BitFieldStyle.Gcc_Clang) ? dummy : ad.alignsize,
|
||||
contributesToAggregateAlignment ? ad.alignsize : dummy,
|
||||
isunion);
|
||||
|
||||
fieldState.inFlight = true;
|
||||
|
@ -7146,45 +7151,30 @@ private extern(C++) class SetFieldOffsetVisitor : Visitor
|
|||
fieldState.fieldSize = memsize;
|
||||
}
|
||||
|
||||
if (style == TargetC.BitFieldStyle.Gcc_Clang)
|
||||
{
|
||||
if (bfd.fieldWidth == 0)
|
||||
{
|
||||
if (!isunion)
|
||||
{
|
||||
// Use type of zero width field to align to next field
|
||||
fieldState.offset = (fieldState.offset + memalignsize - 1) & ~(memalignsize - 1);
|
||||
ad.structsize = fieldState.offset;
|
||||
}
|
||||
if (ad.alignsize == 0)
|
||||
ad.alignsize = 1;
|
||||
if (!isMicrosoftStyle && contributesToAggregateAlignment && ad.alignsize < memalignsize)
|
||||
ad.alignsize = memalignsize;
|
||||
|
||||
fieldState.inFlight = false;
|
||||
return;
|
||||
if (bfd.fieldWidth == 0)
|
||||
{
|
||||
if (!isMicrosoftStyle && !isunion)
|
||||
{
|
||||
// Use type of zero width field to align to next field
|
||||
fieldState.offset = (fieldState.offset + memalignsize - 1) & ~(memalignsize - 1);
|
||||
ad.structsize = fieldState.offset;
|
||||
}
|
||||
else if (isMicrosoftStyle && fieldState.inFlight && !isunion)
|
||||
{
|
||||
// documentation says align to next int
|
||||
//const alsz = cast(uint)Type.tint32.size();
|
||||
const alsz = memsize; // but it really does this
|
||||
fieldState.offset = (fieldState.offset + alsz - 1) & ~(alsz - 1);
|
||||
ad.structsize = fieldState.offset;
|
||||
}
|
||||
|
||||
if (ad.alignsize == 0)
|
||||
ad.alignsize = 1;
|
||||
if (!anon &&
|
||||
ad.alignsize < memalignsize)
|
||||
ad.alignsize = memalignsize;
|
||||
}
|
||||
else if (style == TargetC.BitFieldStyle.MS)
|
||||
{
|
||||
if (ad.alignsize == 0)
|
||||
ad.alignsize = 1;
|
||||
if (bfd.fieldWidth == 0)
|
||||
{
|
||||
if (fieldState.inFlight && !isunion)
|
||||
{
|
||||
// documentation says align to next int
|
||||
//const alsz = cast(uint)Type.tint32.size();
|
||||
const alsz = memsize; // but it really does this
|
||||
fieldState.offset = (fieldState.offset + alsz - 1) & ~(alsz - 1);
|
||||
ad.structsize = fieldState.offset;
|
||||
}
|
||||
|
||||
fieldState.inFlight = false;
|
||||
return;
|
||||
}
|
||||
fieldState.inFlight = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!fieldState.inFlight)
|
||||
|
@ -7192,7 +7182,7 @@ private extern(C++) class SetFieldOffsetVisitor : Visitor
|
|||
//printf("not in flight\n");
|
||||
startNewField();
|
||||
}
|
||||
else if (style == TargetC.BitFieldStyle.Gcc_Clang)
|
||||
else if (!isMicrosoftStyle)
|
||||
{
|
||||
// If the bit-field spans more units of alignment than its type
|
||||
// and is at the alignment boundary, start a new field at the
|
||||
|
@ -7217,7 +7207,7 @@ private extern(C++) class SetFieldOffsetVisitor : Visitor
|
|||
}
|
||||
}
|
||||
}
|
||||
else if (style == TargetC.BitFieldStyle.MS)
|
||||
else
|
||||
{
|
||||
if (memsize != fieldState.fieldSize ||
|
||||
fieldState.bitOffset + bfd.fieldWidth > fieldState.fieldSize * 8)
|
||||
|
@ -7226,14 +7216,14 @@ private extern(C++) class SetFieldOffsetVisitor : Visitor
|
|||
startNewField();
|
||||
}
|
||||
}
|
||||
else
|
||||
assert(0);
|
||||
|
||||
bfd.offset = fieldState.fieldOffset;
|
||||
bfd.bitOffset = fieldState.bitOffset;
|
||||
|
||||
const pastField = bfd.bitOffset + bfd.fieldWidth;
|
||||
if (style == TargetC.BitFieldStyle.Gcc_Clang)
|
||||
if (isMicrosoftStyle)
|
||||
fieldState.fieldSize = memsize;
|
||||
else
|
||||
{
|
||||
auto size = (pastField + 7) / 8;
|
||||
fieldState.fieldSize = size;
|
||||
|
@ -7247,8 +7237,6 @@ private extern(C++) class SetFieldOffsetVisitor : Visitor
|
|||
else
|
||||
ad.structsize = bfd.offset + size;
|
||||
}
|
||||
else
|
||||
fieldState.fieldSize = memsize;
|
||||
//printf("at end: ad.structsize = %d\n", cast(int)ad.structsize);
|
||||
//print(fieldState);
|
||||
|
||||
|
|
|
@ -1695,7 +1695,9 @@ MATCH deduceType(RootObject o, Scope* sc, Type tparam, ref TemplateParameters pa
|
|||
edim = s ? getValue(s) : getValue(e);
|
||||
}
|
||||
}
|
||||
if (tp && tp.matchArg(sc, t.dim, i, ¶meters, dedtypes, null) || edim && edim.toInteger() == t.dim.toInteger())
|
||||
if ((tp && tp.matchArg(sc, t.dim, i, ¶meters, dedtypes, null)) ||
|
||||
(edim && edim.isIntegerExp() && edim.toInteger() == t.dim.toInteger())
|
||||
)
|
||||
{
|
||||
result = deduceType(t.next, sc, tparam.nextOf(), parameters, dedtypes, wm);
|
||||
return;
|
||||
|
@ -3653,7 +3655,22 @@ extern (C++) class TemplateInstance : ScopeDsymbol
|
|||
Dsymbol tempdecl; // referenced by foo.bar.abc
|
||||
Dsymbol enclosing; // if referencing local symbols, this is the context
|
||||
Dsymbol aliasdecl; // !=null if instance is an alias for its sole member
|
||||
TemplateInstance inst; // refer to existing instance
|
||||
|
||||
/**
|
||||
If this is not null and it has a value that is not the current object,
|
||||
then this field points to an existing template instance
|
||||
and that object has been duplicated into us.
|
||||
|
||||
If this object is a duplicate,
|
||||
the ``memberOf`` field will be set to a root module (passed on CLI).
|
||||
|
||||
This information is useful to deduplicate analysis that may occur
|
||||
after semantic 3 has completed.
|
||||
|
||||
See_Also: memberOf
|
||||
*/
|
||||
TemplateInstance inst;
|
||||
|
||||
ScopeDsymbol argsym; // argument symbol table
|
||||
size_t hash; // cached result of toHash()
|
||||
|
||||
|
@ -3665,7 +3682,15 @@ extern (C++) class TemplateInstance : ScopeDsymbol
|
|||
|
||||
TemplateInstances* deferred;
|
||||
|
||||
Module memberOf; // if !null, then this TemplateInstance appears in memberOf.members[]
|
||||
/**
|
||||
If this is not null then this template instance appears in a root module's members.
|
||||
|
||||
Note: This is not useful for determining duplication status of this template instance.
|
||||
Use the field ``inst`` for determining if a template instance has been duplicated into this object.
|
||||
|
||||
See_Also: inst
|
||||
*/
|
||||
Module memberOf;
|
||||
|
||||
// Used to determine the instance needs code generation.
|
||||
// Note that these are inaccurate until semantic analysis phase completed.
|
||||
|
@ -4482,9 +4507,13 @@ extern (C++) class TemplateInstance : ScopeDsymbol
|
|||
|
||||
// The arguments are not treated as part of a default argument,
|
||||
// because they are evaluated at compile time.
|
||||
const inCondition = sc.condition;
|
||||
sc = sc.push();
|
||||
sc.inDefaultArg = false;
|
||||
|
||||
// https://issues.dlang.org/show_bug.cgi?id=24699
|
||||
sc.condition = inCondition;
|
||||
|
||||
for (size_t j = 0; j < tiargs.length; j++)
|
||||
{
|
||||
RootObject o = (*tiargs)[j];
|
||||
|
|
|
@ -570,8 +570,11 @@ extern (C++) void verrorReportSupplemental(const ref Loc loc, const(char)* forma
|
|||
goto case ErrorKind.error;
|
||||
else if (global.params.useDeprecated == DiagnosticReporting.inform && !global.gag)
|
||||
{
|
||||
info.headerColor = Classification.deprecation;
|
||||
verrorPrint(format, ap, info);
|
||||
if (global.params.v.errorLimit == 0 || global.deprecations <= global.params.v.errorLimit)
|
||||
{
|
||||
info.headerColor = Classification.deprecation;
|
||||
verrorPrint(format, ap, info);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
|
|
|
@ -455,7 +455,7 @@ extern (C++) abstract class Expression : ASTNode
|
|||
dinteger_t toInteger()
|
||||
{
|
||||
//printf("Expression %s\n", EXPtoString(op).ptr);
|
||||
if (!type.isTypeError())
|
||||
if (!type || !type.isTypeError())
|
||||
error(loc, "integer constant expression expected instead of `%s`", toChars());
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -140,16 +140,26 @@ private bool isNeedThisScope(Scope* sc, Declaration d)
|
|||
* buf = append generated string to buffer
|
||||
* sc = context
|
||||
* exps = array of Expressions
|
||||
* loc = location of the pragma / mixin where this conversion was requested, for supplemental error
|
||||
* fmt = format string for supplemental error. May contain 1 `%s` which prints the faulty expression
|
||||
* expandTuples = whether tuples should be expanded rather than printed as tuple syntax
|
||||
* Returns:
|
||||
* true on error
|
||||
*/
|
||||
bool expressionsToString(ref OutBuffer buf, Scope* sc, Expressions* exps)
|
||||
bool expressionsToString(ref OutBuffer buf, Scope* sc, Expressions* exps,
|
||||
Loc loc, const(char)* fmt, bool expandTuples)
|
||||
{
|
||||
if (!exps)
|
||||
return false;
|
||||
|
||||
foreach (ex; *exps)
|
||||
{
|
||||
bool error()
|
||||
{
|
||||
if (loc != Loc.initial && fmt)
|
||||
errorSupplemental(loc, fmt, ex.toChars());
|
||||
return true;
|
||||
}
|
||||
if (!ex)
|
||||
continue;
|
||||
auto sc2 = sc.startCTFE();
|
||||
|
@ -162,15 +172,16 @@ bool expressionsToString(ref OutBuffer buf, Scope* sc, Expressions* exps)
|
|||
// allowed to contain types as well as expressions
|
||||
auto e4 = ctfeInterpretForPragmaMsg(e3);
|
||||
if (!e4 || e4.op == EXP.error)
|
||||
return true;
|
||||
return error();
|
||||
|
||||
// expand tuple
|
||||
if (auto te = e4.isTupleExp())
|
||||
{
|
||||
if (expressionsToString(buf, sc, te.exps))
|
||||
return true;
|
||||
continue;
|
||||
}
|
||||
if (expandTuples)
|
||||
if (auto te = e4.isTupleExp())
|
||||
{
|
||||
if (expressionsToString(buf, sc, te.exps, loc, fmt, true))
|
||||
return error();
|
||||
continue;
|
||||
}
|
||||
// char literals exp `.toStringExp` return `null` but we cant override it
|
||||
// because in most contexts we don't want the conversion to succeed.
|
||||
IntegerExp ie = e4.isIntegerExp();
|
||||
|
@ -181,9 +192,11 @@ bool expressionsToString(ref OutBuffer buf, Scope* sc, Expressions* exps)
|
|||
e4 = new ArrayLiteralExp(ex.loc, tsa, ie);
|
||||
}
|
||||
|
||||
if (StringExp se = e4.toStringExp())
|
||||
StringExp se = e4.toStringExp();
|
||||
|
||||
if (se && se.type.nextOf().ty.isSomeChar)
|
||||
buf.writestring(se.toUTF8(sc).peekString());
|
||||
else
|
||||
else if (!(se && se.len == 0)) // don't print empty array literal `[]`
|
||||
buf.writestring(e4.toString());
|
||||
}
|
||||
return false;
|
||||
|
@ -336,6 +349,7 @@ StringExp toUTF8(StringExp se, Scope* sc)
|
|||
Expression e = castTo(se, sc, Type.tchar.arrayOf());
|
||||
e = e.optimize(WANTvalue);
|
||||
auto result = e.isStringExp();
|
||||
assert(result);
|
||||
assert(result.sz == 1);
|
||||
return result;
|
||||
}
|
||||
|
@ -7194,17 +7208,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
|
|||
// Handle this in the glue layer
|
||||
Expression e = new TypeidExp(exp.loc, ta);
|
||||
|
||||
bool genObjCode = true;
|
||||
|
||||
// https://issues.dlang.org/show_bug.cgi?id=23650
|
||||
// We generate object code for typeinfo, required
|
||||
// by typeid, only if in non-speculative context
|
||||
if (sc.traitsCompiles)
|
||||
{
|
||||
genObjCode = false;
|
||||
}
|
||||
|
||||
e.type = getTypeInfoType(exp.loc, ta, sc, genObjCode);
|
||||
e.type = getTypeInfoType(exp.loc, ta, sc);
|
||||
semanticTypeInfo(sc, ta);
|
||||
|
||||
if (ea)
|
||||
|
@ -7704,7 +7708,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
|
|||
private Expression compileIt(MixinExp exp, Scope *sc)
|
||||
{
|
||||
OutBuffer buf;
|
||||
if (expressionsToString(buf, sc, exp.exps))
|
||||
if (expressionsToString(buf, sc, exp.exps, exp.loc, null, true))
|
||||
return null;
|
||||
|
||||
uint errors = global.errors;
|
||||
|
|
|
@ -5904,6 +5904,7 @@ struct TargetC final
|
|||
uint8_t wchar_tsize;
|
||||
Runtime runtime;
|
||||
BitFieldStyle bitFieldStyle;
|
||||
bool contributesToAggregateAlignment(BitFieldDeclaration* bfd);
|
||||
TargetC() :
|
||||
crtDestructorsSupported(true),
|
||||
boolsize(),
|
||||
|
@ -7596,7 +7597,7 @@ public:
|
|||
|
||||
extern Target target;
|
||||
|
||||
extern Type* getTypeInfoType(const Loc& loc, Type* t, Scope* sc, bool genObjCode = true);
|
||||
extern Type* getTypeInfoType(const Loc& loc, Type* t, Scope* sc);
|
||||
|
||||
class SemanticTimeTransitiveVisitor : public SemanticTimePermissiveVisitor
|
||||
{
|
||||
|
|
|
@ -1720,10 +1720,10 @@ void toCBuffer(Dsymbol s, ref OutBuffer buf, ref HdrGenState hgs)
|
|||
//printf("FuncDeclaration::toCBuffer() '%s'\n", f.toChars());
|
||||
if (stcToBuffer(buf, f.storage_class))
|
||||
buf.writeByte(' ');
|
||||
typeToBuffer(f.type, f.ident, buf, hgs);
|
||||
auto tf = f.type.isTypeFunction();
|
||||
typeToBuffer(tf, f.ident, buf, hgs);
|
||||
|
||||
if (hgs.hdrgen)
|
||||
if (hgs.hdrgen && tf)
|
||||
{
|
||||
// if the return type is missing (e.g. ref functions or auto)
|
||||
// https://issues.dlang.org/show_bug.cgi?id=20090
|
||||
|
@ -1858,9 +1858,9 @@ void toCBuffer(Dsymbol s, ref OutBuffer buf, ref HdrGenState hgs)
|
|||
if (stcToBuffer(buf, d.storage_class))
|
||||
buf.writeByte(' ');
|
||||
buf.writestring("invariant");
|
||||
if(auto es = d.fbody.isExpStatement())
|
||||
auto es = d.fbody.isExpStatement();
|
||||
if (es && es.exp && es.exp.op == EXP.assert_)
|
||||
{
|
||||
assert(es.exp && es.exp.op == EXP.assert_);
|
||||
buf.writestring(" (");
|
||||
(cast(AssertExp)es.exp).e1.expressionToBuffer(buf, hgs);
|
||||
buf.writestring(");");
|
||||
|
|
|
@ -1426,8 +1426,8 @@ void parseLinkerOutput(const(char)[] linkerOutput, ErrorSink eSink)
|
|||
return s;
|
||||
}
|
||||
|
||||
bool missingSymbols = false;
|
||||
bool missingDfunction = false;
|
||||
bool missingCSymbols = false;
|
||||
bool missingDsymbols = false;
|
||||
bool missingMain = false;
|
||||
|
||||
void missingSymbol(const(char)[] name, const(char)[] referencedFrom)
|
||||
|
@ -1437,11 +1437,12 @@ void parseLinkerOutput(const(char)[] linkerOutput, ErrorSink eSink)
|
|||
name = name[1 .. $]; // MS LINK prepends underscore to the existing one
|
||||
auto sym = demangle(name);
|
||||
|
||||
missingSymbols = true;
|
||||
if (sym == "main")
|
||||
missingMain = true;
|
||||
if (sym != name)
|
||||
missingDfunction = true;
|
||||
else if (sym != name)
|
||||
missingDsymbols = true;
|
||||
else
|
||||
missingCSymbols = true;
|
||||
|
||||
eSink.error(Loc.initial, "undefined reference to `%.*s`", cast(int) sym.length, sym.ptr);
|
||||
if (referencedFrom.length > 0)
|
||||
|
@ -1513,10 +1514,9 @@ void parseLinkerOutput(const(char)[] linkerOutput, ErrorSink eSink)
|
|||
|
||||
if (missingMain)
|
||||
eSink.errorSupplemental(Loc.initial, "perhaps define a `void main() {}` function or use the `-main` switch");
|
||||
|
||||
if (missingDfunction)
|
||||
else if (missingDsymbols)
|
||||
eSink.errorSupplemental(Loc.initial, "perhaps `.d` files need to be added on the command line, or use `-i` to compile imports");
|
||||
else if (missingSymbols)
|
||||
else if (missingCSymbols)
|
||||
eSink.errorSupplemental(Loc.initial, "perhaps a library needs to be added with the `-L` flag or `pragma(lib, ...)`");
|
||||
}
|
||||
|
||||
|
|
|
@ -9774,6 +9774,7 @@ immutable PREC[EXP.max + 1] precedence =
|
|||
EXP.assign : PREC.assign,
|
||||
EXP.construct : PREC.assign,
|
||||
EXP.blit : PREC.assign,
|
||||
EXP.loweredAssignExp : PREC.assign,
|
||||
EXP.addAssign : PREC.assign,
|
||||
EXP.minAssign : PREC.assign,
|
||||
EXP.concatenateAssign : PREC.assign,
|
||||
|
|
|
@ -557,32 +557,19 @@ private uint setMangleOverride(Dsymbol s, const(char)[] sym)
|
|||
private bool pragmaMsgSemantic(Loc loc, Scope* sc, Expressions* args)
|
||||
{
|
||||
import dmd.tokens;
|
||||
import dmd.common.outbuffer;
|
||||
|
||||
if (!args)
|
||||
return true;
|
||||
foreach (arg; *args)
|
||||
{
|
||||
sc = sc.startCTFE();
|
||||
auto e = arg.expressionSemantic(sc);
|
||||
e = resolveProperties(sc, e);
|
||||
sc = sc.endCTFE();
|
||||
|
||||
// pragma(msg) is allowed to contain types as well as expressions
|
||||
e = ctfeInterpretForPragmaMsg(e);
|
||||
if (e.op == EXP.error)
|
||||
{
|
||||
errorSupplemental(loc, "while evaluating `pragma(msg, %s)`", arg.toChars());
|
||||
return false;
|
||||
}
|
||||
if (auto se = e.toStringExp())
|
||||
{
|
||||
const slice = se.toUTF8(sc).peekString();
|
||||
fprintf(stderr, "%.*s", cast(int)slice.length, slice.ptr);
|
||||
}
|
||||
else
|
||||
fprintf(stderr, "%s", e.toChars());
|
||||
OutBuffer buf;
|
||||
if (expressionsToString(buf, sc, args, loc, "while evaluating `pragma(msg, %s)`", false))
|
||||
return false;
|
||||
else
|
||||
{
|
||||
buf.writestring("\n");
|
||||
fprintf(stderr, buf.extractChars);
|
||||
}
|
||||
fprintf(stderr, "\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -4803,7 +4803,7 @@ private Statements* flatten(Statement statement, Scope* sc)
|
|||
|
||||
|
||||
OutBuffer buf;
|
||||
if (expressionsToString(buf, sc, cs.exps))
|
||||
if (expressionsToString(buf, sc, cs.exps, cs.loc, null, true))
|
||||
return errorStatements();
|
||||
|
||||
const errors = global.errors;
|
||||
|
|
|
@ -1373,6 +1373,8 @@ extern (C++) struct Target
|
|||
*/
|
||||
struct TargetC
|
||||
{
|
||||
import dmd.declaration : BitFieldDeclaration;
|
||||
|
||||
enum Runtime : ubyte
|
||||
{
|
||||
Unspecified,
|
||||
|
@ -1462,6 +1464,24 @@ struct TargetC
|
|||
crtDestructorsSupported = false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether the specified bit-field contributes to the alignment
|
||||
* of the containing aggregate.
|
||||
* E.g., (not all) ARM ABIs do NOT ignore anonymous (incl. 0-length)
|
||||
* bit-fields.
|
||||
*/
|
||||
extern (C++) bool contributesToAggregateAlignment(BitFieldDeclaration bfd)
|
||||
{
|
||||
if (bitFieldStyle == BitFieldStyle.MS)
|
||||
return true;
|
||||
if (bitFieldStyle == BitFieldStyle.Gcc_Clang)
|
||||
{
|
||||
// sufficient for DMD's currently supported architectures
|
||||
return !bfd.isAnonymous();
|
||||
}
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include "globals.h"
|
||||
#include "tokens.h"
|
||||
|
||||
class BitFieldDeclaration;
|
||||
class ClassDeclaration;
|
||||
class Dsymbol;
|
||||
class Expression;
|
||||
|
@ -77,6 +78,8 @@ struct TargetC
|
|||
uint8_t wchar_tsize; // size of a C 'wchar_t' type
|
||||
Runtime runtime;
|
||||
BitFieldStyle bitFieldStyle; // different C compilers do it differently
|
||||
|
||||
bool contributesToAggregateAlignment(BitFieldDeclaration *bfd);
|
||||
};
|
||||
|
||||
struct TargetCPP
|
||||
|
|
|
@ -1441,6 +1441,13 @@ private extern (C++) class TypeInfoDtVisitor : Visitor
|
|||
/* ti.toObjFile() won't get called. So, store these
|
||||
* member functions into object file in here.
|
||||
*/
|
||||
|
||||
if (sd.semanticRun < PASS.semantic3done)
|
||||
{
|
||||
import dmd.semantic3 : semanticTypeInfoMembers;
|
||||
semanticTypeInfoMembers(sd);
|
||||
}
|
||||
|
||||
if (sd.xeq && sd.xeq != StructDeclaration.xerreq)
|
||||
toObjFile(sd.xeq, global.params.multiobj);
|
||||
if (sd.xcmp && sd.xcmp != StructDeclaration.xerrcmp)
|
||||
|
|
|
@ -836,7 +836,9 @@ extern (D) MATCH callMatch(TypeFunction tf, Type tthis, ArgumentList argumentLis
|
|||
L1:
|
||||
if (parameterList.varargs == VarArg.typesafe && u + 1 == nparams) // if last varargs param
|
||||
{
|
||||
auto trailingArgs = args[u .. $];
|
||||
Expression[] trailingArgs;
|
||||
if (args.length >= u)
|
||||
trailingArgs = args[u .. $];
|
||||
if (auto vmatch = matchTypeSafeVarArgs(tf, p, trailingArgs, pMessage))
|
||||
return vmatch < match ? vmatch : match;
|
||||
// Error message was already generated in `matchTypeSafeVarArgs`
|
||||
|
@ -7853,7 +7855,7 @@ Expression getMaxMinValue(EnumDeclaration ed, const ref Loc loc, Identifier id)
|
|||
RootObject compileTypeMixin(TypeMixin tm, ref const Loc loc, Scope* sc)
|
||||
{
|
||||
OutBuffer buf;
|
||||
if (expressionsToString(buf, sc, tm.exps))
|
||||
if (expressionsToString(buf, sc, tm.exps, tm.loc, null, true))
|
||||
return null;
|
||||
|
||||
const errors = global.errors;
|
||||
|
|
|
@ -100,14 +100,13 @@ bool genTypeInfo(Expression e, const ref Loc loc, Type torig, Scope* sc)
|
|||
* loc = the location for reporting line nunbers in errors
|
||||
* t = the type to get the type of the `TypeInfo` object for
|
||||
* sc = the scope
|
||||
* genObjCode = if true, object code will be generated for the obtained TypeInfo
|
||||
* Returns:
|
||||
* The type of the `TypeInfo` object associated with `t`
|
||||
*/
|
||||
extern (C++) Type getTypeInfoType(const ref Loc loc, Type t, Scope* sc, bool genObjCode = true)
|
||||
extern (C++) Type getTypeInfoType(const ref Loc loc, Type t, Scope* sc)
|
||||
{
|
||||
assert(t.ty != Terror);
|
||||
if (genTypeInfo(null, loc, t, sc) && genObjCode)
|
||||
if (genTypeInfo(null, loc, t, sc))
|
||||
{
|
||||
// Find module that will go all the way to an object file
|
||||
Module m = sc._module.importedFrom;
|
||||
|
|
|
@ -22,4 +22,4 @@ namespace dmd
|
|||
bool isSpeculativeType(Type *t);
|
||||
bool builtinTypeInfo(Type *t);
|
||||
}
|
||||
Type *getTypeInfoType(const Loc &loc, Type *t, Scope *sc, bool genObjCode = true);
|
||||
Type *getTypeInfoType(const Loc &loc, Type *t, Scope *sc);
|
||||
|
|
|
@ -1865,7 +1865,7 @@ void template_h(TemplateParameter *tp, Scope *sc, TemplateParameters *tps,
|
|||
void typinf_h(Expression *e, const Loc &loc, Type *t, Scope *sc)
|
||||
{
|
||||
dmd::genTypeInfo(e, loc, t, sc);
|
||||
::getTypeInfoType(loc, t, sc, false);
|
||||
::getTypeInfoType(loc, t, sc);
|
||||
dmd::isSpeculativeType(t);
|
||||
dmd::builtinTypeInfo(t);
|
||||
}
|
||||
|
|
|
@ -623,6 +623,11 @@ static assert (__traits(compiles, false && error) == false);
|
|||
int f11042a3()() if (__traits(compiles, true || error) == false) { return 0; } enum x11042a3 = f11042a3();
|
||||
int f11042b3()() if (__traits(compiles, false && error) == false) { return 0; } enum x11042b3 = f11042b3();
|
||||
|
||||
// https://issues.dlang.org/show_bug.cgi?id=24699
|
||||
enum T24699(bool cond) = cond;
|
||||
enum b24699a = T24699!(true || error);
|
||||
enum b24699b = T24699!(false && error);
|
||||
|
||||
/***************************************************/
|
||||
// https://issues.dlang.org/show_bug.cgi?id=11554
|
||||
|
||||
|
|
|
@ -18,5 +18,5 @@ void main()
|
|||
f();
|
||||
f();
|
||||
f();
|
||||
f();
|
||||
static assert("1"); // also surpress deprecationSupplemental
|
||||
}
|
||||
|
|
|
@ -100,6 +100,12 @@ void main()
|
|||
values();
|
||||
return 0;
|
||||
}
|
||||
import imports.vcg_ast_import;
|
||||
template imported()
|
||||
{
|
||||
import imported = imports.vcg_ast_import;
|
||||
}
|
||||
alias myImport = vcg_ast_import;
|
||||
R!int
|
||||
{
|
||||
struct _R
|
||||
|
@ -126,6 +132,21 @@ mixin _d_cmain!();
|
|||
}
|
||||
}
|
||||
}
|
||||
imported!()
|
||||
{
|
||||
import object;
|
||||
struct O
|
||||
{
|
||||
invariant
|
||||
{
|
||||
}
|
||||
invariant
|
||||
{
|
||||
__invariant0();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
RTInfo!(C)
|
||||
{
|
||||
enum immutable(void)* RTInfo = null;
|
||||
|
@ -150,4 +171,3 @@ RTInfo!(_R)
|
|||
enum immutable(void)* RTInfo = null;
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -34,3 +34,11 @@ enum expectedStart = "module imports.imp16088;";
|
|||
immutable ubyte[] s0 = import("imp16088.d");
|
||||
|
||||
static assert(s0[0 .. expectedStart.length] == "module imports.imp16088;");
|
||||
|
||||
// https://issues.dlang.org/show_bug.cgi?id=24687
|
||||
|
||||
void foo(string path);
|
||||
void foo(const(ubyte[]) data);
|
||||
|
||||
void bar1() { foo(import("imp16088.d")); } // matches both
|
||||
void bar2() { foo(cast(const(ubyte[])) import("imp16088.d")); } // matches both!
|
||||
|
|
4
compiler/test/compilable/imports/vcg_ast_import.d
Normal file
4
compiler/test/compilable/imports/vcg_ast_import.d
Normal file
|
@ -0,0 +1,4 @@
|
|||
struct O
|
||||
{
|
||||
invariant() {}
|
||||
}
|
|
@ -117,8 +117,8 @@ foo2
|
|||
T2
|
||||
TestStaticForeach2
|
||||
issue22007
|
||||
1 2 '3'
|
||||
2 3 '4'
|
||||
1 2 3
|
||||
2 3 4
|
||||
0 1
|
||||
1 2
|
||||
2 3
|
||||
|
|
11
compiler/test/compilable/test24337.d
Normal file
11
compiler/test/compilable/test24337.d
Normal file
|
@ -0,0 +1,11 @@
|
|||
/*
|
||||
TEST_OUTPUT:
|
||||
---
|
||||
"ab"w x"11223344556677"
|
||||
---
|
||||
*/
|
||||
// https://issues.dlang.org/show_bug.cgi?id=24337
|
||||
|
||||
immutable ushort[] y = cast(immutable ushort[]) "ab"w;
|
||||
immutable ulong[] z = x"00 11 22 33 44 55 66 77";
|
||||
pragma(msg, y, " ", z);
|
4
compiler/test/compilable/test24760.d
Normal file
4
compiler/test/compilable/test24760.d
Normal file
|
@ -0,0 +1,4 @@
|
|||
// https://issues.dlang.org/show_bug.cgi?id=24760
|
||||
|
||||
long f(int e = 0, uint[] optional...) => optional.length;
|
||||
long f0() => f(); // compiler segfaults
|
|
@ -23,4 +23,9 @@ void main()
|
|||
|
||||
static assert(is(typeof(a.length = 0) == size_t));
|
||||
static assert(is(typeof(a.length = f.length = 0) == size_t));
|
||||
|
||||
// https://issues.dlang.org/show_bug.cgi?id=24790
|
||||
struct S { int[] payload; }
|
||||
S s;
|
||||
s.payload.length += 3;
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
REQUIRED_ARGS: -vcg-ast -o-
|
||||
PERMUTE_ARGS:
|
||||
OUTPUT_FILES: compilable/vcg-ast.d.cg
|
||||
EXTRA_FILES: imports/vcg_ast_import.d
|
||||
TEST_OUTPUT_FILE: extra-files/vcg-ast.d.cg
|
||||
*/
|
||||
|
||||
|
@ -63,3 +64,14 @@ void main()
|
|||
{
|
||||
values!wchar_t;
|
||||
}
|
||||
|
||||
// https://issues.dlang.org/show_bug.cgi?id=24764
|
||||
|
||||
import imports.vcg_ast_import;
|
||||
|
||||
template imported()
|
||||
{
|
||||
import imported = imports.vcg_ast_import;
|
||||
}
|
||||
|
||||
alias myImport = imported!();
|
||||
|
|
69
compiler/test/compilable/vcg_ast_compilable.d
Normal file
69
compiler/test/compilable/vcg_ast_compilable.d
Normal file
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
REQUIRED_ARGS: -vcg-ast -o-
|
||||
OUTPUT_FILES: compilable/vcg_ast_compilable.d.cg
|
||||
TEST_OUTPUT:
|
||||
---
|
||||
=== compilable/vcg_ast_compilable.d.cg
|
||||
import object;
|
||||
auto binaryFun(E)(E b)
|
||||
{
|
||||
return 'a' == b;
|
||||
}
|
||||
void find(Element)(Element needle) if (is(typeof(binaryFun(needle))))
|
||||
{
|
||||
}
|
||||
void find()(string needle)
|
||||
{
|
||||
}
|
||||
void splitter()
|
||||
{
|
||||
find(3);
|
||||
find("");
|
||||
}
|
||||
binaryFun!int
|
||||
{
|
||||
auto pure nothrow @nogc @safe bool binaryFun(int b)
|
||||
{
|
||||
return 97 == b;
|
||||
}
|
||||
|
||||
}
|
||||
find!int
|
||||
{
|
||||
pure nothrow @nogc @safe void find(int needle)
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
binaryFun!string
|
||||
{
|
||||
auto _error_ binaryFun
|
||||
{
|
||||
__error__
|
||||
}
|
||||
|
||||
}
|
||||
find!()
|
||||
{
|
||||
pure nothrow @nogc @safe void find(string needle)
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
---
|
||||
*/
|
||||
|
||||
// https://issues.dlang.org/show_bug.cgi?id=24431
|
||||
auto binaryFun(E)(E b)
|
||||
{
|
||||
return 'a' == b;
|
||||
}
|
||||
|
||||
void find(Element)(Element needle) if (is(typeof(binaryFun(needle)))) { }
|
||||
void find()(string needle) { }
|
||||
|
||||
void splitter()
|
||||
{
|
||||
find!int(3);
|
||||
find!()("");
|
||||
}
|
|
@ -72,6 +72,20 @@ class Tst(TST, int v = 2) {
|
|||
|
||||
class Y : Tst!(float) {}
|
||||
|
||||
// https://issues.dlang.org/show_bug.cgi?id=24731
|
||||
void test24731()
|
||||
{
|
||||
static int solve(size_t N)(ref double[N+1][N])
|
||||
{
|
||||
return N;
|
||||
}
|
||||
|
||||
double[3][2] m;
|
||||
assert(solve(m) == 2);
|
||||
assert(solve!2(m) == 2);
|
||||
}
|
||||
|
||||
|
||||
void main() {
|
||||
Tst!(int) t = new Tst!(int);
|
||||
Y u = new Y;
|
||||
|
@ -113,4 +127,5 @@ void main() {
|
|||
printf("%g\n", i);
|
||||
}
|
||||
|
||||
test24731();
|
||||
}
|
||||
|
|
|
@ -4,9 +4,9 @@
|
|||
/*
|
||||
TEST_OUTPUT:
|
||||
---
|
||||
CT x.offsetof = <
|
||||
CT y.offsetof = <
|
||||
0 > y
|
||||
CT x.offsetof = <
|
||||
0 > x
|
||||
---
|
||||
*/
|
||||
|
|
|
@ -1,13 +0,0 @@
|
|||
// https://issues.dlang.org/show_bug.cgi?id=23650
|
||||
|
||||
__gshared int x;
|
||||
|
||||
void main()
|
||||
{
|
||||
|
||||
static assert(__traits(compiles,
|
||||
{
|
||||
struct S { int *p = &x; }
|
||||
auto t = typeid(S);
|
||||
}));
|
||||
}
|
24
compiler/test/runnable/test24599.d
Normal file
24
compiler/test/runnable/test24599.d
Normal file
|
@ -0,0 +1,24 @@
|
|||
module mod;
|
||||
|
||||
struct Variable
|
||||
{
|
||||
size_t toHash() const { return 0; }
|
||||
}
|
||||
|
||||
enum hasInoutConstruction(T) = __traits(compiles, { struct S { T a; } });
|
||||
|
||||
struct Algebraic(T)
|
||||
{
|
||||
static if (hasInoutConstruction!T)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
Algebraic!Variable foo();
|
||||
|
||||
struct S
|
||||
{
|
||||
Variable[] symbols;
|
||||
}
|
||||
|
||||
void main() {}
|
Loading…
Add table
Add a link
Reference in a new issue