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
args: [--branch, master]
- repo: https://github.com/sirosen/check-jsonschema
rev: 0.17.1
rev: 0.18.3
hooks:
- 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
---------------
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:
```

View file

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

View file

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

View file

@ -162,7 +162,14 @@ int blockExit(Statement s, FuncDeclaration func, bool mustNotThrow)
{
if (blockExit(s, func, mustNotThrow) != BE.halt && s.hasCode() &&
s.loc != Loc.initial) // don't emit warning for generated code
s.warning("statement is not reachable");
{
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");
}
}
else
{

View file

@ -216,6 +216,10 @@ extern (C++) class StructDeclaration : AggregateDeclaration
bool hasIdentityEquals; // true if has identity opEquals
bool hasNoFields; // has no fields
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
// (e.g. TypeidExp, NewExp, ArrayLiteralExp, etc) request its TypeInfo.
// For those, today TypeInfo_Struct is generated in COMDAT.
@ -223,7 +227,7 @@ extern (C++) class StructDeclaration : AggregateDeclaration
}
import dmd.common.bitfields : generateBitFields;
mixin(generateBitFields!(BitFields, ubyte));
mixin(generateBitFields!(BitFields, ushort));
extern (D) this(const ref Loc loc, Identifier id, bool inObject)
{
@ -391,9 +395,32 @@ extern (C++) class StructDeclaration : AggregateDeclaration
}
}
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).
*

View file

@ -3214,6 +3214,7 @@ struct HdrGenState final
int32_t tpltMember;
int32_t autoMember;
int32_t forStmtInit;
int32_t insideFuncBody;
bool declstring;
EnumDeclaration* inEnumDecl;
HdrGenState() :
@ -3224,11 +3225,12 @@ struct HdrGenState final
tpltMember(),
autoMember(),
forStmtInit(),
insideFuncBody(),
declstring(),
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),
ddoc(ddoc),
fullDump(fullDump),
@ -3236,6 +3238,7 @@ struct HdrGenState final
tpltMember(tpltMember),
autoMember(autoMember),
forStmtInit(forStmtInit),
insideFuncBody(insideFuncBody),
declstring(declstring),
inEnumDecl(inEnumDecl)
{}
@ -6309,10 +6312,18 @@ public:
bool hasNoFields(bool v);
bool hasCopyCtor() const;
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(bool v);
private:
uint8_t bitFields;
uint16_t bitFields;
public:
static StructDeclaration* create(const Loc& loc, Identifier* id, bool inObject);
StructDeclaration* syntaxCopy(Dsymbol* s) override;

View file

@ -64,6 +64,7 @@ struct HdrGenState
int tpltMember;
int autoMember;
int forStmtInit;
int insideFuncBody;
bool declstring; // set while declaring alias for string,wstring or dstring
EnumDeclaration inEnumDecl;
@ -1559,7 +1560,7 @@ public:
bodyToBuffer(f);
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)
{
@ -1644,7 +1645,7 @@ public:
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))
{
@ -1655,6 +1656,18 @@ public:
buf.writenl();
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 saveauto = hgs.autoMember;
hgs.tpltMember = 0;

View file

@ -5532,52 +5532,25 @@ extern (C++) final class TypeStruct : Type
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)
error(sym.loc, "no size because of forward references");
foreach (VarDeclaration v; s.fields)
{
if (v.storage_class & STC.ref_ || v.hasPointers())
return true;
}
return false;
sym.determineTypeProperties();
return sym.hasPointerField;
}
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
foreach (VarDeclaration v; s.fields)
{
if (v._init && v._init.isVoidInitializer() && v.type.hasPointers())
return true;
if (!v._init && v.type.hasVoidInitPointers())
return true;
}
return false;
sym.determineTypeProperties();
return sym.hasVoidInitPointers;
}
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
if (s.hasInvariant())
return true;
foreach (VarDeclaration v; s.fields)
{
if (v.type.hasInvariant())
return true;
}
return false;
sym.determineTypeProperties();
return sym.hasInvariant() || sym.hasFieldWithInvariant;
}
extern (D) MATCH implicitConvToWithoutAliasThis(Type to)

View file

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

View file

@ -162,6 +162,18 @@ align(2) struct S12200_2
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
void gun()()
{

View file

@ -119,6 +119,21 @@ align (2) struct S12200_2
{
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()()
{
int[] res;

View file

@ -221,6 +221,21 @@ align (2) struct S12200_2
{
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()()
{
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
```