Bug 21764 - visibility attributes on namespace scope
Summary: visibility attributes on namespace scope
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 4.0.0
: P2 enhancement
Target Milestone: 4.2.0
Assignee: Jason Merrill
URL:
Keywords:
: 24668 (view as bug list)
Depends on:
Blocks: 19664
  Show dependency treegraph
 
Reported: 2005-05-26 06:58 UTC by Benjamin Kosnik
Modified: 2006-03-21 16:32 UTC (History)
4 users (show)

See Also:
Host: i686-pc-linux-gnu
Target: i686-pc-linux-gnu
Build: i686-pc-linux-gnu
Known to work:
Known to fail:
Last reconfirmed: 2005-12-02 22:16:52


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Benjamin Kosnik 2005-05-26 06:58:37 UTC
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.
Comment 1 Giovanni Bajo 2005-05-26 10:18:26 UTC
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!
}
Comment 2 Benjamin Kosnik 2005-05-26 15:57:33 UTC
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.
Comment 3 Andrew Pinski 2005-05-26 20:10:04 UTC
Confirmed.
Comment 4 Andrew Pinski 2005-11-04 13:05:25 UTC
*** Bug 24668 has been marked as a duplicate of this bug. ***
Comment 5 Benjamin Kosnik 2005-11-04 17:05:50 UTC
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.
Comment 6 Jason Merrill 2005-11-17 22:55:03 UTC
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.
Comment 7 Benjamin Kosnik 2005-11-17 23:53:54 UTC
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.
Comment 8 Jason Merrill 2005-11-18 06:15:28 UTC
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
Comment 9 Geoff Keating 2005-11-18 19:39:32 UTC
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().

Comment 10 Jason Merrill 2005-12-13 06:46:09 UTC
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.
Comment 11 Jason Merrill 2006-03-21 03:19:09 UTC
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

Comment 12 Andrew Pinski 2006-03-21 16:32:34 UTC
Fixed.
Comment 13 Jakub Jelinek 2006-08-28 12:22:34 UTC
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