Bug 106613 - GCC rejects valid program involving std::invariant saying incomplete type
Summary: GCC rejects valid program involving std::invariant saying incomplete type
Status: RESOLVED DUPLICATE of bug 96645
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 12.1.1
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2022-08-14 10:52 UTC by Jason Liam
Modified: 2022-08-15 04:57 UTC (History)
0 users

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Jason Liam 2022-08-14 10:52:14 UTC
The following valid(afaik) program is rejected by gcc. https://godbolt.org/z/e73Yf4s47

```
#include <variant>

struct LiteralExpr
{
    int value;
};

template <typename T>
struct BaseSpace
{
    struct AddExpr;
    struct AddExprBox
    {
        const AddExpr &_impl;

    public:
        AddExprBox(const AddExpr &obj) {}
    };
    using Expr = std::variant<AddExprBox, LiteralExpr>;
    struct AddExpr
    {
        std::variant<AddExprBox, LiteralExpr> lhs;  // error: 'BaseSpace<T>::AddExpr::lhs' has incomplete type
    };
};

auto main() -> int
{
    auto expr = BaseSpace<int>::Expr(LiteralExpr{2});
}
```

The error says:

```
error: 'BaseSpace<T>::AddExpr::lhs' has incomplete type
   22 |         std::variant<AddExprBox, LiteralExpr> lhs;
      |                                               ^~~
In file included from <source>:1:
/opt/compiler-explorer/gcc-12.1.0/include/c++/12.1.0/variant:1336:11: note: declaration of 'class std::variant<BaseSpace<int>::AddExprBox, LiteralExpr>'
 1336 |     class variant
      |           ^~~~~~~
```
Comment 1 Andrew Pinski 2022-08-14 16:53:03 UTC
clang rejects it with the same error message.

Both GCC and clang are correct because the inner types are not complete until after the outer type is complete.
Comment 2 Jason Liam 2022-08-15 03:45:18 UTC
(In reply to Andrew Pinski from comment #1)
> clang rejects it with the same error message.
> 
> Both GCC and clang are correct because the inner types are not complete
> until after the outer type is complete.

I don't think what you said about " inner types are not complete until after the outer type is complete" is true.

In particular, the following program is well-formed. Note in the below program the nested type named `A` is complete when its `};` is encountered and not when the containing class `C`'s `};` is encountered as opposed to your claim.

```
struct C 
{
    struct A
    {

    };
    static constexpr A a{}; //this is fine because A is complete here as opposed to Andrew's claim

};
```
Comment 3 Andrew Pinski 2022-08-15 04:53:54 UTC
Dup of bug 96645.

*** This bug has been marked as a duplicate of bug 96645 ***
Comment 4 Andrew Pinski 2022-08-15 04:57:08 UTC
Also see PR 102199.

Also see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88165#c10 (which references when the inner class type is complete).

This is one of the dark corners of C++ which have issues with many things.