https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106666

            Bug ID: 106666
           Summary: Anonymous struct incorrectly allows types with
                    constructors if placed in a known sized array
           Product: gcc
           Version: 12.1.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: twmouton at gmail dot com
  Target Milestone: ---

Consider the following:
#include <iostream>
#include <memory>

struct ConstructMe {
    ConstructMe() {
        std::cout << "I have been constructed" << std::endl;
    }

    ~ConstructMe() {
        std::cout << "I have been destructed" << std::endl;
    }
};

struct Foo {
    Foo()
    : me{ std::make_unique< ConstructMe >() } {
        std::cout << "Foo" << std::endl;
    }

    struct {
        std::unique_ptr< ConstructMe > me[1];
    };
};

int main() {
        Foo f;
    return 0;
}

Compiled with g++ 12.1 using only -std=c++17.

If you remove the "[1]" after "me" the compiler will emit the error "error:
member 'std::unique_ptr<ConstructMe> Foo::<unnamed struct>::me' with
constructor not allowed in anonymous aggregate" with similar errors for the
existence of a destructor and copy-assignment operator.

To make matters worse, if you do make this an array then the object is only
constructed if it's included in the member initialization list (in above -
remove the unique_ptr and use just a plain ConstructMe to see that it is not
constructed) and it is never destructed. In the example above using unique_ptr,
this means the memory is leaked when Foo falls out of scope.

Since this is an extension, I am not sure what the correct behavior should be
but it should be consistent regardless of an object is in an array or single
member. I see two options for this.

1. Make it so the objects in an array that have
constructor/destructor/copy-assignment defined emit the same errors as not
having an array.
2. Objects with zero argument constructors should be allowed in an anonymous
struct, and should be constructed/destructed as if they were direct members of
the enclosing struct.

For what it's worth, clang seems to have chosen option 2.

Reply via email to