mirror of
https://github.com/dlang/dmd.git
synced 2025-04-26 13:10:12 +03:00
Merge remote-tracking branch 'upstream/master' into stable
This commit is contained in:
commit
ea16dd1531
32 changed files with 172 additions and 123 deletions
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
|
||||
```
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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).
|
||||
*
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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()()
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
23
compiler/test/fail_compilation/warn14905.d
Normal file
23
compiler/test/fail_compilation/warn14905.d
Normal 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";
|
||||
}
|
|
@ -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
|
||||
```
|
Loading…
Add table
Add a link
Reference in a new issue