This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[C++ PATCH] PR 79091, ICE with unnamed enum mangle


Jason,
in r241944:
2016-11-07  Jason Merrill  <jason@redhat.com>

	Implement P0012R1, Make exception specifications part of the type
	system.

You increment processing_template_decl around the mangling of a template function decl. AFAICT, that's so that nothrow_spec_p doesn't explode at:
  gcc_assert (processing_template_decl
	      || TREE_PURPOSE (spec) == error_mark_node);
when called from the mangler at:
  if (nothrow_spec_p (spec))
    write_string ("Do");
  else if (TREE_PURPOSE (spec))
    ....

the trouble is that's now causing no_linkage_check to bail out early with:
  if (processing_template_decl)
    return NULL_TREE;

thus triggering the assert:
     gcc_assert (no_linkage_check (type, /*relaxed_p=*/true));
      /* Just use the old mangling at namespace scope.  */

It seems to me risky to have processsing_template_decl incremented, as no_linkage_check is called from a number of places in the mangler. Thus the attached patch, which adds a default arg to nothrow_spec_p to tell it to be a little more lenient.

In the old days, I'd've made nothrow_spec_p an asserting wrapper for a non-asserting function, and called that non-asserting function from the mangler. But we can use default arg magic to avoid adjusting all the other call sites. I'm fine with doing it the wrapper way, if you'd prefer.

ok?

--
Nathan Sidwell
2017-01-17  Nathan Sidwell  <nathan@acm.org>

	cp/
	PR c++/79091
	* cp-tree.h (nothrow_spec_p): add defaulted arg.
	* except.c (nothrow_spec_p): add unresolved_ok arg.
	* mangle.c (write_exception_spec): adjust nothrow_spec_p call.
	(write_encoding): don't increment processing_template_decl around
	encoding.

	testsuite/
	PR c++/79091
	* g++.dg/pr79091.C: New.

Index: cp/cp-tree.h
===================================================================
--- cp/cp-tree.h	(revision 244535)
+++ cp/cp-tree.h	(working copy)
@@ -5990,7 +5990,7 @@ extern void check_handlers			(tree);
 extern tree finish_noexcept_expr		(tree, tsubst_flags_t);
 extern bool expr_noexcept_p			(tree, tsubst_flags_t);
 extern void perform_deferred_noexcept_checks	(void);
-extern bool nothrow_spec_p			(const_tree);
+extern bool nothrow_spec_p			(const_tree, bool = false);
 extern bool type_noexcept_p			(const_tree);
 extern bool type_throw_all_p			(const_tree);
 extern tree build_noexcept_spec			(tree, int);
Index: cp/except.c
===================================================================
--- cp/except.c	(revision 244535)
+++ cp/except.c	(working copy)
@@ -1137,10 +1137,12 @@ expr_noexcept_p (tree expr, tsubst_flags
     return true;
 }
 
-/* Return true iff SPEC is throw() or noexcept(true).  */
+/* Return true iff SPEC is throw() or noexcept(true).  UNRESOLVED_OK
+   is true if it's ok to have an unresolved noexcept spec.  That
+   happens during mangling of a template instantation.  */
 
 bool
-nothrow_spec_p (const_tree spec)
+nothrow_spec_p (const_tree spec, bool unresolved_ok)
 {
   gcc_assert (!DEFERRED_NOEXCEPT_SPEC_P (spec));
   if (spec == NULL_TREE
@@ -1150,7 +1152,8 @@ nothrow_spec_p (const_tree spec)
   if (TREE_PURPOSE (spec) == NULL_TREE
       || spec == noexcept_true_spec)
     return true;
-  gcc_assert (processing_template_decl
+  gcc_assert (unresolved_ok
+	      || processing_template_decl
 	      || TREE_PURPOSE (spec) == error_mark_node);
   return false;
 }
Index: cp/mangle.c
===================================================================
--- cp/mangle.c	(revision 244535)
+++ cp/mangle.c	(working copy)
@@ -366,7 +366,7 @@ write_exception_spec (tree spec)
       return;
     }
 
-  if (nothrow_spec_p (spec))
+  if (nothrow_spec_p (spec, true))
     write_string ("Do");
   else if (TREE_PURPOSE (spec))
     {
@@ -829,7 +829,6 @@ write_encoding (const tree decl)
 
       if (tmpl)
 	{
-	  ++processing_template_decl;
 	  fn_type = get_mostly_instantiated_function_type (decl);
 	  /* FN_TYPE will not have parameter types for in-charge or
 	     VTT parameters.  Therefore, we pass NULL_TREE to
@@ -846,9 +845,6 @@ write_encoding (const tree decl)
       write_bare_function_type (fn_type,
 				mangle_return_type_p (decl),
 				d);
-
-      if (tmpl)
-	--processing_template_decl;
     }
 }
 
Index: testsuite/g++.dg/pr79091.C
===================================================================
--- testsuite/g++.dg/pr79091.C	(revision 0)
+++ testsuite/g++.dg/pr79091.C	(working copy)
@@ -0,0 +1,25 @@
+// PR 79091 ICE mangling an unnamed enum in a tempate instantiation.
+
+enum  {
+  One = 1
+};
+
+template<int Options>
+class Matrix {};
+
+template<int Dim>
+Matrix<Dim ? One : 0> *Bar ()
+{
+  return 0;
+}
+
+template<int Opt> 
+Matrix<Opt> *Baz ()
+{
+  return 0;
+}
+
+bool Foo ()
+{
+  return Baz<1> () == Bar<1> ();
+}

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]