It doesn't make sense to use an 'auto' parameter type outside of an
implicit template declaration; conveniently, default_arg_ok_p already
tracks whether we are in a suitable context.

As Jakub points out in the PR, this extension really shouldn't be
silently accepted, given that it still isn't part of the standard
working paper even now, after much of the Concepts TS was merged in.
So the second patch makes the pedwarn unconditional, and moves
affected testcases into the concepts directory.

Tested x86_64-pc-linux-gnu, applying to trunk.
commit 2bfb31f29c5ff65d16d549a8ced8f3312b19513e
Author: Jason Merrill <ja...@redhat.com>
Date:   Tue Mar 13 00:37:40 2018 -0400

            PR c++/84798 - ICE with auto in abstract function declarator.
    
            * parser.c (cp_parser_parameter_declaration_clause): Check
            parser->default_arg_ok_p.

diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index cdc62388973..8e8ebceb0d5 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -21198,7 +21198,10 @@ cp_parser_parameter_declaration_clause (cp_parser* parser)
 
   if (!processing_specialization
       && !processing_template_parmlist
-      && !processing_explicit_instantiation)
+      && !processing_explicit_instantiation
+      /* default_arg_ok_p tracks whether this is a parameter-clause for an
+         actual function or a random abstract declarator.  */
+      && parser->default_arg_ok_p)
     if (!current_function_decl
 	|| (current_class_type && LAMBDA_TYPE_P (current_class_type)))
       parser->auto_is_implicit_function_template_parm_p = true;
diff --git a/gcc/testsuite/g++.dg/cpp0x/auto51.C b/gcc/testsuite/g++.dg/cpp0x/auto51.C
new file mode 100644
index 00000000000..dfb08336b53
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/auto51.C
@@ -0,0 +1,9 @@
+// PR c++/84798
+// { dg-do compile { target c++11 } }
+
+template<typename T>
+struct S {
+    static constexpr T value = 0;
+};
+
+constexpr auto x = S<void(*)(auto)>::value; // { dg-error "auto" }
diff --git a/gcc/testsuite/g++.dg/cpp1y/pr60393.C b/gcc/testsuite/g++.dg/cpp1y/pr60393.C
index 27fe2b72296..2ae21ed1147 100644
--- a/gcc/testsuite/g++.dg/cpp1y/pr60393.C
+++ b/gcc/testsuite/g++.dg/cpp1y/pr60393.C
@@ -1,8 +1,7 @@
 // PR c++/60393
 // { dg-do compile { target c++14 } }
-// { dg-options "" }
 
-void (*f)(auto) + 0; // { dg-error "expected" }
+void (*f)(auto) + 0; // { dg-error "auto|expected" }
 
 struct A
 {
commit 9da596356fed08bbbaf190ff1d70fdf7e76bd47a
Author: Jason Merrill <ja...@redhat.com>
Date:   Tue Mar 13 09:57:08 2018 -0400

    Pedwarn about auto parameter even without -Wpedantic.
    
            * parser.c (cp_parser_simple_type_specifier): Pedwarn about auto
            parameter even without -Wpedantic.

diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 8e8ebceb0d5..0a82f415196 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -17049,9 +17049,9 @@ cp_parser_simple_type_specifier (cp_parser* parser,
 		     "only available with "
 		     "-std=c++14 or -std=gnu++14");
 	  else if (!flag_concepts)
-	    pedwarn (token->location, OPT_Wpedantic,
-		     "ISO C++ forbids use of %<auto%> in parameter "
-		     "declaration");
+	    pedwarn (token->location, 0,
+		     "use of %<auto%> in parameter declaration "
+		     "only available with -fconcepts");
 	}
       else
 	type = make_auto ();
diff --git a/gcc/testsuite/g++.dg/cpp1z/abbrev1.C b/gcc/testsuite/g++.dg/concepts/abbrev1.C
similarity index 70%
rename from gcc/testsuite/g++.dg/cpp1z/abbrev1.C
rename to gcc/testsuite/g++.dg/concepts/abbrev1.C
+++ b/gcc/testsuite/g++.dg/concepts/abbrev1.C
@@ -1,5 +1,6 @@
 // PR c++/64969
-// { dg-options "-std=c++17" }
+// { dg-do compile { target c++14 } }
+// { dg-additional-options "-fconcepts" }
 
 auto f1(auto x) { return *x; }
 decltype(auto) f2(auto x) { return *x; }
diff --git a/gcc/testsuite/g++.dg/cpp1z/abbrev2.C b/gcc/testsuite/g++.dg/concepts/abbrev2.C
similarity index 79%
rename from gcc/testsuite/g++.dg/cpp1z/abbrev2.C
rename to gcc/testsuite/g++.dg/concepts/abbrev2.C
+++ b/gcc/testsuite/g++.dg/concepts/abbrev2.C
@@ -1,6 +1,6 @@
 // PR c++/66197
-// { dg-do run }
-// { dg-options "-std=c++17" }
+// { dg-do run { target c++14 } }
+// { dg-additional-options "-fconcepts" }
 
 extern "C" void abort();
 
diff --git a/gcc/testsuite/g++.dg/cpp1y/fn-generic-member-ool.C b/gcc/testsuite/g++.dg/concepts/fn-generic-member-ool.C
similarity index 93%
rename from gcc/testsuite/g++.dg/cpp1y/fn-generic-member-ool.C
rename to gcc/testsuite/g++.dg/concepts/fn-generic-member-ool.C
+++ b/gcc/testsuite/g++.dg/concepts/fn-generic-member-ool.C
@@ -1,6 +1,6 @@
 // Out-of-line generic member function definitions.
 // { dg-do compile { target c++14 } }
-// { dg-options "" }
+// { dg-additional-options "-fconcepts" }
 
 struct A {
   void f(auto x);
diff --git a/gcc/testsuite/g++.dg/cpp1y/pr58500.C b/gcc/testsuite/g++.dg/concepts/pr58500.C
similarity index 69%
rename from gcc/testsuite/g++.dg/cpp1y/pr58500.C
rename to gcc/testsuite/g++.dg/concepts/pr58500.C
+++ b/gcc/testsuite/g++.dg/concepts/pr58500.C
@@ -1,6 +1,6 @@
 // PR c++/58500
 // { dg-do compile { target c++14 } }
-// { dg-options "" }
+// { dg-additional-options "-fconcepts" }
 
 struct A {};
 
diff --git a/gcc/testsuite/g++.dg/cpp1y/pr58534.C b/gcc/testsuite/g++.dg/concepts/pr58534.C
similarity index 79%
rename from gcc/testsuite/g++.dg/cpp1y/pr58534.C
rename to gcc/testsuite/g++.dg/concepts/pr58534.C
+++ b/gcc/testsuite/g++.dg/concepts/pr58534.C
@@ -1,6 +1,6 @@
 // PR c++/58534
 // { dg-do compile { target c++14 } }
-// { dg-options "" }
+// { dg-additional-options "-fconcepts" }
 
 template<typename> void foo(const auto&) {}
 
diff --git a/gcc/testsuite/g++.dg/concepts/pr58535.C b/gcc/testsuite/g++.dg/concepts/pr58535.C
new file mode 100644
index 00000000000..3e212a0ffd7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/concepts/pr58535.C
@@ -0,0 +1,7 @@
+// PR c++/58535
+// { dg-do compile { target c++14 } }
+
+struct A
+{
+  virtual void foo(auto); // { dg-error "auto|templates" }
+};
diff --git a/gcc/testsuite/g++.dg/cpp1y/pr58536.C b/gcc/testsuite/g++.dg/concepts/pr58536.C
similarity index 69%
rename from gcc/testsuite/g++.dg/cpp1y/pr58536.C
rename to gcc/testsuite/g++.dg/concepts/pr58536.C
+++ b/gcc/testsuite/g++.dg/concepts/pr58536.C
@@ -1,6 +1,6 @@
 // PR c++/58536
 // { dg-do compile { target c++14 } }
-// { dg-options "" }
+// { dg-additional-options "-fconcepts" }
 
 struct A
 {
diff --git a/gcc/testsuite/g++.dg/cpp1y/pr58548.C b/gcc/testsuite/g++.dg/concepts/pr58548.C
similarity index 69%
rename from gcc/testsuite/g++.dg/cpp1y/pr58548.C
rename to gcc/testsuite/g++.dg/concepts/pr58548.C
+++ b/gcc/testsuite/g++.dg/concepts/pr58548.C
@@ -1,6 +1,6 @@
 // PR c++/58548
 // { dg-do compile { target c++14 } }
-// { dg-options "" }
+// { dg-additional-options "-fconcepts" }
 
 void foo(auto)
 {
diff --git a/gcc/testsuite/g++.dg/cpp1y/pr58549.C b/gcc/testsuite/g++.dg/concepts/pr58549.C
similarity index 67%
rename from gcc/testsuite/g++.dg/cpp1y/pr58549.C
rename to gcc/testsuite/g++.dg/concepts/pr58549.C
+++ b/gcc/testsuite/g++.dg/concepts/pr58549.C
@@ -1,6 +1,6 @@
 // PR c++/58549
 // { dg-do compile { target c++14 } }
-// { dg-options "" }
+// { dg-additional-options "-fconcepts" }
 
 void foo(auto)
 {
diff --git a/gcc/testsuite/g++.dg/cpp1y/pr60052.C b/gcc/testsuite/g++.dg/concepts/pr60052.C
similarity index 77%
rename from gcc/testsuite/g++.dg/cpp1y/pr60052.C
rename to gcc/testsuite/g++.dg/concepts/pr60052.C
+++ b/gcc/testsuite/g++.dg/concepts/pr60052.C
@@ -1,6 +1,6 @@
 // PR c++/60052
 // { dg-do compile { target c++14 } }
-// { dg-options "" }
+// { dg-additional-options "-fconcepts" }
 
 struct A
 {
diff --git a/gcc/testsuite/g++.dg/cpp1y/pr60053.C b/gcc/testsuite/g++.dg/concepts/pr60053.C
similarity index 81%
rename from gcc/testsuite/g++.dg/cpp1y/pr60053.C
rename to gcc/testsuite/g++.dg/concepts/pr60053.C
+++ b/gcc/testsuite/g++.dg/concepts/pr60053.C
@@ -1,6 +1,6 @@
 // PR c++/60053
 // { dg-do compile { target c++14 } }
-// { dg-options "" }
+// { dg-additional-options "-fconcepts" }
 
 struct A
 {
diff --git a/gcc/testsuite/g++.dg/cpp1y/pr60064.C b/gcc/testsuite/g++.dg/concepts/pr60064.C
similarity index 82%
rename from gcc/testsuite/g++.dg/cpp1y/pr60064.C
rename to gcc/testsuite/g++.dg/concepts/pr60064.C
+++ b/gcc/testsuite/g++.dg/concepts/pr60064.C
@@ -1,6 +1,6 @@
 // PR c++/60064
 // { dg-do compile { target c++14 } }
-// { dg-options "" }
+// { dg-additional-options "-fconcepts" }
 
 class A
 {
diff --git a/gcc/testsuite/g++.dg/cpp1y/pr60065.C b/gcc/testsuite/g++.dg/concepts/pr60065.C
similarity index 85%
rename from gcc/testsuite/g++.dg/cpp1y/pr60065.C
rename to gcc/testsuite/g++.dg/concepts/pr60065.C
+++ b/gcc/testsuite/g++.dg/concepts/pr60065.C
@@ -1,6 +1,6 @@
 // PR c++/60065
 // { dg-do compile { target c++14 } }
-// { dg-options "" }
+// { dg-additional-options "-fconcepts" }
 
 template <int> void foo(auto... x);
 template <typename> void foo2(auto... x);
diff --git a/gcc/testsuite/g++.dg/cpp1y/pr60377.C b/gcc/testsuite/g++.dg/concepts/pr60377.C
similarity index 50%
rename from gcc/testsuite/g++.dg/cpp1y/pr60377.C
rename to gcc/testsuite/g++.dg/concepts/pr60377.C
+++ b/gcc/testsuite/g++.dg/concepts/pr60377.C
@@ -1,8 +1,7 @@
 // PR c++/60377
 // { dg-do compile { target c++14 } }
-// { dg-options "" }
 
-void foo(auto, void (f*)()); // { dg-error "expected" }
+void foo(auto, void (f*)()); // { dg-error "auto|expected" }
 
 struct A
 {
diff --git a/gcc/testsuite/g++.dg/cpp1y/pr60390.C b/gcc/testsuite/g++.dg/concepts/pr60390.C
similarity index 84%
rename from gcc/testsuite/g++.dg/cpp1y/pr60390.C
rename to gcc/testsuite/g++.dg/concepts/pr60390.C
+++ b/gcc/testsuite/g++.dg/concepts/pr60390.C
@@ -1,6 +1,6 @@
 // PR c++/60390
 // { dg-do compile { target c++14 } }
-// { dg-options "" }
+// { dg-additional-options "-fconcepts" }
 
 struct A
 {
diff --git a/gcc/testsuite/g++.dg/cpp1y/pr60391.C b/gcc/testsuite/g++.dg/concepts/pr60391.C
similarity index 53%
rename from gcc/testsuite/g++.dg/cpp1y/pr60391.C
rename to gcc/testsuite/g++.dg/concepts/pr60391.C
+++ b/gcc/testsuite/g++.dg/concepts/pr60391.C
@@ -1,10 +1,9 @@
 // PR c++/60391
 // { dg-do compile { target c++14 } }
-// { dg-options "" }
 
 namespace N
 {
-  int operator"" _X(auto) {} // { dg-error "invalid" }
+  int operator"" _X(auto) {} // { dg-error "auto|invalid" }
 }
 
 namespace N {}
diff --git a/gcc/testsuite/g++.dg/cpp1y/pr60573.C b/gcc/testsuite/g++.dg/concepts/pr60573.C
similarity index 90%
rename from gcc/testsuite/g++.dg/cpp1y/pr60573.C
rename to gcc/testsuite/g++.dg/concepts/pr60573.C
+++ b/gcc/testsuite/g++.dg/concepts/pr60573.C
@@ -1,6 +1,6 @@
 // PR c++/60573
 // { dg-do compile { target c++14 } }
-// { dg-options "" }
+// { dg-additional-options "-fconcepts" }
 
 struct A
 {
diff --git a/gcc/testsuite/g++.dg/cpp1y/pr80471.C b/gcc/testsuite/g++.dg/concepts/pr80471.C
similarity index 92%
rename from gcc/testsuite/g++.dg/cpp1y/pr80471.C
rename to gcc/testsuite/g++.dg/concepts/pr80471.C
+++ b/gcc/testsuite/g++.dg/concepts/pr80471.C
@@ -1,6 +1,6 @@
 // PR c++/80471
 // { dg-do compile { target c++14 } }
-// { dg-options "" }
+// { dg-additional-options "-fconcepts" }
 
 template <class, class>
 constexpr bool is_same = false;
diff --git a/gcc/testsuite/g++.dg/cpp0x/auto-60626.C b/gcc/testsuite/g++.dg/cpp0x/auto-60626.C
new file mode 100644
index 00000000000..35671924ea9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/auto-60626.C
@@ -0,0 +1,6 @@
+// PR c++/60626
+// { dg-do compile { target c++14 } }
+
+struct A {};
+
+void (*A::p)(auto) = 0;  // { dg-error "auto|static data member|template" }
diff --git a/gcc/testsuite/g++.dg/cpp1y/pr84662.C b/gcc/testsuite/g++.dg/cpp0x/auto-84662.C
similarity index 57%
rename from gcc/testsuite/g++.dg/cpp1y/pr84662.C
rename to gcc/testsuite/g++.dg/cpp0x/auto-84662.C
+++ b/gcc/testsuite/g++.dg/cpp0x/auto-84662.C
@@ -1,6 +1,5 @@
 // PR c++/84662
 // { dg-do compile { target c++14 } }
-// { dg-options "" }
 
 double b;
-a (__attribute__((c (0 && int() - ([] {} && b) || auto))));	// { dg-error "expected constructor, destructor, or type conversion before" }
+a (__attribute__((c (0 && int() - ([] {} && b) || auto))));	// { dg-error "auto|expected constructor, destructor, or type conversion before" }
diff --git a/gcc/testsuite/g++.dg/cpp1y/pr58535.C b/gcc/testsuite/g++.dg/cpp1y/pr58535.C
deleted file mode 100644
index b36be8f4a45..00000000000
--- a/gcc/testsuite/g++.dg/cpp1y/pr58535.C
+++ /dev/null
@@ -1,8 +0,0 @@
-// PR c++/58535
-// { dg-do compile { target c++14 } }
-// { dg-options "" }
-
-struct A
-{
-  virtual void foo(auto); // { dg-error "templates" }
-};
diff --git a/gcc/testsuite/g++.dg/cpp1y/pr60626.C b/gcc/testsuite/g++.dg/cpp1y/pr60626.C
deleted file mode 100644
index 311464472da..00000000000
--- a/gcc/testsuite/g++.dg/cpp1y/pr60626.C
+++ /dev/null
@@ -1,7 +0,0 @@
-// PR c++/60626
-// { dg-do compile { target c++14 } }
-// { dg-options "" }
-
-struct A {};
-
-void (*A::p)(auto) = 0;  // { dg-error "static data member|template" }
diff --git a/gcc/testsuite/g++.dg/cpp1z/decomp3.C b/gcc/testsuite/g++.dg/cpp1z/decomp3.C
index 529f3732fd5..1886cdbe90d 100644
--- a/gcc/testsuite/g++.dg/cpp1z/decomp3.C
+++ b/gcc/testsuite/g++.dg/cpp1z/decomp3.C
@@ -43,7 +43,7 @@ test (A &b, B c)
 
 void
 test2 (auto & [ p ] = bar ())		// { dg-error "'p' was not declared in this scope" }
-{
+{					// { dg-warning "auto" "" { target { ! concepts } } .-1 }
 }
 
 int arr[4];

Reply via email to