mirror of
https://github.com/dlang/dmd.git
synced 2025-04-25 20:50:41 +03:00
Merge branch 'stable' into merge-stable
This commit is contained in:
commit
33c32407c0
14 changed files with 295 additions and 34 deletions
20
.github/workflows/main.yml
vendored
20
.github/workflows/main.yml
vendored
|
@ -32,11 +32,12 @@ jobs:
|
|||
os: ubuntu-22.04
|
||||
model: 32
|
||||
host_dmd: dmd
|
||||
- job_name: Ubuntu 22.04 x86, DMD (coverage)
|
||||
os: ubuntu-22.04
|
||||
model: 32
|
||||
host_dmd: dmd
|
||||
coverage: true
|
||||
# Disabled because of failure https://issues.dlang.org/show_bug.cgi?id=24518
|
||||
# - job_name: Ubuntu 22.04 x86, DMD (coverage)
|
||||
# os: ubuntu-22.04
|
||||
# model: 32
|
||||
# host_dmd: dmd
|
||||
# coverage: true
|
||||
- job_name: Ubuntu 22.04 x86, DMD (bootstrap)
|
||||
os: ubuntu-22.04
|
||||
model: 32
|
||||
|
@ -52,10 +53,11 @@ jobs:
|
|||
- job_name: macOS 13 x64, DMD (latest)
|
||||
os: macos-13
|
||||
host_dmd: dmd
|
||||
- job_name: macOS 13 x64, DMD (coverage)
|
||||
os: macos-13
|
||||
host_dmd: dmd
|
||||
coverage: true
|
||||
# Disabled because of failure https://issues.dlang.org/show_bug.cgi?id=24518
|
||||
# - job_name: macOS 13 x64, DMD (coverage)
|
||||
# os: macos-13
|
||||
# host_dmd: dmd
|
||||
# coverage: true
|
||||
- job_name: macOS 12 x64, DMD (bootstrap)
|
||||
os: macos-12
|
||||
# de-facto bootstrap version on OSX
|
||||
|
|
|
@ -1919,6 +1919,14 @@ final class CParser(AST) : Parser!AST
|
|||
auto s = cparseFunctionDefinition(id, dt.isTypeFunction(), specifier);
|
||||
typedefTab.setDim(typedefTabLengthSave);
|
||||
symbols = symbolsSave;
|
||||
if (specifier.mod & MOD.x__stdcall)
|
||||
{
|
||||
// If this function is __stdcall, wrap it in a LinkDeclaration so that
|
||||
// it's extern(Windows) when imported in D.
|
||||
auto decls = new AST.Dsymbols(1);
|
||||
(*decls)[0] = s;
|
||||
s = new AST.LinkDeclaration(s.loc, LINK.windows, decls);
|
||||
}
|
||||
symbols.push(s);
|
||||
return;
|
||||
}
|
||||
|
@ -2071,13 +2079,14 @@ final class CParser(AST) : Parser!AST
|
|||
}
|
||||
}
|
||||
s = applySpecifier(s, specifier);
|
||||
if (level == LVL.local)
|
||||
if (level == LVL.local || (specifier.mod & MOD.x__stdcall))
|
||||
{
|
||||
// Wrap the declaration in `extern (C) { declaration }`
|
||||
// Wrap the declaration in `extern (C/Windows) { declaration }`
|
||||
// Necessary for function pointers, but harmless to apply to all.
|
||||
auto decls = new AST.Dsymbols(1);
|
||||
(*decls)[0] = s;
|
||||
s = new AST.LinkDeclaration(s.loc, linkage, decls);
|
||||
const lkg = specifier.mod & MOD.x__stdcall ? LINK.windows : linkage;
|
||||
s = new AST.LinkDeclaration(s.loc, lkg, decls);
|
||||
}
|
||||
symbols.push(s);
|
||||
}
|
||||
|
@ -5860,13 +5869,15 @@ final class CParser(AST) : Parser!AST
|
|||
|
||||
const(char)* endp = &slice[length - 7];
|
||||
|
||||
AST.Dsymbols newSymbols;
|
||||
|
||||
size_t[void*] defineTab; // hash table of #define's turned into Symbol's
|
||||
// indexed by Identifier, returns index into symbols[]
|
||||
// indexed by Identifier, returns index into newSymbols[]
|
||||
// The memory for this is leaked
|
||||
|
||||
void addVar(AST.Dsymbol s)
|
||||
void addSym(AST.Dsymbol s)
|
||||
{
|
||||
//printf("addVar() %s\n", s.toChars());
|
||||
//printf("addSym() %s\n", s.toChars());
|
||||
if (auto v = s.isVarDeclaration())
|
||||
v.isCmacro(true); // mark it as coming from a C #define
|
||||
/* If it's already defined, replace the earlier
|
||||
|
@ -5874,13 +5885,22 @@ final class CParser(AST) : Parser!AST
|
|||
*/
|
||||
if (size_t* pd = cast(void*)s.ident in defineTab)
|
||||
{
|
||||
//printf("replacing %s\n", v.toChars());
|
||||
(*symbols)[*pd] = s;
|
||||
//printf("replacing %s\n", s.toChars());
|
||||
newSymbols[*pd] = s;
|
||||
return;
|
||||
}
|
||||
assert(symbols, "symbols is null");
|
||||
defineTab[cast(void*)s.ident] = symbols.length;
|
||||
symbols.push(s);
|
||||
defineTab[cast(void*)s.ident] = newSymbols.length;
|
||||
newSymbols.push(s);
|
||||
}
|
||||
|
||||
void removeSym(Identifier ident)
|
||||
{
|
||||
//printf("removeSym() %s\n", ident.toChars());
|
||||
if (size_t* pd = cast(void*)ident in defineTab)
|
||||
{
|
||||
//printf("removing %s\n", ident.toChars());
|
||||
newSymbols[*pd] = null;
|
||||
}
|
||||
}
|
||||
|
||||
while (p < endp)
|
||||
|
@ -5924,7 +5944,7 @@ final class CParser(AST) : Parser!AST
|
|||
*/
|
||||
AST.Expression e = new AST.IntegerExp(scanloc, intvalue, t);
|
||||
auto v = new AST.VarDeclaration(scanloc, t, id, new AST.ExpInitializer(scanloc, e), STC.manifest);
|
||||
addVar(v);
|
||||
addSym(v);
|
||||
++p;
|
||||
continue;
|
||||
}
|
||||
|
@ -5947,7 +5967,7 @@ final class CParser(AST) : Parser!AST
|
|||
*/
|
||||
AST.Expression e = new AST.RealExp(scanloc, floatvalue, t);
|
||||
auto v = new AST.VarDeclaration(scanloc, t, id, new AST.ExpInitializer(scanloc, e), STC.manifest);
|
||||
addVar(v);
|
||||
addSym(v);
|
||||
++p;
|
||||
continue;
|
||||
}
|
||||
|
@ -5965,7 +5985,7 @@ final class CParser(AST) : Parser!AST
|
|||
*/
|
||||
AST.Expression e = new AST.StringExp(scanloc, str[0 .. len], len, 1, postfix);
|
||||
auto v = new AST.VarDeclaration(scanloc, null, id, new AST.ExpInitializer(scanloc, e), STC.manifest);
|
||||
addVar(v);
|
||||
addSym(v);
|
||||
++p;
|
||||
continue;
|
||||
}
|
||||
|
@ -6001,7 +6021,7 @@ final class CParser(AST) : Parser!AST
|
|||
AST.TemplateParameters* tpl = new AST.TemplateParameters();
|
||||
AST.Expression constraint = null;
|
||||
auto tempdecl = new AST.TemplateDeclaration(exp.loc, id, tpl, constraint, decldefs, false);
|
||||
addVar(tempdecl);
|
||||
addSym(tempdecl);
|
||||
++p;
|
||||
continue;
|
||||
}
|
||||
|
@ -6092,7 +6112,7 @@ final class CParser(AST) : Parser!AST
|
|||
AST.Dsymbols* decldefs = new AST.Dsymbols();
|
||||
decldefs.push(fd);
|
||||
auto tempdecl = new AST.TemplateDeclaration(exp.loc, id, tpl, null, decldefs, false);
|
||||
addVar(tempdecl);
|
||||
addSym(tempdecl);
|
||||
|
||||
++p;
|
||||
continue;
|
||||
|
@ -6103,6 +6123,14 @@ final class CParser(AST) : Parser!AST
|
|||
}
|
||||
}
|
||||
}
|
||||
else if (p[0 .. 6] == "#undef")
|
||||
{
|
||||
p += 6;
|
||||
nextToken();
|
||||
//printf("undef %s\n", token.toChars());
|
||||
if (token.value == TOK.identifier)
|
||||
removeSym(token.ident);
|
||||
}
|
||||
// scan to end of line
|
||||
while (*p)
|
||||
++p;
|
||||
|
@ -6110,6 +6138,16 @@ final class CParser(AST) : Parser!AST
|
|||
scanloc.linnum = scanloc.linnum + 1;
|
||||
}
|
||||
|
||||
if (newSymbols.length)
|
||||
{
|
||||
assert(symbols, "symbols is null");
|
||||
symbols.reserve(newSymbols.length);
|
||||
|
||||
foreach (sym; newSymbols)
|
||||
if (sym) // undefined entries are null
|
||||
symbols.push(sym);
|
||||
}
|
||||
|
||||
scanloc = scanlocSave;
|
||||
eSink = save;
|
||||
defines = buf;
|
||||
|
|
|
@ -5335,7 +5335,8 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
|
|||
lowering = new DotIdExp(exp.loc, lowering, Id.object);
|
||||
|
||||
auto tbn = exp.type.nextOf();
|
||||
while (tbn.ty == Tarray)
|
||||
size_t i = nargs;
|
||||
while (tbn.ty == Tarray && --i)
|
||||
tbn = tbn.nextOf();
|
||||
auto unqualTbn = tbn.unqualify(MODFlags.wild | MODFlags.const_ |
|
||||
MODFlags.immutable_ | MODFlags.shared_);
|
||||
|
|
|
@ -868,11 +868,13 @@ Initializer initializerSemantic(Initializer init, Scope* sc, ref Type tx, NeedIn
|
|||
* by the initializer syntax. if a CInitializer has a Designator, it is probably
|
||||
* a nested anonymous struct
|
||||
*/
|
||||
if (cix.initializerList.length)
|
||||
int found;
|
||||
foreach (dix; cix.initializerList)
|
||||
{
|
||||
DesigInit dix = cix.initializerList[0];
|
||||
Designators* dlistx = dix.designatorList;
|
||||
if (dlistx && (*dlistx).length == 1 && (*dlistx)[0].ident)
|
||||
if (!dlistx)
|
||||
continue;
|
||||
if ((*dlistx).length == 1 && (*dlistx)[0].ident)
|
||||
{
|
||||
auto id = (*dlistx)[0].ident;
|
||||
foreach (k, f; sd.fields[]) // linear search for now
|
||||
|
@ -883,11 +885,18 @@ Initializer initializerSemantic(Initializer init, Scope* sc, ref Type tx, NeedIn
|
|||
si.addInit(id, dix.initializer);
|
||||
++fieldi;
|
||||
++index;
|
||||
continue Loop1;
|
||||
++found;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
error(ci.loc, "only 1 designator currently allowed for C struct field initializer `%s`", toChars(ci));
|
||||
}
|
||||
}
|
||||
|
||||
if (found == cix.initializerList.length)
|
||||
continue Loop1;
|
||||
}
|
||||
|
||||
VarDeclaration field;
|
||||
|
|
|
@ -1246,7 +1246,7 @@ Expression semanticTraits(TraitsExp e, Scope* sc)
|
|||
// @@@DEPRECATION 2.100.2
|
||||
if (auto td = s.isTemplateDeclaration())
|
||||
{
|
||||
if (td.overnext || td.overroot)
|
||||
if (td.overnext)
|
||||
{
|
||||
deprecation(e.loc, "`__traits(getAttributes)` may only be used for individual functions, not the overload set `%s`", td.ident.toChars());
|
||||
deprecationSupplemental(e.loc, "the result of `__traits(getOverloads)` may be used to select the desired function to extract attributes from");
|
||||
|
|
17
compiler/test/compilable/imports/test24511_c.c
Normal file
17
compiler/test/compilable/imports/test24511_c.c
Normal file
|
@ -0,0 +1,17 @@
|
|||
typedef void (*CFunctionPointer)();
|
||||
typedef void (__stdcall *StdCallFunctionPointer)();
|
||||
|
||||
void cFunction()
|
||||
{}
|
||||
|
||||
void __stdcall stdcallFunction()
|
||||
{}
|
||||
|
||||
void __stdcall takesCFunctionPointer(CFunctionPointer f)
|
||||
{}
|
||||
|
||||
void takesStdCallFunctionPointer(StdCallFunctionPointer f)
|
||||
{}
|
||||
|
||||
typedef void (__stdcall *StdCallFunctionPointerTakingCFunctionPointer)(CFunctionPointer f);
|
||||
typedef void (*CFunctionPointerTakingStdCallFunctionPointer)(StdCallFunctionPointer f);
|
|
@ -6,6 +6,10 @@ __stdcall int foostdcall(int a) { return a; }
|
|||
|
||||
int __stdcall foostdcall2(int a) { return a; }
|
||||
|
||||
#if _MSC_VER
|
||||
int _stdcall foostdcall3(int a) { return a; } // test issue 24509
|
||||
#endif
|
||||
|
||||
int __stdcall (*fp1)(int a) = &foostdcall;
|
||||
|
||||
int (__stdcall *fp2)(int a) = &foostdcall2;
|
||||
|
|
35
compiler/test/compilable/test24479.d
Normal file
35
compiler/test/compilable/test24479.d
Normal file
|
@ -0,0 +1,35 @@
|
|||
// https://issues.dlang.org/show_bug.cgi?id=24479
|
||||
|
||||
/*
|
||||
TEST_OUTPUT:
|
||||
---
|
||||
1
|
||||
2
|
||||
---
|
||||
*/
|
||||
|
||||
struct S
|
||||
{
|
||||
@1
|
||||
S opBinary(string op: "-")(S rhs) const pure nothrow @nogc
|
||||
{
|
||||
return rhs;
|
||||
}
|
||||
@2
|
||||
S opBinary(string op: "*")(S dur) const pure nothrow @nogc
|
||||
{
|
||||
return dur;
|
||||
}
|
||||
}
|
||||
|
||||
private enum hasExternalUDA(alias A) = is(A == External) || is(typeof(A) == External);
|
||||
|
||||
void foo()
|
||||
{
|
||||
static foreach (t; __traits(getOverloads, S, "opBinary", true))
|
||||
static foreach(attr; __traits(getAttributes, t))
|
||||
pragma(msg, attr);
|
||||
|
||||
static assert(__traits(getOverloads, S, "opBinary", true).length == 2);
|
||||
alias A = __traits(getAttributes, __traits(getOverloads, S, "opBinary", true)[1]);
|
||||
}
|
15
compiler/test/compilable/test24505.c
Normal file
15
compiler/test/compilable/test24505.c
Normal file
|
@ -0,0 +1,15 @@
|
|||
// https://issues.dlang.org/show_bug.cgi?id=24505
|
||||
|
||||
// PERMUTE_ARGS:
|
||||
|
||||
struct stat { int x; };
|
||||
|
||||
void __stat(int x, int y);
|
||||
#define stat(x, y) __stat(x, y)
|
||||
|
||||
// reversed order:
|
||||
#define stat2(x, y) __stat(x, y)
|
||||
struct stat2 { int x; };
|
||||
|
||||
#undef stat
|
||||
#undef stat2
|
28
compiler/test/compilable/test24511.d
Normal file
28
compiler/test/compilable/test24511.d
Normal file
|
@ -0,0 +1,28 @@
|
|||
// REQUIRED_ARGS: -os=windows
|
||||
// EXTRA_SOURCES: imports/test24511_c.c
|
||||
// DISABLED: osx
|
||||
// This is disabled on macOS because ld complains about _main being undefined
|
||||
// when clang attempts to preprocess the C file.
|
||||
|
||||
import test24511_c;
|
||||
|
||||
static assert(__traits(getLinkage, CFunctionPointer) == "C");
|
||||
static assert(__traits(getLinkage, StdCallFunctionPointer) == "Windows");
|
||||
static assert(__traits(getLinkage, cFunction) == "C");
|
||||
static assert(__traits(getLinkage, stdcallFunction) == "Windows");
|
||||
|
||||
static assert(__traits(getLinkage, takesCFunctionPointer) == "Windows");
|
||||
static if (is(typeof(&takesCFunctionPointer) ParamsA == __parameters))
|
||||
static assert(__traits(getLinkage, ParamsA[0]) == "C");
|
||||
|
||||
static assert(__traits(getLinkage, takesStdCallFunctionPointer) == "C");
|
||||
static if (is(typeof(&takesStdCallFunctionPointer) ParamsB == __parameters))
|
||||
static assert(__traits(getLinkage, ParamsB[0]) == "Windows");
|
||||
|
||||
static assert(__traits(getLinkage, StdCallFunctionPointerTakingCFunctionPointer) == "Windows");
|
||||
static if (is(typeof(&StdCallFunctionPointerTakingCFunctionPointer) ParamsC == __parameters))
|
||||
static assert(__traits(getLinkage, ParamsC[0]) == "C");
|
||||
|
||||
static assert(__traits(getLinkage, CFunctionPointerTakingStdCallFunctionPointer) == "C");
|
||||
static if (is(typeof(&CFunctionPointerTakingStdCallFunctionPointer) ParamsD == __parameters))
|
||||
static assert(__traits(getLinkage, ParamsD[0]) == "Windows");
|
|
@ -124,6 +124,83 @@ void test6()
|
|||
assert(t.abc[3] == 7);
|
||||
}
|
||||
|
||||
/**************************************/
|
||||
// https://issues.dlang.org/show_bug.cgi?id=24495
|
||||
struct Subitem {
|
||||
int x;
|
||||
int y;
|
||||
};
|
||||
|
||||
struct Item {
|
||||
|
||||
int a;
|
||||
|
||||
struct {
|
||||
int b1;
|
||||
struct Subitem b2;
|
||||
int b3;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
void test7() {
|
||||
|
||||
struct Item first = {
|
||||
.a = 1,
|
||||
.b1 = 2,
|
||||
.b3 = 3,
|
||||
};
|
||||
struct Item second = {
|
||||
.a = 1,
|
||||
{
|
||||
.b1 = 2,
|
||||
.b2 = { 1, 2 },
|
||||
.b3 = 3
|
||||
}
|
||||
};
|
||||
|
||||
assert(second.a == 1);
|
||||
assert(second.b1 == 2);
|
||||
assert(second.b2.x == 1);
|
||||
assert(second.b2.y == 2);
|
||||
assert(second.b3 == 3);
|
||||
}
|
||||
|
||||
|
||||
/**************************************/
|
||||
// https://issues.dlang.org/show_bug.cgi?id=24277
|
||||
struct S8
|
||||
{
|
||||
int s;
|
||||
struct
|
||||
{
|
||||
int vis;
|
||||
int count;
|
||||
int id;
|
||||
struct
|
||||
{
|
||||
int symbol;
|
||||
int state;
|
||||
} leaf;
|
||||
};
|
||||
};
|
||||
|
||||
struct S8 s8 = (struct S8) {
|
||||
.s = 10,
|
||||
{
|
||||
.count = 20,
|
||||
.id = 30,
|
||||
.leaf = {.symbol = 40, .state = 50},
|
||||
}
|
||||
};
|
||||
|
||||
void test8()
|
||||
{
|
||||
assert(s8.id == 30);
|
||||
assert(s8.leaf.symbol == 40);
|
||||
assert(s8.leaf.state == 50);
|
||||
}
|
||||
|
||||
/**************************************/
|
||||
|
||||
int main()
|
||||
|
@ -134,5 +211,7 @@ int main()
|
|||
test4();
|
||||
test5();
|
||||
test6();
|
||||
test7();
|
||||
test8();
|
||||
return 0;
|
||||
}
|
21
compiler/test/runnable/test24498.d
Normal file
21
compiler/test/runnable/test24498.d
Normal file
|
@ -0,0 +1,21 @@
|
|||
import core.memory;
|
||||
|
||||
void main()
|
||||
{
|
||||
{
|
||||
int[][] a = new int[][](2, 2);
|
||||
assert(!(GC.getAttr(a.ptr) & GC.BlkAttr.NO_SCAN));
|
||||
assert(GC.getAttr(a[0].ptr) & GC.BlkAttr.NO_SCAN);
|
||||
}
|
||||
{
|
||||
void*[][] a = new void*[][](2, 2);
|
||||
assert(!(GC.getAttr(a.ptr) & GC.BlkAttr.NO_SCAN));
|
||||
assert(!(GC.getAttr(a[0].ptr) & GC.BlkAttr.NO_SCAN));
|
||||
}
|
||||
{
|
||||
int[][][] a = new int[][][](2, 2);
|
||||
assert(!(GC.getAttr(a.ptr) & GC.BlkAttr.NO_SCAN));
|
||||
assert(!(GC.getAttr(a[0].ptr) & GC.BlkAttr.NO_SCAN));
|
||||
assert(a[0][0].ptr is null);
|
||||
}
|
||||
}
|
|
@ -526,7 +526,7 @@ Tarr _d_newarraymTX(Tarr : U[], T, U)(size_t[] dims, bool isShared=false) @trust
|
|||
|
||||
auto dim = dims[0];
|
||||
|
||||
debug(PRINTF) printf("__allocateInnerArray(ti = %p, ti.next = %p, dim = %d, ndims = %d\n", ti, ti.next, dim, dims.length);
|
||||
debug(PRINTF) printf("__allocateInnerArray(UnqT = %s, dim = %lu, ndims = %lu\n", UnqT.stringof.ptr, dim, dims.length);
|
||||
if (dims.length == 1)
|
||||
{
|
||||
auto r = _d_newarrayT!UnqT(dim, isShared);
|
||||
|
@ -534,8 +534,9 @@ Tarr _d_newarraymTX(Tarr : U[], T, U)(size_t[] dims, bool isShared=false) @trust
|
|||
}
|
||||
|
||||
auto allocSize = (void[]).sizeof * dim;
|
||||
auto info = __arrayAlloc!UnqT(allocSize);
|
||||
__setArrayAllocLength!UnqT(info, allocSize, isShared);
|
||||
// the array-of-arrays holds pointers! Don't use UnqT here!
|
||||
auto info = __arrayAlloc!(void[])(allocSize);
|
||||
__setArrayAllocLength!(void[])(info, allocSize, isShared);
|
||||
auto p = __arrayStart(info)[0 .. dim];
|
||||
|
||||
foreach (i; 0..dim)
|
||||
|
@ -579,6 +580,16 @@ unittest
|
|||
}
|
||||
}
|
||||
|
||||
// https://issues.dlang.org/show_bug.cgi?id=24436
|
||||
@system unittest
|
||||
{
|
||||
import core.memory : GC;
|
||||
|
||||
int[][] a = _d_newarraymTX!(int[][], int)([2, 2]);
|
||||
|
||||
assert(!(GC.getAttr(a.ptr) & GC.BlkAttr.NO_SCAN));
|
||||
}
|
||||
|
||||
version (D_ProfileGC)
|
||||
{
|
||||
/**
|
||||
|
|
|
@ -134,6 +134,7 @@ typedef unsigned long long __uint64_t;
|
|||
#define __ptr64
|
||||
#define __unaligned
|
||||
#define _NO_CRT_STDIO_INLINE 1
|
||||
#define _stdcall __stdcall
|
||||
|
||||
// This header disables the Windows API Annotations macros
|
||||
// Need to include sal.h to get the pragma once to prevent macro redefinition.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue