diff mbox

[C++] 79296, ICE mangling local class

Message ID e409f248-178a-802e-c8a5-28af3094c025@acm.org
State New
Headers show

Commit Message

Nathan Sidwell Feb. 13, 2017, 5:04 p.m. UTC
On 02/06/2017 02:19 PM, Jason Merrill wrote:

>> AFAICT we cannot easily assert the condition anymore -- C++11 added the
>> ability for instantiations involving local types.
>
> That doesn't mean they have linkage, though; this type isn't subject
> to the ODR, so need_assembler_name_p should be false.
>
> I notice that for some reason TREE_PUBLIC is set on the TYPE_DECL for
> A we're trying to mangle, which might be where the problem comes in.

This patch amends determine_visibility to use the template fn context 
for a local class instantiation.  With that TREE_PUBLIC gets cleared, 
and we no longer ICE.

ok?

nathan

Comments

Jason Merrill Feb. 13, 2017, 5:26 p.m. UTC | #1
OK.

On Mon, Feb 13, 2017 at 12:04 PM, Nathan Sidwell <nathan@acm.org> wrote:
> On 02/06/2017 02:19 PM, Jason Merrill wrote:
>
>>> AFAICT we cannot easily assert the condition anymore -- C++11 added the
>>> ability for instantiations involving local types.
>>
>>
>> That doesn't mean they have linkage, though; this type isn't subject
>> to the ODR, so need_assembler_name_p should be false.
>>
>> I notice that for some reason TREE_PUBLIC is set on the TYPE_DECL for
>> A we're trying to mangle, which might be where the problem comes in.
>
>
> This patch amends determine_visibility to use the template fn context for a
> local class instantiation.  With that TREE_PUBLIC gets cleared, and we no
> longer ICE.
>
> ok?
>
> nathan
>
> --
> Nathan Sidwell
diff mbox

Patch

2017-02-13  Nathan Sidwell  <nathan@acm.org>

	PR c++/79296 - ICE mangling localized template instantiation
	* decl2.c (determine_visibility): Use template fn context for
	local class instantiations.

	PR c++/79296
	* g++.dg/cpp0x/pr79296.C: New.

Index: cp/decl2.c
===================================================================
--- cp/decl2.c	(revision 245387)
+++ cp/decl2.c	(working copy)
@@ -2225,11 +2225,6 @@  constrain_visibility_for_template (tree
 void
 determine_visibility (tree decl)
 {
-  tree class_type = NULL_TREE;
-  bool use_template;
-  bool orig_visibility_specified;
-  enum symbol_visibility orig_visibility;
-
   /* Remember that all decls get VISIBILITY_DEFAULT when built.  */
 
   /* Only relevant for names with external linkage.  */
@@ -2241,25 +2236,28 @@  determine_visibility (tree decl)
      maybe_clone_body.  */
   gcc_assert (!DECL_CLONED_FUNCTION_P (decl));
 
-  orig_visibility_specified = DECL_VISIBILITY_SPECIFIED (decl);
-  orig_visibility = DECL_VISIBILITY (decl);
+  bool orig_visibility_specified = DECL_VISIBILITY_SPECIFIED (decl);
+  enum symbol_visibility orig_visibility = DECL_VISIBILITY (decl);
 
+  /* The decl may be a template instantiation, which could influence
+     visibilty.  */
+  tree template_decl = NULL_TREE;
   if (TREE_CODE (decl) == TYPE_DECL)
     {
       if (CLASS_TYPE_P (TREE_TYPE (decl)))
-	use_template = CLASSTYPE_USE_TEMPLATE (TREE_TYPE (decl));
+	{
+	  if (CLASSTYPE_USE_TEMPLATE (TREE_TYPE (decl)))
+	    template_decl = decl;
+	}
       else if (TYPE_TEMPLATE_INFO (TREE_TYPE (decl)))
-	use_template = 1;
-      else
-	use_template = 0;
+	template_decl = decl;
     }
-  else if (DECL_LANG_SPECIFIC (decl))
-    use_template = DECL_USE_TEMPLATE (decl);
-  else
-    use_template = 0;
+  else if (DECL_LANG_SPECIFIC (decl) && DECL_USE_TEMPLATE (decl))
+    template_decl = decl;
 
   /* If DECL is a member of a class, visibility specifiers on the
      class can influence the visibility of the DECL.  */
+  tree class_type = NULL_TREE;
   if (DECL_CLASS_SCOPE_P (decl))
     class_type = DECL_CONTEXT (decl);
   else
@@ -2302,8 +2300,11 @@  determine_visibility (tree decl)
 	    }
 
 	  /* Local classes in templates have CLASSTYPE_USE_TEMPLATE set,
-	     but have no TEMPLATE_INFO, so don't try to check it.  */
-	  use_template = 0;
+	     but have no TEMPLATE_INFO.  Their containing template
+	     function does, and the local class could be constrained
+	     by that.  */
+	  if (template_decl)
+	    template_decl = fn;
 	}
       else if (VAR_P (decl) && DECL_TINFO_P (decl)
 	       && flag_visibility_ms_compat)
@@ -2333,7 +2334,7 @@  determine_visibility (tree decl)
 	      && !CLASSTYPE_VISIBILITY_SPECIFIED (TREE_TYPE (DECL_NAME (decl))))
 	    targetm.cxx.determine_class_data_visibility (decl);
 	}
-      else if (use_template)
+      else if (template_decl)
 	/* Template instantiations and specializations get visibility based
 	   on their template unless they override it with an attribute.  */;
       else if (! DECL_VISIBILITY_SPECIFIED (decl))
@@ -2350,11 +2351,11 @@  determine_visibility (tree decl)
 	}
     }
 
-  if (use_template)
+  if (template_decl)
     {
       /* If the specialization doesn't specify visibility, use the
 	 visibility from the template.  */
-      tree tinfo = get_template_info (decl);
+      tree tinfo = get_template_info (template_decl);
       tree args = TI_ARGS (tinfo);
       tree attribs = (TREE_CODE (decl) == TYPE_DECL
 		      ? TYPE_ATTRIBUTES (TREE_TYPE (decl))
Index: testsuite/g++.dg/cpp0x/pr79296.C
===================================================================
--- testsuite/g++.dg/cpp0x/pr79296.C	(revision 0)
+++ testsuite/g++.dg/cpp0x/pr79296.C	(working copy)
@@ -0,0 +1,18 @@ 
+// { dg-require-effective-target lto }
+// { dg-additional-options "-flto" }
+// { dg-do compile { target c++11 } }
+
+// PR 79296 ICE mangling local class of localized instantiation
+
+struct X {
+  template <typename T> X (T const *) {
+    struct Z {};
+  }
+};
+
+void Baz ()
+{
+  struct Y { } y;
+
+  0, X (&y);
+}