[Bug c++/111923] default argument is not treated as a complete-class context of a class

2024-02-03 Thread jens.maurer at gmx dot net via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111923

Jens Maurer  changed:

   What|Removed |Added

 CC||jens.maurer at gmx dot net

--- Comment #12 from Jens Maurer  ---
In general, we want to be rather careful that the layout of the non-static data
members of a class cannot depend on properties of other non-static data members
that are visible due to some "complete class" rules.

Otherwise, it's way too easy to construct cycles.

[Bug c++/111923] default argument is not treated as a complete-class context of a class

2023-10-24 Thread stsp at users dot sourceforge.net via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111923

--- Comment #11 from Stas Sergeev  ---
So if I understand correctly, before
your proposal the following code was
conforming:

template 
struct B {
static constexpr int off = O();
};

struct A {
char a;
B<[]() static constexpr ->int { return offsetof(A, b); }> b;
};

due to 7.1 (function body) + note4 for
closure sub-class.
Do you know any specific reason why that
code should be disallowed, rather than
supported per the current standard?
After reinterpret_cast is constexpr was
also disallowed, it became quite challenging
to come up with the work-around.

[Bug c++/111923] default argument is not treated as a complete-class context of a class

2023-10-24 Thread stsp at users dot sourceforge.net via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111923

--- Comment #10 from Stas Sergeev  ---
OMG, not what I intended to get. :(
All I need is to use offsetof() in templates.
Last time I started to use reinterpret_cast
for that, you disallowed reinterpret_cast in
constexpr context. Now this...
Why is it such a big deal to disallow every
possible loop-hole for the use of offsetof()
in templates?

[Bug c++/111923] default argument is not treated as a complete-class context of a class

2023-10-24 Thread richard-gccbugzilla at metafoo dot co.uk via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111923

--- Comment #9 from Richard Smith  ---
I don't think we intended for default arguments of class-scope lambdas to get
the same complete-class context treatment as default argument of member
functions, but the standard wording does currently seem to suggest that they do
get that treatment.

Filed https://github.com/cplusplus/CWG/issues/449 to suggest the standard
wording be fixed to match the implementations.

[Bug c++/111923] default argument is not treated as a complete-class context of a class

2023-10-24 Thread stsp at users dot sourceforge.net via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111923

--- Comment #8 from Stas Sergeev  ---
Added a few experts who can probably
answer that. While I do not doubt that
Andrew is right, I am sure having the
properly spelled explanation will help.

[Bug c++/111923] default argument is not treated as a complete-class context of a class

2023-10-23 Thread stsp at users dot sourceforge.net via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111923

--- Comment #7 from Stas Sergeev  ---
Also I verified your assumption in
comment #5 by this code:

struct A {
struct dummy {
static constexpr const int foo(const int off = offsetof(A, a)) { return
off; }
static constexpr const int operator()() { return foo(); }
};
static constexpr const int (*off_p)() = ::operator();

int t[off_p()];
char a;
};

It says:

error: size of array ‘t’ is not an integral constant-expression
   11 | int t[off_p()];

So it seems, "constexpr const" is not
enough to alter the structure size, so
your fears about that were likely wrong.

So could you please explain why note4 doesn't
apply to the nested closure type? Unless
there is a consistent explanation, the
chances are that the bug is missed. :(

[Bug c++/111923] default argument is not treated as a complete-class context of a class

2023-10-22 Thread stsp at users dot sourceforge.net via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111923

--- Comment #6 from Stas Sergeev  ---
(In reply to Andrew Pinski from comment #5)
> Nope, lamdba's are not a nested class.

But according to this:
https://timsong-cpp.github.io/cppwp/n3337/expr.prim.lambda#3
The type of the lambda-expression (which is also the type of the closure
object) is a unique, unnamed non-union class type — called the closure type —
whose properties are described below. This class type is not an aggregate
([dcl.init.aggr]). The closure type is declared in the smallest block scope,
class scope, or namespace scope that contains the corresponding
lambda-expression.

So am I right that defining lambda
in class A, means defining it in a
class's scope? In which case note4
should apply? What am I missing?

Additionally I've got this to compile:

struct A {
struct dummy {
static constexpr int foo(int off = offsetof(A, a)) { return off; }
static constexpr int operator()() { return foo(); }
};
static constexpr int (*off_p)() = ::operator();

int x;
char a;
};

Seems like note4 applies in that case.
But it should be very similar to the
"closure type" described above...

[Bug c++/111923] default argument is not treated as a complete-class context of a class

2023-10-22 Thread pinskia at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111923

--- Comment #5 from Andrew Pinski  ---
(In reply to Stas Sergeev from comment #4)
> (In reply to Andrew Pinski from comment #3)
> > One more note, default argument clause does not apply here as the it is not
> > an argument of a method of that class but rather a different context (the
> > lamdba definition context).
> 
> Yes, but doesn't this apply to the note4?
> [Note 4: A complete-class context of a nested class is also a complete-class
> context of any enclosing class, if the nested class is defined within the
> member-specification of the enclosing class.
> — end note]
> 
> Isn't lambda an instance of a nested class here?

Nope, lamdba's are not a nested class.

> 
> > int off_p = offsetof(A, a);
> > is well formed due to it being a DMI.
> 
> Thanks for info.
> Do you happen to know the particular reason
> why the standard disallows this for static
> member? Shouldn't that be a DR?

Considering all compilers agree, it is not usually a defect report.
I also don't see how this would work in really because you could use a `static
constexpr` as an size for an array.

That is:
```
#include 
struct A {
static constexpr int (*off_p)(int p) =
[](int off = offsetof(A, a))  { return off; };
int t[off_p(1)];
char a;
};
```

[Bug c++/111923] default argument is not treated as a complete-class context of a class

2023-10-22 Thread stsp at users dot sourceforge.net via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111923

--- Comment #4 from Stas Sergeev  ---
(In reply to Andrew Pinski from comment #3)
> One more note, default argument clause does not apply here as the it is not
> an argument of a method of that class but rather a different context (the
> lamdba definition context).

Yes, but doesn't this apply to the note4?
[Note 4: A complete-class context of a nested class is also a complete-class
context of any enclosing class, if the nested class is defined within the
member-specification of the enclosing class.
— end note]

Isn't lambda an instance of a nested class here?

> int off_p = offsetof(A, a);
> is well formed due to it being a DMI.

Thanks for info.
Do you happen to know the particular reason
why the standard disallows this for static
member? Shouldn't that be a DR?

[Bug c++/111923] default argument is not treated as a complete-class context of a class

2023-10-22 Thread pinskia at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111923

--- Comment #3 from Andrew Pinski  ---
One more note, default argument clause does not apply here as the it is not an
argument of a method of that class but rather a different context (the lamdba
definition context).

[Bug c++/111923] default argument is not treated as a complete-class context of a class

2023-10-22 Thread pinskia at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111923

Andrew Pinski  changed:

   What|Removed |Added

 Status|UNCONFIRMED |RESOLVED
 Resolution|--- |INVALID

--- Comment #2 from Andrew Pinski  ---
For the non-static case, "default member initializer" applies.

That is:
```
#include 
struct A {
char a;
static constexpr int off_p = offsetof(A, a);
};
```

is illformed too.

But
```
#include 
struct A {
char a;
int off_p = offsetof(A, a);
};
```
is well formed due to it being a DMI.

[Bug c++/111923] default argument is not treated as a complete-class context of a class

2023-10-22 Thread pinskia at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111923

--- Comment #1 from Andrew Pinski  ---
clang rejects it for the same reason ...

So does MSVC .