gcc 4.7.0 20110507 (experimental) in C++0x mode rejects the following code at the line marked with #: //--- struct B { friend constexpr int f(B) { return 0; } // # }; //--- "error: invalid type for parameter 1 of constexpr function 'constexpr int f(B)'" This code should be accepted. The same problem occurs with friend operators, like this case friend constexpr int operator+(B) { return 0; } within B resulting in: "error: invalid type for parameter 1 of constexpr function 'constexpr int operator+(B)'" It seems to me that this defect is *not* a dup of bug 48945, where the compiler incorrectly attempts to add a const-qualifier to a static member function. I can only assume that the compiler considers the argument as incomplete and thus not being a valid literal type, because other non-friend constexpr functions don't cause such problems, but I'm not sure. Finally, the problem does not occur, if the friend function is defined out-of-class, like so: class C { friend constexpr int g(C); }; constexpr int g(C) { return 0; }
(In reply to comment #0) > gcc 4.7.0 20110507 (experimental) in C++0x mode rejects the following code at > the line marked with #: > > //--- > struct B { > friend constexpr int f(B) { return 0; } // # > }; > //--- > > "error: invalid type for parameter 1 of constexpr function 'constexpr int > f(B)'" > > This code should be accepted. > > The same problem occurs with friend operators, like this case > > friend constexpr int operator+(B) { return 0; } > > within B resulting in: > > "error: invalid type for parameter 1 of constexpr function 'constexpr int > operator+(B)'" > Well, class "B" is incomplete in the parameter type list of f. The spec allows B to be incomplete for that parameter type (8.3.5p9), but it doesn't say anything what that means for determining whether or not the parameter has literal class type (several of the bullets of 3.9p10 require a complete class type to be checked). I don't know whether an implementation is supposed to reject the code, or supposed to wait until B is complete. Same would apply for non-static member functions. Any hints?
(In reply to comment #1) I don't think that this is intended, but I would like to await feedback from the developer group before submitting a corresponding core issue. IMO there are some core wordings in regard to type completeness that are not intended to be read strictly, e.g. 3.2 p.4 "— a function with a return type or argument type of type T is defined (3.1) [..]" can be read to disallow any of the following function definitions: struct A { A f(A a) { return a; } friend A g(A a) { return a; } }; I haven't seen a compiler who rejects this code, because they all contribute more weight to 9.2 p.2. In regard to constexpr functions the clear intention is that these can be forward-declared and are only required to be completely defined, if used in a manner that requires a constant expression. The example in 7.1.5 with the constexpr function "small" and it's usage in the constexpr constructor of pixel make this intention very clear. Now to me, the 3.2 p.4 requirement was always supposed to be interpreted as "complete as it would be required to be complete within the function body" for both function parameters and function return types within this function definition, so I don't see any reason why the compiler needs to validate the constraints on literal types at the point where the class type is still incomplete and *does* not need to be complete. If the gcc developer feedback indeed points to an intended conservative reading of 3.2 p.4 for constexpr functions as in this example I will surely require to open a core issue for this situation, because this severely constraints constexpr function definitions within classes. In this case a simple workaround is to replace the "by-value" parameter by "by-reference", but the need for such a change looks like an artifact to me. It seems to me that both functions f() and g() defined in class A above could be constexpr functions.
(In reply to comment #2) > (In reply to comment #1) > > I don't think that this is intended, but I would like to await feedback from > the developer group before submitting a corresponding core issue. IMO there are > some core wordings in regard to type completeness that are not intended to be > read strictly, e.g. 3.2 p.4 > > "— a function with a return type or argument type of type T is defined (3.1) > [..]" > > can be read to disallow any of the following function definitions: > > struct A { > A f(A a) { return a; } > friend A g(A a) { return a; } > }; > > I haven't seen a compiler who rejects this code, because they all contribute > more weight to 9.2 p.2. Within "A a" (the parameters) and within "A f" / "A g" (the return types), the class A is incomplete. Only within the function bodies, the class A is complete by 9.2p2. The compilers accept that code because of 8.3.5p9. 3.2 p4 is a non-normative big note, which can impossibly achieve the precision of covering every detail. It only provides a rough description.
(In reply to comment #0) > gcc 4.7.0 20110507 (experimental) in C++0x mode rejects the following code at > the line marked with #: > > //--- > struct B { > friend constexpr int f(B) { return 0; } // # > }; > //--- > > "error: invalid type for parameter 1 of constexpr function 'constexpr int > f(B)'" > > This code should be accepted. > I remember that Gaby (I hope I remember correctly, hehe) argued that the body of "f" is late-parsed. Hence, the argument, until after the end of definition of "B", "f" is only considered declared but not defined. I don't share that view though. That view is an implementation detail. In the language, the function marked by "#" is defined as soon as its body has been completely seen. If something else is intended, the specification needs to be explicit about this. Unless I've missed the text, it is not explicit about that.
(In reply to comment #4) > (In reply to comment #0) > > gcc 4.7.0 20110507 (experimental) in C++0x mode rejects the following code at > > the line marked with #: > > > > //--- > > struct B { > > friend constexpr int f(B) { return 0; } // # > > }; > > //--- > > > > "error: invalid type for parameter 1 of constexpr function 'constexpr int > > f(B)'" > > > > This code should be accepted. > > > > I remember that Gaby (I hope I remember correctly, hehe) argued that the body > of "f" is late-parsed. Hence, the argument, until after the end of definition > of "B", "f" is only considered declared but not defined. > Consider also this, which I think demonstrates that position: struct A { struct B; void f(B) { } struct B { }; }; I think this is ill-formed by the spec, because "B" is incomplete in f's parameter and f is defined at that point. And this is not one of the contexts that B is allowed to be incomplete by 8.3.5p9. However, clang, gcc and comeau online all accept this. Apparently, they consider "f" only declared and not defined. I would be glad if someone points me to the rule that says that "f" is only considered defined at the closing "}" of A though.
(In reply to comment #4) > (In reply to comment #0) > > gcc 4.7.0 20110507 (experimental) in C++0x mode rejects the following code at > > the line marked with #: > > > > //--- > > struct B { > > friend constexpr int f(B) { return 0; } // # > > }; > > //--- > > > > "error: invalid type for parameter 1 of constexpr function 'constexpr int > > f(B)'" > > > > This code should be accepted. > > > > I remember that Gaby (I hope I remember correctly, hehe) argued that the body > of "f" is late-parsed. Hence, the argument, until after the end of definition > of "B", "f" is only considered declared but not defined. > > I don't share that view though. That view is an implementation detail. In the > language, the function marked by "#" is defined as soon as its body has been > completely seen. If something else is intended, the specification needs to be > explicit about this. Unless I've missed the text, it is not explicit about > that. But I can live with that. Having remembered the intent as described, I see that the friend function you already showed is valid, because when the body is late parsed, and the function is then considered defined only when the enclosing class is complete, it makes sense. I wouldn't intuitively get to this result though, but I think it's an interpretation I can live with! I'm sorry for that load of nonsense in the comment boxes. I promise this is the last comment in this row of this PR! :)
Author: jason Date: Wed May 11 21:30:18 2011 New Revision: 173683 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=173683 Log: PR c++/48948 * semantics.c (validate_constexpr_fundecl): Defer checking if an argument type is being defined. (is_valid_constexpr_fn): Add defer_ok parm. (cxx_eval_call_expression): Adjust. (check_deferred_constexpr_decls): New. (literal_type_p): Make sure type isn't being defined. (ensure_literal_type_for_constexpr_object): Handle type being defined. * cp-tree.h: Declare check_deferred_constexpr_decls. * decl.c (grokfndecl): Call validate_constexpr_fundecl here. (start_preparsed_function, cp_finish_decl): Not here. * class.c (finalize_literal_type_property): Don't call validate_constexpr_fundecl. (finish_struct): Call check_deferred_constexpr_decls. * pt.c (tsubst_decl): Call validate_constexpr_fundecl. (instantiate_class_template): Call check_deferred_constexpr_decls. Added: trunk/gcc/testsuite/g++.dg/cpp0x/constexpr-friend.C trunk/gcc/testsuite/g++.dg/cpp0x/constexpr-incomplete1.C Modified: trunk/gcc/cp/ChangeLog trunk/gcc/cp/class.c trunk/gcc/cp/cp-tree.h trunk/gcc/cp/decl.c trunk/gcc/cp/pt.c trunk/gcc/cp/semantics.c trunk/gcc/testsuite/ChangeLog
Fixed.
Author: jason Date: Wed May 18 17:19:15 2011 New Revision: 173869 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=173869 Log: PR c++/48948 PR c++/49015 * class.c (finalize_literal_type_property): Do check for constexpr member functions of non-literal class. (finish_struct): Don't call check_deferred_constexpr_decls. * cp-tree.h: Don't declare it. (DECL_DEFERRED_CONSTEXPR_CHECK): Remove. * decl.c (grok_special_member_properties): Don't check it (grokfnedcl): Don't call validate_constexpr_fundecl. (start_preparsed_function): Do call it. * pt.c (tsubst_decl): Don't call it. (instantiate_class_template_1): Don't call check_deferred_constexpr_decls. * semantics.c (literal_type_p): Check for any incompleteness. (ensure_literal_type_for_constexpr_object): Likewise. (is_valid_constexpr_fn): Revert deferral changes. (validate_constexpr_fundecl): Likewise. (register_constexpr_fundef): Likewise. (check_deferred_constexpr_decls): Remove. Added: trunk/gcc/testsuite/g++.dg/cpp0x/constexpr-incomplete3.C Modified: trunk/gcc/cp/ChangeLog trunk/gcc/cp/class.c trunk/gcc/cp/cp-tree.h trunk/gcc/cp/decl.c trunk/gcc/cp/pt.c trunk/gcc/cp/semantics.c trunk/gcc/testsuite/ChangeLog trunk/gcc/testsuite/g++.dg/cpp0x/constexpr-incomplete2.C trunk/gcc/testsuite/g++.dg/cpp0x/constexpr-memfn1.C
Author: jason Date: Fri May 20 19:02:42 2011 New Revision: 173975 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=173975 Log: PR c++/48948 * class.c (finalize_literal_type_property): Only check for constexpr member functions of non-literal class. * decl.c (cp_finish_decl): Don't call validate_constexpr_fundecl. * semantics.c (literal_type_p): Call complete_type. Added: branches/gcc-4_6-branch/gcc/testsuite/g++.dg/cpp0x/constexpr-friend.C branches/gcc-4_6-branch/gcc/testsuite/g++.dg/cpp0x/constexpr-incomplete1.C branches/gcc-4_6-branch/gcc/testsuite/g++.dg/cpp0x/constexpr-incomplete2.C branches/gcc-4_6-branch/gcc/testsuite/g++.dg/cpp0x/constexpr-incomplete3.C Modified: branches/gcc-4_6-branch/gcc/cp/ChangeLog branches/gcc-4_6-branch/gcc/cp/class.c branches/gcc-4_6-branch/gcc/cp/decl.c branches/gcc-4_6-branch/gcc/cp/semantics.c branches/gcc-4_6-branch/gcc/testsuite/ChangeLog branches/gcc-4_6-branch/gcc/testsuite/g++.dg/cpp0x/constexpr-memfn1.C