Hi,

On 09/03/2018 16:17, Jason Merrill wrote:
You should be able to say

   if (any_erroneous_template_args (type))
Indeed, that's what I tried to express earlier today, after a cappuccino ;)
and I don't think you need the goto; the normal logic should handle
the truncated vecs fine.
It should, otherwise something needs fixing anyway. And since by that time we are in error recovery it doesn't make any sense to micro-optimize anything. Thus, I'm re-testing (previous iteration was Ok) with the below. Ok if it passes?

Thanks,
Paolo.

///////////////////
Index: cp/cp-tree.h
===================================================================
--- cp/cp-tree.h        (revision 258381)
+++ cp/cp-tree.h        (working copy)
@@ -6558,6 +6558,7 @@ extern int processing_template_parmlist;
 extern bool dependent_type_p                   (tree);
 extern bool dependent_scope_p                  (tree);
 extern bool any_dependent_template_arguments_p  (const_tree);
+extern bool any_erroneous_template_args_p       (const_tree);
 extern bool dependent_template_p               (tree);
 extern bool dependent_template_id_p            (tree, tree);
 extern bool type_dependent_expression_p                (tree);
Index: cp/parser.c
===================================================================
--- cp/parser.c (revision 258381)
+++ cp/parser.c (working copy)
@@ -22669,6 +22669,16 @@ cp_parser_class_specifier_1 (cp_parser* parser)
       cp_default_arg_entry *e;
       tree save_ccp, save_ccr;
 
+      if (any_erroneous_template_args_p (type))
+       {
+         /* Skip default arguments, NSDMIs, etc, in order to improve
+            error recovery (c++/71169, c++/71832).  */
+         vec_safe_truncate (unparsed_funs_with_default_args, 0);
+         vec_safe_truncate (unparsed_nsdmis, 0);
+         vec_safe_truncate (unparsed_classes, 0);
+         vec_safe_truncate (unparsed_funs_with_definitions, 0);
+       }
+
       /* In a first pass, parse default arguments to the functions.
         Then, in a second pass, parse the bodies of the functions.
         This two-phased approach handles cases like:
Index: cp/pt.c
===================================================================
--- cp/pt.c     (revision 258381)
+++ cp/pt.c     (working copy)
@@ -25048,6 +25048,38 @@ any_dependent_template_arguments_p (const_tree arg
   return false;
 }
 
+/* Returns true if ARGS contains any errors.  */
+
+bool
+any_erroneous_template_args_p (const_tree args)
+{
+  int i;
+  int j;
+
+  if (args && TREE_CODE (args) != TREE_VEC)
+    {
+      if (tree ti = get_template_info (args))
+       args = TI_ARGS (ti);
+      else
+       args = NULL_TREE;
+    }
+
+  if (!args)
+    return false;
+  if (args == error_mark_node)
+    return true;
+
+  for (i = 0; i < TMPL_ARGS_DEPTH (args); ++i)
+    {
+      const_tree level = TMPL_ARGS_LEVEL (args, i + 1);
+      for (j = 0; j < TREE_VEC_LENGTH (level); ++j)
+       if (error_operand_p (TREE_VEC_ELT (level, j)))
+         return true;
+    }
+
+  return false;
+}
+
 /* Returns TRUE if the template TMPL is type-dependent.  */
 
 bool
Index: testsuite/g++.dg/cpp0x/pr71169-2.C
===================================================================
--- testsuite/g++.dg/cpp0x/pr71169-2.C  (nonexistent)
+++ testsuite/g++.dg/cpp0x/pr71169-2.C  (working copy)
@@ -0,0 +1,19 @@
+// { dg-do compile { target c++11 } }
+
+template <Preconditioner> class A {  // { dg-error "declared" }
+  template <class = int> void m_fn1() {
+    m_fn1();
+    }
+};
+
+template<typename>
+struct B
+{
+  int f(int = 0) { return 0; }
+};
+
+int main()
+{
+  B<int> b;
+  return b.f();
+}
Index: testsuite/g++.dg/cpp0x/pr71169.C
===================================================================
--- testsuite/g++.dg/cpp0x/pr71169.C    (nonexistent)
+++ testsuite/g++.dg/cpp0x/pr71169.C    (working copy)
@@ -0,0 +1,7 @@
+// { dg-do compile { target c++11 } }
+
+template <Preconditioner> class A {  // { dg-error "declared" }
+  template <class = int> void m_fn1() {
+    m_fn1();
+    }
+};
Index: testsuite/g++.dg/cpp0x/pr71832.C
===================================================================
--- testsuite/g++.dg/cpp0x/pr71832.C    (nonexistent)
+++ testsuite/g++.dg/cpp0x/pr71832.C    (working copy)
@@ -0,0 +1,7 @@
+// { dg-do compile { target c++11 } }
+
+template < typename decltype (0) > struct A  // { dg-error "expected|two or 
more" }
+{ 
+  void foo () { baz (); }
+  template < typename ... S > void baz () {}
+};

Reply via email to