Skip to content
Snippets Groups Projects
Commit 198f4df0 authored by Simon Martin's avatar Simon Martin
Browse files

c++: Reject default arguments for template class friend functions [PR118319]

We segfault upon the following invalid code

=== cut here ===
template <int> struct S {
  friend void foo (int a = []{}());
};
void foo (int a) {}
int main () {
  S<0> t;
  foo ();
}
=== cut here ===

The problem is that we end up with a LAMBDA_EXPR callee in
set_flags_from_callee, and dereference its NULL_TREE
TREE_TYPE (TREE_TYPE (..)).

This patch sets the default argument to error_mark_node and gives a hard
error for template class friend functions that do not meet the
requirement in C++17 11.3.6/4 (the change is restricted to templates per
discussion with Jason).

	PR c++/118319

gcc/cp/ChangeLog:

	* decl.cc (grokfndecl): Inspect all friend function parameters.
	If it's not valid for them to have a default value and we're
	processing a template, set the default value to error_mark_node
	and give a hard error.

gcc/testsuite/ChangeLog:

	* g++.dg/parse/defarg18.C: New test.
	* g++.dg/parse/defarg18a.C: New test.
parent 98545441
No related branches found
No related tags found
No related merge requests found
...@@ -11213,14 +11213,28 @@ grokfndecl (tree ctype, ...@@ -11213,14 +11213,28 @@ grokfndecl (tree ctype,
expression, that declaration shall be a definition..." */ expression, that declaration shall be a definition..." */
if (friendp && !funcdef_flag) if (friendp && !funcdef_flag)
{ {
bool has_errored = false;
for (tree t = FUNCTION_FIRST_USER_PARMTYPE (decl); for (tree t = FUNCTION_FIRST_USER_PARMTYPE (decl);
t && t != void_list_node; t = TREE_CHAIN (t)) t && t != void_list_node; t = TREE_CHAIN (t))
if (TREE_PURPOSE (t)) if (TREE_PURPOSE (t))
{ {
permerror (DECL_SOURCE_LOCATION (decl), diagnostic_t diag_kind = DK_PERMERROR;
"friend declaration of %qD specifies default " /* For templates, mark the default argument as erroneous and give a
"arguments and isn%'t a definition", decl); hard error. */
break; if (processing_template_decl)
{
diag_kind = DK_ERROR;
TREE_PURPOSE (t) = error_mark_node;
}
if (!has_errored)
{
has_errored = true;
emit_diagnostic (diag_kind,
DECL_SOURCE_LOCATION (decl),
/*diagnostic_option_id=*/0,
"friend declaration of %qD specifies default "
"arguments and isn%'t a definition", decl);
}
} }
} }
   
......
// PR c++/118319
// { dg-do "compile" { target c++11 } }
// Template case, that used to crash.
template <int>
struct S {
friend void foo1 (int a = []{}()); // { dg-error "specifies default|only declaration" }
friend void foo3 (int a, // { dg-error "specifies default|only declaration" }
int b = []{}(),
int c = []{}());
};
void foo1 (int a) {}
void foo3 (int a, int b, int c) {}
void hello (){
S<0> t;
foo1 ();
foo3 (1, 2);
}
// Template case, that already worked.
template <int>
struct T {
friend void bar (int a = []{}()); // { dg-error "specifies default|only declaration" }
};
void hallo (){
T<0> t;
bar (); // { dg-error "not declared" }
}
// Non template case, that already worked.
struct NoTemplate {
friend void baz (int a = []{}()); // { dg-error "specifies default|could not convert" }
};
void baz (int a) {} // { dg-error "only declaration" }
void ola (){
NoTemplate t;
baz (); // { dg-error "void value not ignored" }
}
// PR c++/118319 - With -fpermissive
// { dg-do "compile" { target c++11 } }
// { dg-additional-options "-fpermissive" }
// Template case, that used to crash.
// Check that we error-out even with -fpermissive.
template <int>
struct S { // { dg-error "instantiating erroneous template" }
friend void foo1 (int a = []{}()); // { dg-warning "specifies default|only declaration" }
};
void foo1 (int a) {}
void hello (){
S<0> t;
foo1 ();
}
// Non template case, that already worked.
// Check that errors are demoted to warnings.
struct NoTemplate {
friend void baz (int a = 1); // { dg-warning "specifies default" }
};
void baz (int a) {} // { dg-warning "only declaration" }
void ola (){
NoTemplate t;
baz ();
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment