diff --git a/compiler/src/dmd/clone.d b/compiler/src/dmd/clone.d index ca7f398ae7..e4060d4e39 100644 --- a/compiler/src/dmd/clone.d +++ b/compiler/src/dmd/clone.d @@ -1571,7 +1571,7 @@ private Statement generateCopyCtorBody(StructDeclaration sd) * `true` if one needs to be generated * `false` otherwise */ -private bool needCopyCtor(StructDeclaration sd, out bool hasCpCtor) +bool needCopyCtor(StructDeclaration sd, out bool hasCpCtor) { if (global.errors) return false; diff --git a/compiler/src/dmd/dstruct.d b/compiler/src/dmd/dstruct.d index 0e0a1f52f8..49411c6975 100644 --- a/compiler/src/dmd/dstruct.d +++ b/compiler/src/dmd/dstruct.d @@ -434,7 +434,11 @@ extern (C++) class StructDeclaration : AggregateDeclaration ispod = ThreeState.yes; - if (enclosing || postblit || dtor || hasCopyCtor) + import dmd.clone; + bool hasCpCtorLocal; + needCopyCtor(this, hasCpCtorLocal); + + if (enclosing || search(this, loc, Id.postblit) || search(this, loc, Id.dtor) || hasCpCtorLocal) { ispod = ThreeState.no; return false; diff --git a/compiler/test/compilable/issue20339.d b/compiler/test/compilable/issue20339.d new file mode 100644 index 0000000000..3d5bdd80a0 --- /dev/null +++ b/compiler/test/compilable/issue20339.d @@ -0,0 +1,44 @@ +/* +TEST_OUTPUT: +--- +4 +false +false +--- +*/ + +// https://issues.dlang.org/show_bug.cgi?id=20339 + +struct S +{ + pragma(msg, cast(int)S.sizeof); + + this(this){} + ~this(){} + + int f; +} + +static assert(__traits(isPOD, S) == false); + + +pragma(msg, __traits(isPOD, T)); + +struct T +{ + this(this){} + ~this(){} +} + +static assert(__traits(isPOD, T) == false); + + +struct U +{ + pragma(msg, __traits(isPOD, U)); + + this(this){} + ~this(){} +} + +static assert(__traits(isPOD, U) == false); diff --git a/compiler/test/runnable_cxx/extra-files/test24292.cpp b/compiler/test/runnable_cxx/extra-files/test24292.cpp new file mode 100644 index 0000000000..2fab9afbbd --- /dev/null +++ b/compiler/test/runnable_cxx/extra-files/test24292.cpp @@ -0,0 +1,46 @@ +template +struct List +{ + T* begin; +}; + +struct StructWithDestructor +{ + ~StructWithDestructor(); + + int i; +}; + +struct StructWithCopyCtor +{ + StructWithCopyCtor(); + StructWithCopyCtor(const StructWithCopyCtor &other); + + int i; +}; + +StructWithDestructor::~StructWithDestructor() +{ +} + +StructWithCopyCtor::StructWithCopyCtor() +{ +} + +StructWithCopyCtor::StructWithCopyCtor(const StructWithCopyCtor &other) : i(other.i) +{ +} + +StructWithDestructor getStructWithDestructor() +{ + StructWithDestructor r; + r.i = 12345; + return r; +} + +StructWithCopyCtor getStructWithCopyCtor() +{ + StructWithCopyCtor r; + r.i = 54321; + return r; +} diff --git a/compiler/test/runnable_cxx/test24292.d b/compiler/test/runnable_cxx/test24292.d new file mode 100644 index 0000000000..b71f925639 --- /dev/null +++ b/compiler/test/runnable_cxx/test24292.d @@ -0,0 +1,50 @@ +// EXTRA_CPP_SOURCES: test24292.cpp + +extern(C++) struct List(T) +{ + // Any of the following static ifs can trigger the problem. + static if (T.sizeof > 4) {} + static if (__traits(isZeroInit, T)) {} + static if (__traits(isPOD, T)) {} + + T* begin; +} + +extern(C++) struct StructWithDestructor +{ + ~this(); + + alias L = List!StructWithDestructor; + int i; +} + +extern(C++) struct StructWithCopyCtor +{ + this(ref const(StructWithCopyCtor)); + + alias L = List!StructWithCopyCtor; + int i; +} + +extern(D) struct StructWithPostblit +{ + this(this) {} + + alias L = List!StructWithPostblit; + int i; +} + +static assert(!__traits(isPOD, StructWithDestructor)); +static assert(!__traits(isPOD, StructWithCopyCtor)); +static assert(!__traits(isPOD, StructWithPostblit)); + +extern(C++) StructWithDestructor getStructWithDestructor(); +extern(C++) StructWithCopyCtor getStructWithCopyCtor(); + +void main() +{ + StructWithDestructor structWithDestructor = getStructWithDestructor(); + assert(structWithDestructor.i == 12345); + StructWithCopyCtor structWithCopyCtor = getStructWithCopyCtor(); + assert(structWithCopyCtor.i == 54321); +}