From: Jason Merrill Date: Tue, 9 Oct 2007 20:52:24 +0000 (-0400) Subject: re PR c++/32470 (fvisibility=hidden without effect in some cases) X-Git-Tag: prereleases/gcc-4.2.3-rc1~205 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=13eec6792693dd6d85605f321013f659baff873b;p=thirdparty%2Fgcc.git re PR c++/32470 (fvisibility=hidden without effect in some cases) PR c++/32470 * name-lookup.c (push_namespace_with_attrs): Fold back into... (push_namespace): Here. (handle_namespace_attrs): New fn for the attr code. (leave_scope): Don't pop_visibility. * name-lookup.h (struct cp_binding_level): Remove has_visibility. * parser.c (cp_parser_namespace_definition): Call handle_namespace_attrs and pop_visibility as appropriate. PR c++/33094 * decl.c (make_rtl_for_nonlocal_decl): It's ok for a member constant to not have DECL_EXTERNAL if it's file-local. From-SVN: r129180 --- diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 006c0b0084e3..5a8ecbcbe35b 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,18 @@ +2007-10-09 Jason Merrill + + PR c++/32470 + * name-lookup.c (push_namespace_with_attrs): Fold back into... + (push_namespace): Here. + (handle_namespace_attrs): New fn for the attr code. + (leave_scope): Don't pop_visibility. + * name-lookup.h (struct cp_binding_level): Remove has_visibility. + * parser.c (cp_parser_namespace_definition): Call + handle_namespace_attrs and pop_visibility as appropriate. + + PR c++/33094 + * decl.c (make_rtl_for_nonlocal_decl): It's ok for a member + constant to not have DECL_EXTERNAL if it's file-local. + 2007-10-07 Release Manager * GCC 4.2.2 released. diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 5b5858df7cd5..90cb6e8182b0 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -4967,7 +4967,7 @@ make_rtl_for_nonlocal_decl (tree decl, tree init, const char* asmspec) /* An in-class declaration of a static data member should be external; it is only a declaration, and not a definition. */ if (init == NULL_TREE) - gcc_assert (DECL_EXTERNAL (decl)); + gcc_assert (DECL_EXTERNAL (decl) || !TREE_PUBLIC (decl)); } /* We don't create any RTL for local variables. */ diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c index 953d9ffba308..f02bf269fad3 100644 --- a/gcc/cp/name-lookup.c +++ b/gcc/cp/name-lookup.c @@ -1348,11 +1348,6 @@ leave_scope (void) is_class_level = 0; } -#ifdef HANDLE_PRAGMA_VISIBILITY - if (scope->has_visibility) - pop_visibility (); -#endif - /* Move one nesting level up. */ current_binding_level = scope->level_chain; @@ -2982,20 +2977,59 @@ current_decl_namespace (void) return result; } -/* Push into the scope of the NAME namespace. If NAME is NULL_TREE, then we - select a name that is unique to this compilation unit. */ +/* Process any ATTRIBUTES on a namespace definition. Currently only + attribute visibility is meaningful, which is a property of the syntactic + block rather than the namespace as a whole, so we don't touch the + NAMESPACE_DECL at all. Returns true if attribute visibility is seen. */ -void -push_namespace (tree name) +bool +handle_namespace_attrs (tree ns, tree attributes) { - push_namespace_with_attribs (name, NULL_TREE); -} + tree d; + bool saw_vis = false; + + for (d = attributes; d; d = TREE_CHAIN (d)) + { + tree name = TREE_PURPOSE (d); + tree args = TREE_VALUE (d); + +#ifdef HANDLE_PRAGMA_VISIBILITY + if (is_attribute_p ("visibility", name)) + { + tree x = args ? TREE_VALUE (args) : NULL_TREE; + if (x == NULL_TREE || TREE_CODE (x) != STRING_CST || TREE_CHAIN (args)) + { + warning (OPT_Wattributes, + "%qD attribute requires a single NTBS argument", + name); + continue; + } + + if (!TREE_PUBLIC (ns)) + warning (OPT_Wattributes, + "%qD attribute is meaningless since members of the " + "anonymous namespace get local symbols", name); + + push_visibility (TREE_STRING_POINTER (x)); + saw_vis = true; + } + else +#endif + { + warning (OPT_Wattributes, "%qD attribute directive ignored", + name); + continue; + } + } -/* Same, but specify attributes to apply to the namespace. The attributes - only apply to the current namespace-body, not to any later extensions. */ + return saw_vis; +} + +/* Push into the scope of the NAME namespace. If NAME is NULL_TREE, then we + select a name that is unique to this compilation unit. */ void -push_namespace_with_attribs (tree name, tree attributes) +push_namespace (tree name) { tree d = NULL_TREE; int need_new = 1; @@ -3066,38 +3100,6 @@ push_namespace_with_attribs (tree name, tree attributes) /* Enter the name space. */ current_namespace = d; -#ifdef HANDLE_PRAGMA_VISIBILITY - /* Clear has_visibility in case a previous namespace-definition had a - visibility attribute and this one doesn't. */ - current_binding_level->has_visibility = 0; - for (d = attributes; d; d = TREE_CHAIN (d)) - { - tree name = TREE_PURPOSE (d); - tree args = TREE_VALUE (d); - tree x; - - if (! is_attribute_p ("visibility", name)) - { - warning (OPT_Wattributes, "%qs attribute directive ignored", - IDENTIFIER_POINTER (name)); - continue; - } - - x = args ? TREE_VALUE (args) : NULL_TREE; - if (x == NULL_TREE || TREE_CODE (x) != STRING_CST || TREE_CHAIN (args)) - { - warning (OPT_Wattributes, "%qs attribute requires a single NTBS argument", - IDENTIFIER_POINTER (name)); - continue; - } - - current_binding_level->has_visibility = 1; - push_visibility (TREE_STRING_POINTER (x)); - goto found; - } - found: -#endif - timevar_pop (TV_NAME_LOOKUP); } diff --git a/gcc/cp/name-lookup.h b/gcc/cp/name-lookup.h index d82445f3ac2f..f4c058996290 100644 --- a/gcc/cp/name-lookup.h +++ b/gcc/cp/name-lookup.h @@ -258,11 +258,7 @@ struct cp_binding_level GTY(()) unsigned more_cleanups_ok : 1; unsigned have_cleanups : 1; - /* Nonzero if this level has associated visibility which we should pop - when leaving the scope. */ - unsigned has_visibility : 1; - - /* 23 bits left to fill a 32-bit word. */ + /* 24 bits left to fill a 32-bit word. */ }; /* The binding level currently in effect. */ @@ -310,10 +306,10 @@ extern void pop_inner_scope (tree, tree); extern void push_binding_level (struct cp_binding_level *); extern void push_namespace (tree); -extern void push_namespace_with_attribs (tree, tree); extern void pop_namespace (void); extern void push_nested_namespace (tree); extern void pop_nested_namespace (tree); +extern bool handle_namespace_attrs (tree, tree); extern void pushlevel_class (void); extern void poplevel_class (void); extern tree pushdecl_with_scope (tree, cxx_scope *, bool); diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index a06a47143f84..179b09149038 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -10640,6 +10640,7 @@ static void cp_parser_namespace_definition (cp_parser* parser) { tree identifier, attribs; + bool has_visibility; /* Look for the `namespace' keyword. */ cp_parser_require_keyword (parser, RID_NAMESPACE, "`namespace'"); @@ -10659,9 +10660,18 @@ cp_parser_namespace_definition (cp_parser* parser) /* Look for the `{' to start the namespace. */ cp_parser_require (parser, CPP_OPEN_BRACE, "`{'"); /* Start the namespace. */ - push_namespace_with_attribs (identifier, attribs); + push_namespace (identifier); + + has_visibility = handle_namespace_attrs (current_namespace, attribs); + /* Parse the body of the namespace. */ cp_parser_namespace_body (parser); + +#ifdef HANDLE_PRAGMA_VISIBILITY + if (has_visibility) + pop_visibility (); +#endif + /* Finish the namespace. */ pop_namespace (); /* Look for the final `}'. */ diff --git a/gcc/testsuite/g++.dg/ext/visibility/anon6.C b/gcc/testsuite/g++.dg/ext/visibility/anon6.C new file mode 100644 index 000000000000..951de4964e4f --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/visibility/anon6.C @@ -0,0 +1,28 @@ +// PR c++/33094 +// { dg-final { scan-assembler "1BIiE1cE" } } +// { dg-final { scan-assembler-not "globl.*1BIiE1cE" } } +// { dg-final { scan-assembler-not "1CIiE1cE" } } + +// Test that B::c is emitted as an internal symbol, and C::c is +// not emitted. + +namespace +{ + template + class A + { + virtual T f1() { return c; } + static const T c = 0; + }; + + template + class B + { + static const T c = 0; + }; + + template const T B::c; + + template class A; + template class B; +} diff --git a/gcc/testsuite/g++.dg/ext/visibility/namespace2.C b/gcc/testsuite/g++.dg/ext/visibility/namespace2.C new file mode 100644 index 000000000000..5e6e71f8f1fa --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/visibility/namespace2.C @@ -0,0 +1,20 @@ +// PR c++/32470 + +// { dg-require-visibility } +// { dg-options "-fvisibility=hidden" } +// { dg-final { scan-hidden "_ZN4Test4testEv" } } + +namespace std __attribute__((__visibility__("default"))) { + template + class basic_streambuf + { + friend void getline(); + }; + extern template class basic_streambuf; +} + +class Test +{ + void test(); +}; +void Test::test() { }