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

Fix Issue 8887 - Disallow passing static arrays by value in extern(C) ... #1215

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 16 additions & 1 deletion src/mtype.c
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -5520,6 +5520,13 @@ Type *TypeFunction::semantic(Loc loc, Scope *sc)
wildreturn = TRUE; wildreturn = TRUE;
} }


// don't return static array by value in extern(C)/extern(C++) function
if (((tf->linkage == LINKc) || (tf->linkage == LINKcpp))
&& !tf->isref && (tf->next && tf->next->toBasetype()->ty == Tsarray))
{
error(loc, "Return type (%s) cannot be returned by value in %s function", tf->next->toChars(), ((tf->linkage == LINKc) ? "extern(C)" : "extern(C++)"));
}

bool wildparams = FALSE; bool wildparams = FALSE;
if (tf->parameters) if (tf->parameters)
{ {
Expand All @@ -5533,7 +5540,6 @@ Type *TypeFunction::semantic(Loc loc, Scope *sc)
size_t dim = Parameter::dim(tf->parameters); size_t dim = Parameter::dim(tf->parameters);
for (size_t i = 0; i < dim; i++) for (size_t i = 0; i < dim; i++)
{ Parameter *fparam = Parameter::getNth(tf->parameters, i); { Parameter *fparam = Parameter::getNth(tf->parameters, i);

tf->inuse++; tf->inuse++;
fparam->type = fparam->type->semantic(loc, argsc); fparam->type = fparam->type->semantic(loc, argsc);
if (tf->inuse == 1) tf->inuse--; if (tf->inuse == 1) tf->inuse--;
Expand All @@ -5548,6 +5554,15 @@ Type *TypeFunction::semantic(Loc loc, Scope *sc)


Type *t = fparam->type->toBasetype(); Type *t = fparam->type->toBasetype();


// don't pass static array by value in extern(C) function
if (((tf->linkage == LINKc) || (tf->linkage == LINKcpp))
&& !(fparam->storageClass & (STCout | STCref))
&& (t->ty == Tsarray))
{
error(loc, "param '%s' of type (%s) cannot be passed by value in %s function",
fparam->ident->toChars(), t->toChars(), ((tf->linkage == LINKc) ? "extern(C)" : "extern(C++)"));
}

if (fparam->storageClass & (STCout | STCref | STClazy)) if (fparam->storageClass & (STCout | STCref | STClazy))
{ {
//if (t->ty == Tsarray) //if (t->ty == Tsarray)
Expand Down
12 changes: 12 additions & 0 deletions test/compilable/test8887.d
Original file line number Original file line Diff line number Diff line change
@@ -0,0 +1,12 @@
extern(C) void c_ok1(ref int[4] x);
extern(C) void c_ok2(out int[4] x);
extern(C) void c_ok3(int[4]* x);
extern(C) ref int[4] c_ok4();
extern(C) int[4]* c_ok5();
extern(C++) void c_ok7(ref int[4] x);
extern(C++) void c_ok8(out int[4] x);
extern(C++) void c_ok9(int[4]* x);
extern(C++) ref int[4] c_ok10();
extern(C++) int[4]* c_ok11();

void main() { }
19 changes: 19 additions & 0 deletions test/fail_compilation/diag8887.d
Original file line number Original file line Diff line number Diff line change
@@ -0,0 +1,19 @@
// REQUIRED_ARGS: -m32
/*
TEST_OUTPUT:
---
fail_compilation/diag8887.d(1): Error: param 'x' of type (int[4u]) cannot be passed by value in extern(C) function
fail_compilation/diag8887.d(2): Error: Return type (int[4u]) cannot be returned by value in extern(C) function
fail_compilation/diag8887.d(3): Error: param 'x' of type (int[4u]) cannot be passed by value in extern(C++) function
fail_compilation/diag8887.d(4): Error: Return type (int[4u]) cannot be returned by value in extern(C++) function
---
*/
module diag8887;

#line 1
extern(C) void fail(int[4] x);
extern(C) int[4] fail2();
extern(C++) void fail3(int[4] x);
extern(C++) int[4] fail4();

void main() { }
8 changes: 8 additions & 0 deletions test/fail_compilation/fail8887.d
Original file line number Original file line Diff line number Diff line change
@@ -0,0 +1,8 @@
module fail8887;

extern(C) void fail(int[4] x);
extern(C) int[4] fail2();
extern(C++) void fail3(int[4] x);
extern(C++) int[4] fail4();

void main() { }