Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merge stable #16406

Merged
merged 10 commits into from
Apr 23, 2024
Merged
20 changes: 11 additions & 9 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
70 changes: 54 additions & 16 deletions compiler/src/dmd/cparse.d
Original file line number Diff line number Diff line change
Expand Up @@ -1919,6 +1919,14 @@
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;
}
Expand Down Expand Up @@ -2071,13 +2079,14 @@
}
}
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);
}
Expand Down Expand Up @@ -5860,27 +5869,38 @@

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
* definition
*/
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;

Check warning on line 5889 in compiler/src/dmd/cparse.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/cparse.d#L5889

Added line #L5889 was not covered by tests
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;

Check warning on line 5902 in compiler/src/dmd/cparse.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/cparse.d#L5902

Added line #L5902 was not covered by tests
}
}

while (p < endp)
Expand Down Expand Up @@ -5924,7 +5944,7 @@
*/
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;
}
Expand All @@ -5947,7 +5967,7 @@
*/
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;
}
Expand All @@ -5965,7 +5985,7 @@
*/
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;
}
Expand Down Expand Up @@ -6001,7 +6021,7 @@
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;
}
Expand Down Expand Up @@ -6092,7 +6112,7 @@
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;
Expand All @@ -6103,13 +6123,31 @@
}
}
}
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;
++p; // advance to start of next line
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;
Expand Down
3 changes: 2 additions & 1 deletion compiler/src/dmd/expressionsem.d
Original file line number Diff line number Diff line change
Expand Up @@ -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_);
Expand Down
17 changes: 13 additions & 4 deletions compiler/src/dmd/initsem.d
Original file line number Diff line number Diff line change
Expand Up @@ -868,11 +868,13 @@
* 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
Expand All @@ -883,11 +885,18 @@
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));

Check warning on line 894 in compiler/src/dmd/initsem.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/initsem.d#L894

Added line #L894 was not covered by tests
}
}

if (found == cix.initializerList.length)
continue Loop1;
}

VarDeclaration field;
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dmd/traits.d
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand Down
17 changes: 17 additions & 0 deletions compiler/test/compilable/imports/test24511_c.c
Original file line number Diff line number Diff line change
@@ -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);
4 changes: 4 additions & 0 deletions compiler/test/compilable/test22727.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 changes: 35 additions & 0 deletions compiler/test/compilable/test24479.d
Original file line number Diff line number Diff line change
@@ -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 changes: 15 additions & 0 deletions compiler/test/compilable/test24505.c
Original file line number Diff line number Diff line change
@@ -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 changes: 28 additions & 0 deletions compiler/test/compilable/test24511.d
Original file line number Diff line number Diff line change
@@ -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");
Loading
Loading