As per the commentary in http://gcc.gnu.org/bugzilla/show_bug.cgi?id=19664. What is desired is to add the visibility attributes to namespace scope, in addition to class scope. So, things like: namespace std __attribute__ ((visibility ("default") )); { class foo { ... }; } when compiled with -fvisibility=hidden would hide all foo symbols, including ctor, dtor, etc.
Please, explicitally specify how you would like this to work with nested namespaces. Also, whoever implements this should also make sure it works correctly with namespace: namespace N __attribute__((visibility ("hidden"))) { template <class T> struct B { B() {} ~B() {} void foo(void) {} }; template <> struct B<int>; } template <> struct ::N::B<int> { void bar(void) {} // still hidden! }
nested namespaces should work the same as nested classes. :) Since that that doesn't seem to be defined anywhere (am I wrong, or should I open a tracker for that in bugzilla), I'd say: case 1: namespace outer __attribute__ ((visibility ("default") )) { namespace inner __attribute__ ((visibility ("hidden") )) { struct A { int i; }; } } case 2: namespace outer __attribute__ ((visibility ("hidden") )) { namespace inner __attribute__ ((visibility ("default") )) { struct B { int i; }; } } Would have the following, easy (?) semantics: hidden makes all enclosed namespaces hidden. Thus, it really doesn't make sense to nest hidden namespaces. I think the only other reasonable alternative is to say that the nearest scope's visibility attribute is the one in effect. However, I've not really looked at the way nested classes are handled. Any insights there? What ever is done, these two things should be treated consistently.
Confirmed.
*** Bug 24668 has been marked as a duplicate of this bug. ***
In addition to the current ability to put visibility attributes on file and class scope, the ability to put visibility attributes on namespace scope is desired. The syntax is straight forward extension of existing visibility attribute options. namespace test __attribute__ ((visibility("hidden"))) { struct c1 { static int s; virtual void foo() { } }; int c1::s; } Is an example. What does this mean? For definitions within namespace scope, set the symbol visibility to the nearest enclosing namespace attribute. Declarations are unaffected. Nested namespaces have the same semantics as nested classes. Ie, enclosing scope. Therefore: #define VIS_default __attribute__ ((visibility("default"))) #define VIS_hidden __attribute__ ((visibility("hidden"))) struct c1 { static int s; virtual void foo() { } struct c2 { static int s; virtual void foo() { } } VIS_default; } VIS_hidden; namespace test1 VIS_hidden { struct c1 { static int s; virtual void foo() { } }; int c1::s; namespace test2 VIS_default { struct c2 { static int s; virtual void foo() { } }; int c2::s; } } In the above, struct c2 and test1::test2::c2 both have default visibility, whereas c1 and test1::c1 both have hidden visibility. Interactions between file, namespace, and class scope are handled sanely. Ie, the same deal, nearest enclosing scope. ie: #pragma GCC visibility push(hidden) namespace test1 VIS_default { struct c1 { static int s; virtual void foo() { } }; int c1::s; struct c2 { static int s; virtual void foo() { } } VIS_hidden; int c2::s; } #pragma GCC visibility pop In the above, c1 would be default, c2 would be hidden.
Why do the examples want to have a namespace (or class) with default visibility nested within one with hidden visibility? The other way around makes sense, but this seems nonsensical. It seems to me that nested scopes ought to have less or equal visibility to their enclosing scope.
What do you mean, "less or equal visibility to their enclosing scope?" My meta-goal is to try and give namespace and class scope visibilty attributes similar meanings. Do you think this is worthwhile, possible, and do you think this is a good idea? Yeah, maybe default namespace with hidden nested makes more sense for the examples. However, wouldn't both have to be supported, anyway? These kinds of "nonsensical" examples are possible with existing visibility attributes on classes. I'm just trying to keep the other scoping mechanism in mind (class scope) when thinking about how it applies to namespaces.
Subject: Re: visibility attributes on namespace scope bkoz at gcc dot gnu dot org wrote: > What do you mean, "less or equal visibility to their enclosing scope?" Where default > protected > hidden > internal, if a class or namespace has a specified visibility, nested scopes should have the same visibility or something later in the above sequence. > My meta-goal is to try and give namespace and class scope visibilty attributes > similar meanings. Do you think this is worthwhile, possible, and do you think > this is a good idea? Yes, guess I should have said that before nitpicking the examples. > Yeah, maybe default namespace with hidden nested makes more sense for the > examples. However, wouldn't both have to be supported, anyway? Both would be supported by the simplest implementation, though we could enforce rules like the above if we wanted to. Mostly I was just puzzled that the examples in both PRs seemed inside out, and wondered if I was missing some compelling use case. Jason
Subject: Re: visibility attributes on namespace scope On 17/11/2005, at 10:15 PM, jason at redhat dot com wrote: > ------- Comment #8 from jason at redhat dot com 2005-11-18 06:15 > ------- > Subject: Re: visibility attributes on namespace scope > > bkoz at gcc dot gnu dot org wrote: >> What do you mean, "less or equal visibility to their enclosing >> scope?" > > Where default > protected > hidden > internal, if a class or namespace > has a specified visibility, nested scopes should have the same > visibility or something later in the above sequence. Although this makes sense for classes, I'm not sure it does for namespaces: namespace foo __attribute__((visibility("hidden"))) { void foo(); void bar() __attribute__((visibility("default"))); } This seems reasonable to me; the attribute on the namespace is setting a default, which is overridden on bar().
The semantics of this feature are pretty obvious for simple testcases. But since there's no One Definition Rule for namespaces, it's perfectly valid for different chunks of the same namespace to have different attributes. So, if you have: namespace Foo __attribute ((visibility ("hidden")) { void f(); } namespace Foo { void g(); } what is the visibility of Foo::g? Should the namespace extension inherit the visibility of the previous namespace definition, or should visibility attributes only affect declarations within that specific block? If the former, should we only allow attributes on the first definition of a particular namespace in a translation unit? That was my initial assumption, but then I realized that's not very composable. On the other hand, perhaps if we're going to specify visibility for a namespace, we want it to be applied consistently to everything in the namespace.
Subject: Bug 21764 Author: jason Date: Tue Mar 21 03:19:06 2006 New Revision: 112239 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=112239 Log: PR c++/21764 * c-pragma.c (visstack): Move out of handle_pragma_visibility. (push_visibility, pop_visibility): Likewise. * c-pragma.h: Declare them. * cp/name-lookup.h (struct cp_binding_level): Add has_visibility bitfield. * cp/name-lookup.c: Include c-pragma.h. (push_namespace_with_attribs): Split out from push_namespace. Push visibility if appropriate. Set TREE_PUBLIC on namespaces. (leave_scope): Pop visibility if appropriate. * cp/parser.c (cp_parser_declaration, cp_parser_namespace_name): Allow attributes on namespace declarations. PR c++/19238 * cp/decl.c (cp_finish_decl): Call determine_visibility later. (start_preparsed_function): Likewise. * cp/cp-tree.h (CP_TYPE_CONTEXT, TYPE_NAMESPACE_SCOPE_P): New macros. (TYPE_CLASS_SCOPE_P, TYPE_FUNCTION_SCOPE_P): New macros. * cp/decl2.c (determine_visibility_from_class): Split out from... (determine_visibility): ...here. Handle function scope and nested classes. (import_export_decl): Move visibility handling to determine_visibility_from_class. Added: trunk/gcc/testsuite/g++.dg/ext/visibility/local1.C trunk/gcc/testsuite/g++.dg/ext/visibility/namespace1.C Modified: trunk/gcc/ChangeLog trunk/gcc/c-pragma.c trunk/gcc/c-pragma.h trunk/gcc/cp/ChangeLog trunk/gcc/cp/cp-tree.h trunk/gcc/cp/decl.c trunk/gcc/cp/decl2.c trunk/gcc/cp/name-lookup.c trunk/gcc/cp/name-lookup.h trunk/gcc/cp/parser.c
Fixed.
Subject: Bug 21764 Author: jakub Date: Mon Aug 28 12:22:14 2006 New Revision: 116504 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=116504 Log: 2006-03-20 Jason Merrill <jason@redhat.com> PR c++/21764 * c-pragma.c (visstack): Move out of handle_pragma_visibility. (push_visibility, pop_visibility): Likewise. * c-pragma.h: Declare them. cp/ PR c++/21764, c++/19238 * decl.c (cp_finish_decl): Call determine_visibility later. (start_preparsed_function): Likewise. * cp-tree.h (CP_TYPE_CONTEXT, TYPE_NAMESPACE_SCOPE_P): New macros. (TYPE_CLASS_SCOPE_P, TYPE_FUNCTION_SCOPE_P): New macros. * name-lookup.h (struct cp_binding_level): Add has_visibility bitfield. * name-lookup.c: Include c-pragma.h. (push_namespace_with_attribs): Split out from push_namespace. Push visibility if appropriate. Set TREE_PUBLIC on namespaces. (leave_scope): Pop visibility if appropriate. * decl2.c (determine_visibility_from_class): Split out from... (determine_visibility): ...here. Handle function scope and nested classes. (import_export_decl): Move visibility handling to determine_visibility_from_class. * parser.c (cp_parser_declaration, cp_parser_namespace_name): Allow attributes on namespace declarations. Added: branches/redhat/gcc-4_1-branch/gcc/testsuite/g++.dg/ext/visibility/local1.C branches/redhat/gcc-4_1-branch/gcc/testsuite/g++.dg/ext/visibility/namespace1.C Modified: branches/redhat/gcc-4_1-branch/gcc/ChangeLog branches/redhat/gcc-4_1-branch/gcc/c-pragma.c branches/redhat/gcc-4_1-branch/gcc/c-pragma.h branches/redhat/gcc-4_1-branch/gcc/cp/ChangeLog branches/redhat/gcc-4_1-branch/gcc/cp/cp-tree.h branches/redhat/gcc-4_1-branch/gcc/cp/decl.c branches/redhat/gcc-4_1-branch/gcc/cp/decl2.c branches/redhat/gcc-4_1-branch/gcc/cp/name-lookup.c branches/redhat/gcc-4_1-branch/gcc/cp/name-lookup.h branches/redhat/gcc-4_1-branch/gcc/cp/parser.c