From 14e9820ddef8026797810979ba66e32696c058cc Mon Sep 17 00:00:00 2001 From: nathan Date: Thu, 27 Apr 2017 13:56:35 +0300 Subject: 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. Change-Id: I51b9ba39a48a97a8836976baf5f598ede9ba695a git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@245398 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/cp/decl2.c | 41 ++++++++++++++++++------------------ gcc/testsuite/g++.dg/cpp0x/pr79296.C | 18 ++++++++++++++++ 2 files changed, 39 insertions(+), 20 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp0x/pr79296.C diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index c4a0e854228..a9511dece51 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -2280,11 +2280,6 @@ constrain_visibility_for_template (tree decl, tree targs) 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. */ @@ -2296,25 +2291,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 @@ -2357,8 +2355,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) @@ -2388,7 +2389,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)) @@ -2405,11 +2406,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)) diff --git a/gcc/testsuite/g++.dg/cpp0x/pr79296.C b/gcc/testsuite/g++.dg/cpp0x/pr79296.C new file mode 100644 index 00000000000..1ee982c71f0 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/pr79296.C @@ -0,0 +1,18 @@ +// { dg-do compile { target c++11 } } +// { dg-require-effective-target lto } +// { dg-additional-options "-flto" } + +// PR 79296 ICE mangling local class of localized instantiation + +struct X { + template X (T const *) { + struct Z {}; + } +}; + +void Baz () +{ + struct Y { } y; + + 0, X (&y); +} -- cgit v1.2.3