20

[dcl.fct.def] p2 states:

The type of a parameter or the return type for a function definition shall not be an incomplete or abstract (possibly cv-qualified) class type in the context of the function definition unless the function is deleted.

And [class.mem] p7 states:

A class is considered a completely-defined object type (or complete type) at the closing } of the class-specifier. The class is regarded as complete within its complete-class contexts; otherwise it is regarded as incomplete within its own class member-specification.

Given this code:

struct S
{
  // S is incomplete
  S f() {  /* S is complete in a function body */ return S(); }
  // S is incomplete 
};
// S is complete

A complete-class context notably does not include the decl-specifier-seq of the function definition, nor does it include the declarator of the function, however, every compiler says this is ok. What wording allows this, as I cannot find it?

Krystian S
  • 1,586
  • 7
  • 23
  • I think it's quite clear what "The class is regarded as complete within its complete-class contexts" means. –  Aug 23 '19 at 18:47
  • @NeilButterworth if you look at the definition of what a complete-class context is http://eel.is/c++draft/class#mem-6 only the function body is included. – Krystian S Aug 23 '19 at 18:51
  • 2
    @NeilButterworth But in [*complete-class contexts*](http://eel.is/c++draft/class#mem-6) the function definition is not included, and that contains the *decl-specifier-seq* – NathanOliver Aug 23 '19 at 18:51
  • What's the question – nicomp Aug 23 '19 at 18:54
  • @nicomp What is the wording that permits using the type of the class being defined in the decl-specifier-seq and declarator of a function definition. – Krystian S Aug 23 '19 at 18:55
  • 2
    And in this [code snippet](https://godbolt.org/z/Loa0eU) `S` is incomplete again :) Seems like an oversight to me, `S` should be incomplete in the return type except when using it directly like you are. – Rakete1111 Aug 23 '19 at 19:17
  • @Rakete1111 Why not just make the entire function-definition a complete class context? Its considered to be complete in a functions noexcept-specifier (which needs to have the full class definition anyways to perform overload resolution), so why not the return type and parameters? https://godbolt.org/z/sQxSno – Krystian S Aug 23 '19 at 19:22
  • 2
    @KrystianS The current definition of complete-class context is already pain in the butt because it is unclear how to treat self-referential `noexcept`s. See https://stackoverflow.com/a/54767417/9585016 and [CWG361](http://wg21.link/cwg361). – Language Lawyer Aug 23 '19 at 19:30
  • @LanguageLawyer So what should be done? Open a defect report? – Krystian S Aug 23 '19 at 19:38
  • @KrystianS IDK. Maybe. – Language Lawyer Aug 23 '19 at 19:39
  • @LanguageLawyer I'll do so and update once it gets assigned a number. – Krystian S Aug 23 '19 at 19:41
  • If you [split the defintion from the declaration](https://godbolt.org/z/o92aYO), it should be ok, but still fails on gcc. Seems like a gcc bug? – Chris Dodd Aug 23 '19 at 20:41
  • @KrystianS you didn't update... – Language Lawyer Jul 24 '20 at 06:53

2 Answers2

7

The very first item at the referred to link:

A complete-class context of a class is a

  • function body ([dcl.fct.def.general]),

So within the function body of any method is considered a complete-class context. The "context of a function definition" is synonymous with the function body, as far as I can tell -- as opposed to the context of a function declaration, where the return type is not required to be complete.

Community
  • 1
  • 1
Chris Dodd
  • 119,907
  • 13
  • 134
  • 226
  • No, the context of the function definition is the *member-specification*. Furthermore, the function body does not include the return type or parameters of the function, see http://eel.is/c++draft/dcl.fct.def#general-1.sentence-2 – Krystian S Aug 23 '19 at 20:23
  • @KrystianS: that's the context of the function declaration, not the function definition... – Chris Dodd Aug 23 '19 at 20:36
  • No, the definition appears in the *member-specification*, therefore the context of the function definition is the *member-specification* – Krystian S Aug 23 '19 at 20:38
  • But the definition itself is just the body -- the rest is the declaration. – Chris Dodd Aug 23 '19 at 20:43
  • No, a declaration can be a definition, and is if the function-body is provided, see http://eel.is/c++draft/basic.def#2. Furthermore, with your interpretation, this would be well formed: https://godbolt.org/z/L6TINp – Krystian S Aug 23 '19 at 20:47
  • @KrystianS Confusing though the wording may be, [dcl.fct.def]/2 means to say that the completeness of the type is checked from within the function body; see [CWG1824](http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1824). – bogdan Sep 07 '19 at 00:12
  • @bogdan Ah, ok. While the intent is there, the wording does not accomplish what it intends to (perhaps it would be more appropriate to say "within the *function-body*") – Krystian S Sep 07 '19 at 03:03
  • @KrystianS In godbolt.org/z/L6TINp, `S` in the return type and `struct S {};` in the function body are 2 different types. – Language Lawyer Jul 24 '20 at 05:49
0

I think that the compiler first finds tokens lex.phases 1.7 S class (with all of its members declared) and f member function (with just declaration, which includes the return type). Then, they are analyzed.

By the time the function body of f is analyzed the S class was analyzed first and considered as complete, because it has the member-function defined (the function boby is there, will be analyzed later).

Now S is complete, f can use return S().


But it his other case:

struct S {
    decltype(S{}) f() { return S(); }
};

the compiler wants to find the type of S by decltype so as to regard the token (the return type of f) and fails because the }; class-ending is not reached yet.

Ripi2
  • 7,031
  • 1
  • 17
  • 33
  • That wording still does not make the return type or parameters of a function a complete-class context though. – Krystian S Aug 23 '19 at 20:26
  • In the 'other' case, if you move the function definition after closing `}`, gcc [still fails](https://godbolt.org/z/o92aYO), so this seems like a gcc bug – Chris Dodd Aug 23 '19 at 20:47
  • @ChrisDodd I don't think so. Gcc complains because of the reason I told, not because the body of the function. – Ripi2 Aug 23 '19 at 20:50