expression, that declaration shall be a definition..." */
if (friendp && !funcdef_flag)
{
+ bool has_errored = false;
for (tree t = FUNCTION_FIRST_USER_PARMTYPE (decl);
t && t != void_list_node; t = TREE_CHAIN (t))
if (TREE_PURPOSE (t))
{
- permerror (DECL_SOURCE_LOCATION (decl),
- "friend declaration of %qD specifies default "
- "arguments and isn%'t a definition", decl);
- break;
+ diagnostic_t diag_kind = DK_PERMERROR;
+ /* For templates, mark the default argument as erroneous and give a
+ hard error. */
+ 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);
+ }
}
}
--- /dev/null
+// 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" }
+}
--- /dev/null
+// 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 ();
+}