Merge remote-tracking branch 'upstream/master' into stable

This commit is contained in:
Iain Buclaw 2022-10-10 08:57:21 +00:00
commit ea16dd1531
32 changed files with 172 additions and 123 deletions

View file

@ -20,6 +20,6 @@ repos:
- id: no-commit-to-branch - id: no-commit-to-branch
args: [--branch, master] args: [--branch, master]
- repo: https://github.com/sirosen/check-jsonschema - repo: https://github.com/sirosen/check-jsonschema
rev: 0.17.1 rev: 0.18.3
hooks: hooks:
- id: check-github-workflows - id: check-github-workflows

View file

@ -34,7 +34,7 @@ For more infos, see the [Ddoc spec](https://dlang.org/spec/ddoc.html).
Preview changes Preview changes
--------------- ---------------
If you have cloned the [tools](https://github.com/dlang/tools) and [dlang.org](https://github.com/dlang/dlang.org) repo), If you have cloned the [tools](https://github.com/dlang/tools) and [dlang.org](https://github.com/dlang/dlang.org) repo,
you can preview the changelog with: you can preview the changelog with:
``` ```

View file

@ -174,7 +174,7 @@ public:
structalign_t alignment; // alignment applied outside of the struct structalign_t alignment; // alignment applied outside of the struct
ThreeState ispod; // if struct is POD ThreeState ispod; // if struct is POD
private: private:
uint8_t bitFields; uint16_t bitFields;
public: public:
static StructDeclaration *create(const Loc &loc, Identifier *id, bool inObject); static StructDeclaration *create(const Loc &loc, Identifier *id, bool inObject);
StructDeclaration *syntaxCopy(Dsymbol *s) override; StructDeclaration *syntaxCopy(Dsymbol *s) override;

View file

@ -251,7 +251,9 @@ debtyp_t * debtyp_alloc(uint length)
length += pad; length += pad;
} }
length < 0x10000 || assert(0); if (length > ushort.max)
err_nomem();
const len = debtyp_t.sizeof - (d.data).sizeof + length; const len = debtyp_t.sizeof - (d.data).sizeof + length;
debug debug
{ {
@ -262,6 +264,8 @@ debug
else else
{ {
d = cast(debtyp_t *) malloc(debtyp_t.sizeof - (d.data).sizeof + length); d = cast(debtyp_t *) malloc(debtyp_t.sizeof - (d.data).sizeof + length);
if (!d)
err_nomem();
} }
d.length = cast(ushort)length; d.length = cast(ushort)length;
if (pad) if (pad)
@ -284,7 +288,7 @@ private void debtyp_free(debtyp_t *d)
//fflush(stdout); //fflush(stdout);
debug debug
{ {
assert(d.length < 0x10000); assert(d.length <= ushort.max);
uint len = debtyp_t.sizeof - (d.data).sizeof + d.length; uint len = debtyp_t.sizeof - (d.data).sizeof + d.length;
// assert((cast(char*)d)[len] == 0x2E); // assert((cast(char*)d)[len] == 0x2E);
memset(d, 0x55, len); memset(d, 0x55, len);
@ -325,56 +329,27 @@ void debtyp_check(debtyp_t* d) { }
@trusted @trusted
idx_t cv_debtyp(debtyp_t *d) idx_t cv_debtyp(debtyp_t *d)
{ {
ushort length;
uint hashi; uint hashi;
assert(d); assert(d);
length = d.length; const length = d.length;
//printf("length = %3d\n",length); //printf("length = %3d\n",length);
static if (SYMDEB_TDB) static if (SYMDEB_TDB)
{ {
if (config.fulltypes == CVTDB) if (config.fulltypes == CVTDB)
{
idx_t result;
static if (1)
{ {
assert(length); assert(length);
debtyp_check(d); debtyp_check(d);
result = tdb_typidx(&d.length); const result = tdb_typidx(&d.length);
}
else
{
ubyte *buf;
// Allocate buffer
buf = malloc(6 + length);
if (!buf)
err_nomem(); // out of memory
// Fill the buffer
TOLONG(buf,cgcv.signature);
memcpy(buf + 4,cast(char *)d + uint.sizeof,2 + length);
static if (0)
{
{int i;
for (i=0;i<length;i++)
printf("%02x ",buf[6+i]);
printf("\n");
}
}
result = tdb_typidx(buf,6 + length);
}
//printf("result = x%x\n",result); //printf("result = x%x\n",result);
debtyp_free(d); debtyp_free(d);
return result; return result;
} }
} }
if (length) if (length)
{ uint hash; {
uint hash = length;
hash = length;
if (length >= uint.sizeof) if (length >= uint.sizeof)
{ {
// Hash consists of the sum of the first 4 bytes with the last 4 bytes // Hash consists of the sum of the first 4 bytes with the last 4 bytes
@ -607,7 +582,8 @@ static if (SYMDEB_TDB)
pstate.STtdbtimestamp = tdb_gettimestamp(); pstate.STtdbtimestamp = tdb_gettimestamp();
size_t len = cv_stringbytes(ftdbname); size_t len = cv_stringbytes(ftdbname);
ubyte *ds = (8 + len <= buf.sizeof) ? buf : cast(ubyte *) malloc(8 + len); ubyte *ds = (8 + len <= buf.sizeof) ? buf : cast(ubyte *) malloc(8 + len);
assert(ds); if (!ds)
err_nomem();
TOWORD(ds,6 + len); TOWORD(ds,6 + len);
TOWORD(ds + 2,S_TDBNAME); TOWORD(ds + 2,S_TDBNAME);
TOLONG(ds + 4,pstate.STtdbtimestamp); TOLONG(ds + 4,pstate.STtdbtimestamp);
@ -2507,7 +2483,8 @@ else
// Length of record // Length of record
length = 2 + 2 + 4 * 3 + _tysize[TYint] * 4 + 2 + cgcv.sz_idx + 1; length = 2 + 2 + 4 * 3 + _tysize[TYint] * 4 + 2 + cgcv.sz_idx + 1;
debsym = (length + len <= (buf).sizeof) ? buf.ptr : cast(ubyte *) malloc(length + len); debsym = (length + len <= (buf).sizeof) ? buf.ptr : cast(ubyte *) malloc(length + len);
assert(debsym); if (!debsym)
err_nomem();
memset(debsym,0,length + len); memset(debsym,0,length + len);
// Symbol type // Symbol type
@ -2586,7 +2563,8 @@ else
} }
len = cast(uint)strlen(id); len = cast(uint)strlen(id);
debsym = (39 + IDOHD + len <= (buf).sizeof) ? buf.ptr : cast(ubyte *) malloc(39 + IDOHD + len); debsym = (39 + IDOHD + len <= (buf).sizeof) ? buf.ptr : cast(ubyte *) malloc(39 + IDOHD + len);
assert(debsym); if (!debsym)
err_nomem();
switch (s.Sclass) switch (s.Sclass)
{ {
case SC.parameter: case SC.parameter:

View file

@ -162,8 +162,15 @@ int blockExit(Statement s, FuncDeclaration func, bool mustNotThrow)
{ {
if (blockExit(s, func, mustNotThrow) != BE.halt && s.hasCode() && if (blockExit(s, func, mustNotThrow) != BE.halt && s.hasCode() &&
s.loc != Loc.initial) // don't emit warning for generated code s.loc != Loc.initial) // don't emit warning for generated code
{
auto parent1 = func.toParent();
if (parent1 && parent1.isTemplateInstance())
s.warning("statement is not reachable in template instance %s", func.toPrettyChars());
else
s.warning("statement is not reachable"); s.warning("statement is not reachable");
} }
}
else else
{ {
result &= ~BE.fallthru; result &= ~BE.fallthru;

View file

@ -216,6 +216,10 @@ extern (C++) class StructDeclaration : AggregateDeclaration
bool hasIdentityEquals; // true if has identity opEquals bool hasIdentityEquals; // true if has identity opEquals
bool hasNoFields; // has no fields bool hasNoFields; // has no fields
bool hasCopyCtor; // copy constructor bool hasCopyCtor; // copy constructor
bool hasPointerField; // members with indirections
bool hasVoidInitPointers; // void-initialized unsafe fields
bool hasFieldWithInvariant; // invariants
bool computedTypeProperties;// the above 3 fields are computed
// Even if struct is defined as non-root symbol, some built-in operations // Even if struct is defined as non-root symbol, some built-in operations
// (e.g. TypeidExp, NewExp, ArrayLiteralExp, etc) request its TypeInfo. // (e.g. TypeidExp, NewExp, ArrayLiteralExp, etc) request its TypeInfo.
// For those, today TypeInfo_Struct is generated in COMDAT. // For those, today TypeInfo_Struct is generated in COMDAT.
@ -223,7 +227,7 @@ extern (C++) class StructDeclaration : AggregateDeclaration
} }
import dmd.common.bitfields : generateBitFields; import dmd.common.bitfields : generateBitFields;
mixin(generateBitFields!(BitFields, ubyte)); mixin(generateBitFields!(BitFields, ushort));
extern (D) this(const ref Loc loc, Identifier id, bool inObject) extern (D) this(const ref Loc loc, Identifier id, bool inObject)
{ {
@ -391,9 +395,32 @@ extern (C++) class StructDeclaration : AggregateDeclaration
} }
} }
argTypes = target.toArgTypes(type); argTypes = target.toArgTypes(type);
} }
/// Compute cached type properties for `TypeStruct`
extern(D) final void determineTypeProperties()
{
if (computedTypeProperties)
return;
foreach (vd; fields)
{
if (vd.storage_class & STC.ref_ || vd.hasPointers())
hasPointerField = true;
if (vd._init && vd._init.isVoidInitializer() && vd.type.hasPointers())
hasVoidInitPointers = true;
if (!vd._init && vd.type.hasVoidInitPointers())
hasVoidInitPointers = true;
if (vd.type.hasInvariant())
hasFieldWithInvariant = true;
}
computedTypeProperties = true;
}
/*************************************** /***************************************
* Determine if struct is POD (Plain Old Data). * Determine if struct is POD (Plain Old Data).
* *

View file

@ -3214,6 +3214,7 @@ struct HdrGenState final
int32_t tpltMember; int32_t tpltMember;
int32_t autoMember; int32_t autoMember;
int32_t forStmtInit; int32_t forStmtInit;
int32_t insideFuncBody;
bool declstring; bool declstring;
EnumDeclaration* inEnumDecl; EnumDeclaration* inEnumDecl;
HdrGenState() : HdrGenState() :
@ -3224,11 +3225,12 @@ struct HdrGenState final
tpltMember(), tpltMember(),
autoMember(), autoMember(),
forStmtInit(), forStmtInit(),
insideFuncBody(),
declstring(), declstring(),
inEnumDecl() inEnumDecl()
{ {
} }
HdrGenState(bool hdrgen, bool ddoc = false, bool fullDump = false, bool fullQual = false, int32_t tpltMember = 0, int32_t autoMember = 0, int32_t forStmtInit = 0, bool declstring = false, EnumDeclaration* inEnumDecl = nullptr) : HdrGenState(bool hdrgen, bool ddoc = false, bool fullDump = false, bool fullQual = false, int32_t tpltMember = 0, int32_t autoMember = 0, int32_t forStmtInit = 0, int32_t insideFuncBody = 0, bool declstring = false, EnumDeclaration* inEnumDecl = nullptr) :
hdrgen(hdrgen), hdrgen(hdrgen),
ddoc(ddoc), ddoc(ddoc),
fullDump(fullDump), fullDump(fullDump),
@ -3236,6 +3238,7 @@ struct HdrGenState final
tpltMember(tpltMember), tpltMember(tpltMember),
autoMember(autoMember), autoMember(autoMember),
forStmtInit(forStmtInit), forStmtInit(forStmtInit),
insideFuncBody(insideFuncBody),
declstring(declstring), declstring(declstring),
inEnumDecl(inEnumDecl) inEnumDecl(inEnumDecl)
{} {}
@ -6309,10 +6312,18 @@ public:
bool hasNoFields(bool v); bool hasNoFields(bool v);
bool hasCopyCtor() const; bool hasCopyCtor() const;
bool hasCopyCtor(bool v); bool hasCopyCtor(bool v);
bool hasPointerField() const;
bool hasPointerField(bool v);
bool hasVoidInitPointers() const;
bool hasVoidInitPointers(bool v);
bool hasFieldWithInvariant() const;
bool hasFieldWithInvariant(bool v);
bool computedTypeProperties() const;
bool computedTypeProperties(bool v);
bool requestTypeInfo() const; bool requestTypeInfo() const;
bool requestTypeInfo(bool v); bool requestTypeInfo(bool v);
private: private:
uint8_t bitFields; uint16_t bitFields;
public: public:
static StructDeclaration* create(const Loc& loc, Identifier* id, bool inObject); static StructDeclaration* create(const Loc& loc, Identifier* id, bool inObject);
StructDeclaration* syntaxCopy(Dsymbol* s) override; StructDeclaration* syntaxCopy(Dsymbol* s) override;

View file

@ -64,6 +64,7 @@ struct HdrGenState
int tpltMember; int tpltMember;
int autoMember; int autoMember;
int forStmtInit; int forStmtInit;
int insideFuncBody;
bool declstring; // set while declaring alias for string,wstring or dstring bool declstring; // set while declaring alias for string,wstring or dstring
EnumDeclaration inEnumDecl; EnumDeclaration inEnumDecl;
@ -1559,7 +1560,7 @@ public:
bodyToBuffer(f); bodyToBuffer(f);
hgs.autoMember--; hgs.autoMember--;
} }
else if (hgs.tpltMember == 0 && global.params.dihdr.fullOutput == false) else if (hgs.tpltMember == 0 && global.params.dihdr.fullOutput == false && !hgs.insideFuncBody)
{ {
if (!f.fbody) if (!f.fbody)
{ {
@ -1644,7 +1645,7 @@ public:
void bodyToBuffer(FuncDeclaration f) void bodyToBuffer(FuncDeclaration f)
{ {
if (!f.fbody || (hgs.hdrgen && global.params.dihdr.fullOutput == false && !hgs.autoMember && !hgs.tpltMember)) if (!f.fbody || (hgs.hdrgen && global.params.dihdr.fullOutput == false && !hgs.autoMember && !hgs.tpltMember && !hgs.insideFuncBody))
{ {
if (!f.fbody && (f.fensures || f.frequires)) if (!f.fbody && (f.fensures || f.frequires))
{ {
@ -1655,6 +1656,18 @@ public:
buf.writenl(); buf.writenl();
return; return;
} }
// there is no way to know if a function is nested
// or not after parsing. We need scope information
// for that, which is avaible during semantic
// analysis. To overcome that, a simple mechanism
// is implemented: everytime we print a function
// body (templated or not) we increment a counter.
// We decredement the counter when we stop
// printing the function body.
++hgs.insideFuncBody;
scope(exit) { --hgs.insideFuncBody; }
const savetlpt = hgs.tpltMember; const savetlpt = hgs.tpltMember;
const saveauto = hgs.autoMember; const saveauto = hgs.autoMember;
hgs.tpltMember = 0; hgs.tpltMember = 0;

View file

@ -5532,52 +5532,25 @@ extern (C++) final class TypeStruct : Type
override bool hasPointers() override bool hasPointers()
{ {
// Probably should cache this information in sym rather than recompute
StructDeclaration s = sym;
if (sym.members && !sym.determineFields() && sym.type != Type.terror) if (sym.members && !sym.determineFields() && sym.type != Type.terror)
error(sym.loc, "no size because of forward references"); error(sym.loc, "no size because of forward references");
foreach (VarDeclaration v; s.fields) sym.determineTypeProperties();
{ return sym.hasPointerField;
if (v.storage_class & STC.ref_ || v.hasPointers())
return true;
}
return false;
} }
override bool hasVoidInitPointers() override bool hasVoidInitPointers()
{ {
// Probably should cache this information in sym rather than recompute
StructDeclaration s = sym;
sym.size(Loc.initial); // give error for forward references sym.size(Loc.initial); // give error for forward references
foreach (VarDeclaration v; s.fields) sym.determineTypeProperties();
{ return sym.hasVoidInitPointers;
if (v._init && v._init.isVoidInitializer() && v.type.hasPointers())
return true;
if (!v._init && v.type.hasVoidInitPointers())
return true;
}
return false;
} }
override bool hasInvariant() override bool hasInvariant()
{ {
// Probably should cache this information in sym rather than recompute
StructDeclaration s = sym;
sym.size(Loc.initial); // give error for forward references sym.size(Loc.initial); // give error for forward references
sym.determineTypeProperties();
if (s.hasInvariant()) return sym.hasInvariant() || sym.hasFieldWithInvariant;
return true;
foreach (VarDeclaration v; s.fields)
{
if (v.type.hasInvariant())
return true;
}
return false;
} }
extern (D) MATCH implicitConvToWithoutAliasThis(Type to) extern (D) MATCH implicitConvToWithoutAliasThis(Type to)

View file

@ -120,7 +120,24 @@ template Foo(T, int V)
B, B,
C, C,
} }
void fswitch(Label l); void fswitch(Label l)
{
final switch (l)
{
case A:
{
break;
}
case B:
{
break;
}
case C:
{
break;
}
}
}
loop: loop:
while (x) while (x)
{ {

View file

@ -162,6 +162,18 @@ align(2) struct S12200_2
align(1): align(1):
} }
// https://issues.dlang.org/show_bug.cgi?id=14694
inout(T)[] overlap(T)(inout(T)[] r1, inout(T)[] r2) @trusted pure nothrow
{
alias U = inout(T);
static U* max(U* a, U* b) nothrow { return a > b ? a : b; }
static U* min(U* a, U* b) nothrow { return a < b ? a : b; }
auto b = max(r1.ptr, r2.ptr);
auto e = min(r1.ptr + r1.length, r2.ptr + r2.length);
return b < e ? b[0 .. e - b] : null;
}
// https://issues.dlang.org/show_bug.cgi?id=16140 // https://issues.dlang.org/show_bug.cgi?id=16140
void gun()() void gun()()
{ {

View file

@ -119,6 +119,21 @@ align (2) struct S12200_2
{ {
align (1) {} align (1) {}
} }
pure nothrow @trusted inout(T)[] overlap(T)(inout(T)[] r1, inout(T)[] r2)
{
alias U = inout(T);
static nothrow U* max(U* a, U* b)
{
return a > b ? a : b;
}
static nothrow U* min(U* a, U* b)
{
return a < b ? a : b;
}
auto b = max(r1.ptr, r2.ptr);
auto e = min(r1.ptr + r1.length, r2.ptr + r2.length);
return b < e ? b[0..e - b] : null;
}
void gun()() void gun()()
{ {
int[] res; int[] res;

View file

@ -221,6 +221,21 @@ align (2) struct S12200_2
{ {
align (1) {} align (1) {}
} }
pure nothrow @trusted inout(T)[] overlap(T)(inout(T)[] r1, inout(T)[] r2)
{
alias U = inout(T);
static nothrow U* max(U* a, U* b)
{
return a > b ? a : b;
}
static nothrow U* min(U* a, U* b)
{
return a < b ? a : b;
}
auto b = max(r1.ptr, r2.ptr);
auto e = min(r1.ptr + r1.length, r2.ptr + r2.length);
return b < e ? b[0..e - b] : null;
}
void gun()() void gun()()
{ {
int[] res; int[] res;

View file

@ -0,0 +1,23 @@
// REQUIRED_ARGS: -o- -w
/*
TEST_OUTPUT:
---
fail_compilation/warn14905.d(16): Warning: statement is not reachable in template instance warn14905.fun!"a".fun
fail_compilation/warn14905.d(16): Warning: statement is not reachable in template instance warn14905.fun!"b".fun
Error: warnings are treated as errors
Use -wi if you wish to treat warnings only as informational.
---
*/
bool fun(string s)()
{
return true;
return false;
}
void main()
{
cast(void)fun!"a";
cast(void)fun!"b";
}

View file

@ -1,42 +0,0 @@
This directory will get copied to dlang.org and cleared when master gets
merged into stable prior to a new release.
How to add a new changelog entry to the pending changelog?
==========================================================
Create a new file in the `changelog` folder. It should end with `.dd` and look
similar to a git commit message. The first line represents the title of the change.
After an empty line follows the long description:
```
My fancy title of the new feature
A long description of the new feature in `std.range`.
It can be followed by an example:
-------
import std.range : padLeft, padRight;
import std.algorithm.comparison : equal;
assert([1, 2, 3, 4, 5].padLeft(0, 7).equal([0, 0, 1, 2, 3, 4, 5]));
assert("Hello World!".padRight('!', 15).equal("Hello World!!!!"));
-------
and links to the documentation, e.g. $(REF drop, std, range) or
$(REF_ALTTEXT a custom name for the function, drop, std, range).
Links to the spec can look like this $(LINK2 $(ROOT_DIR)spec/module.html, this)
and of course you can link to other $(LINK2 https://forum.dlang.org/, external resources).
```
The title can't contain links (it's already one).
For more infos, see the [Ddoc spec](https://dlang.org/spec/ddoc.html).
Preview changes
---------------
If you have cloned the [tools](https://github.com/dlang/tools) and [dlang.org](https://github.com/dlang/dlang.org) repo,
you can preview the changelog with:
```
make -C ../dlang.org -f posix.mak pending_changelog
```