44 changes: 37 additions & 7 deletions src/func.d
Original file line number Diff line number Diff line change
Expand Up @@ -4435,20 +4435,50 @@ public:
/* See if it's the default constructor
* But, template constructor should not become a default constructor.
*/
if (ad && tf.varargs == 0 && Parameter.dim(tf.parameters) == 0 && (!parent.isTemplateInstance() || parent.isTemplateMixin()))
if (ad && (!parent.isTemplateInstance() || parent.isTemplateMixin()))
{
size_t dim = Parameter.dim(tf.parameters);
StructDeclaration sd = ad.isStructDeclaration();
if (sd)
{
if (fbody || !(storage_class & STCdisable))
bool allDefaultedParams = (dim == 0) && tf.varargs == 1; // c-style: foo(...)
bool isDefCtor = dim == 0;

for (size_t i = 0; i < dim; i++)
{
error("default constructor for structs only allowed with @disable and no body");
storage_class |= STCdisable;
fbody = null;
auto arg = Parameter.getNth(tf.parameters, i);

// note: D-style variadic arguments allowed as a special-case (tf.varargs == 2)
if (i + 1 == dim && arg.defaultArg)
{
isDefCtor = true;
allDefaultedParams = true;
}
else
{
break;
}
}

if (isDefCtor)
{
if (allDefaultedParams) // only warn for now
{
warning(loc, "%s %s default constructor for structs "
"only allowed with @disable, no body, and no "
"parameters", kind(), toPrettyChars());
}
else if (fbody || !(storage_class & STCdisable) || dim)
{
error("default constructor for structs only allowed "
"with @disable, no body, and no parameters");
storage_class |= STCdisable;
fbody = null;
}
sd.noDefaultCtor = true;
}
sd.noDefaultCtor = true;
}
else
else if (dim == 0 && tf.varargs == 0)
{
ad.defaultCtor = this;
}
Expand Down
8 changes: 8 additions & 0 deletions test/compilable/compile1.d
Original file line number Diff line number Diff line change
Expand Up @@ -929,3 +929,11 @@ void test15163()
auto arr = [[0]];
func15164(arr[0])();
}

/**************************************************
3438
**************************************************/
import core.vararg;
struct S3438_1 { this(int x, int y = 1) { } }
struct S3438_2 { this(int x, ...) { } }
struct S3438_3 { this(int x, int[] arr...) { } }
2 changes: 1 addition & 1 deletion test/compilable/ddoc7795.d
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ struct TimeValue {
///
struct DateTime {
///
this(TimeValue t = TimeValue(0, 0)) {}
this(int x, TimeValue t = TimeValue(0, 0)) {}
}

void main() { }
2 changes: 1 addition & 1 deletion test/compilable/extra-files/ddoc7795.html
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ <h1>ddoc7795</h1>
<dl><dt><big><a name="DateTime"></a>struct <u>DateTime</u>;
</big></dt>
<dd><br><br>
<dl><dt><big><a name="DateTime.this"></a>this(TimeValue <i>t</i> = TimeValue(0, 0));
<dl><dt><big><a name="DateTime.this"></a>this(int <i>x</i>, TimeValue <i>t</i> = TimeValue(0, 0));
</big></dt>
<dd><br><br>
</dd>
Expand Down
5 changes: 3 additions & 2 deletions test/compilable/interpret3.d
Original file line number Diff line number Diff line change
Expand Up @@ -6708,7 +6708,7 @@ static assert(test11510());

struct MultiArray11534
{
this(size_t[] sizes...)
void set(size_t[] sizes...)
{
storage = new size_t[5];
}
Expand All @@ -6721,7 +6721,8 @@ struct MultiArray11534
}

enum test11534 = () {
auto m = MultiArray11534(3,2,1);
auto m = MultiArray11534();
m.set(3,2,1);
auto start = m.raw_ptr; //this trigger the bug
//auto start = m.storage.ptr + 1; //this obviously works
return 0;
Expand Down
20 changes: 20 additions & 0 deletions test/fail_compilation/diag3438.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// REQUIRED_ARGS: -w
/*
TEST_OUTPUT:
---
fail_compilation/diag3438.d(15): Warning: constructor diag3438.F1.this default constructor for structs only allowed with @disable, no body, and no parameters
fail_compilation/diag3438.d(16): Warning: constructor diag3438.F2.this default constructor for structs only allowed with @disable, no body, and no parameters
fail_compilation/diag3438.d(17): Warning: constructor diag3438.F3.this default constructor for structs only allowed with @disable, no body, and no parameters
fail_compilation/diag3438.d(19): Warning: constructor diag3438.F5.this default constructor for structs only allowed with @disable, no body, and no parameters
fail_compilation/diag3438.d(20): Warning: constructor diag3438.F6.this default constructor for structs only allowed with @disable, no body, and no parameters
---
*/

import core.vararg;

struct F1 { this(int x = 1) { } }
struct F2 { this(int x = 1, ...) { } }
struct F3 { this(...) { } }
struct F4 { this(int[] x...) { } } // ok
struct F5 { @disable this(int x = 1); }
struct F6 { @disable this(int x = 1) { } }
2 changes: 1 addition & 1 deletion test/fail_compilation/fail250.d
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
TEST_OUTPUT:
---
fail_compilation/fail250.d(10): Error: constructor fail250.A.this default constructor for structs only allowed with @disable and no body
fail_compilation/fail250.d(10): Error: constructor fail250.A.this default constructor for structs only allowed with @disable, no body, and no parameters
---
*/

Expand Down
2 changes: 1 addition & 1 deletion test/fail_compilation/ice14146.d
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
TEST_OUTPUT:
---
fail_compilation/ice14146.d(15): Error: constructor ice14146.Array.this default constructor for structs only allowed with @disable and no body
fail_compilation/ice14146.d(15): Error: constructor ice14146.Array.this default constructor for structs only allowed with @disable, no body, and no parameters
---
*/

Expand Down