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:
Nicholas Wilson 2024-10-07 17:00:14 +08:00 committed by GitHub
parent 4c02e46b60
commit 57c5b071af
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
35 changed files with 361 additions and 148 deletions

View file

@ -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
"
),
};

View file

@ -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;

View file

@ -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);

View file

@ -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, &parameters, dedtypes, null) || edim && edim.toInteger() == t.dim.toInteger())
if ((tp && tp.matchArg(sc, t.dim, i, &parameters, 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];

View file

@ -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;

View file

@ -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;
}

View file

@ -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;

View file

@ -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
{

View file

@ -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(");");

View file

@ -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, ...)`");
}

View file

@ -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,

View file

@ -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;
}

View file

@ -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;

View file

@ -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);
}
}
////////////////////////////////////////////////////////////////////////////////

View file

@ -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

View file

@ -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)

View file

@ -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;

View file

@ -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;

View file

@ -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);

View file

@ -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);
}

View file

@ -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

View file

@ -18,5 +18,5 @@ void main()
f();
f();
f();
f();
static assert("1"); // also surpress deprecationSupplemental
}

View file

@ -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;
}

View file

@ -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!

View file

@ -0,0 +1,4 @@
struct O
{
invariant() {}
}

View file

@ -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

View 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);

View 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

View file

@ -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;
}

View file

@ -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!();

View 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!()("");
}

View file

@ -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();
}

View file

@ -4,9 +4,9 @@
/*
TEST_OUTPUT:
---
CT x.offsetof = <
CT y.offsetof = <
0 > y
CT x.offsetof = <
0 > x
---
*/

View file

@ -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);
}));
}

View 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() {}