Commit 65567efa by Jason Merrill Committed by Jason Merrill

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.

From-SVN: r129003
parent dcdc83a1
2007-10-03 Jason Merrill <jason@redhat.com> 2007-10-03 Jason Merrill <jason@redhat.com>
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++/11756 PR c++/11756
* mangle.c (write_type) [TYPEOF_TYPE]: Just sorry. * mangle.c (write_type) [TYPEOF_TYPE]: Just sorry.
......
...@@ -1364,11 +1364,6 @@ leave_scope (void) ...@@ -1364,11 +1364,6 @@ leave_scope (void)
is_class_level = 0; is_class_level = 0;
} }
#ifdef HANDLE_PRAGMA_VISIBILITY
if (scope->has_visibility)
pop_visibility ();
#endif
/* Move one nesting level up. */ /* Move one nesting level up. */
current_binding_level = scope->level_chain; current_binding_level = scope->level_chain;
...@@ -3027,20 +3022,59 @@ current_decl_namespace (void) ...@@ -3027,20 +3022,59 @@ current_decl_namespace (void)
return result; return result;
} }
/* Push into the scope of the NAME namespace. If NAME is NULL_TREE, then we /* Process any ATTRIBUTES on a namespace definition. Currently only
select a name that is unique to this compilation unit. */ 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 bool
push_namespace (tree name) 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 return saw_vis;
only apply to the current namespace-body, not to any later extensions. */ }
/* 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 void
push_namespace_with_attribs (tree name, tree attributes) push_namespace (tree name)
{ {
tree d = NULL_TREE; tree d = NULL_TREE;
int need_new = 1; int need_new = 1;
...@@ -3107,38 +3141,6 @@ push_namespace_with_attribs (tree name, tree attributes) ...@@ -3107,38 +3141,6 @@ push_namespace_with_attribs (tree name, tree attributes)
/* Enter the name space. */ /* Enter the name space. */
current_namespace = d; 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); timevar_pop (TV_NAME_LOOKUP);
} }
......
...@@ -255,11 +255,7 @@ struct cp_binding_level GTY(()) ...@@ -255,11 +255,7 @@ struct cp_binding_level GTY(())
unsigned more_cleanups_ok : 1; unsigned more_cleanups_ok : 1;
unsigned have_cleanups : 1; unsigned have_cleanups : 1;
/* Nonzero if this level has associated visibility which we should pop /* 24 bits left to fill a 32-bit word. */
when leaving the scope. */
unsigned has_visibility : 1;
/* 23 bits left to fill a 32-bit word. */
}; };
/* The binding level currently in effect. */ /* The binding level currently in effect. */
...@@ -307,10 +303,10 @@ extern void pop_inner_scope (tree, tree); ...@@ -307,10 +303,10 @@ extern void pop_inner_scope (tree, tree);
extern void push_binding_level (struct cp_binding_level *); extern void push_binding_level (struct cp_binding_level *);
extern void push_namespace (tree); extern void push_namespace (tree);
extern void push_namespace_with_attribs (tree, tree);
extern void pop_namespace (void); extern void pop_namespace (void);
extern void push_nested_namespace (tree); extern void push_nested_namespace (tree);
extern void pop_nested_namespace (tree); extern void pop_nested_namespace (tree);
extern bool handle_namespace_attrs (tree, tree);
extern void pushlevel_class (void); extern void pushlevel_class (void);
extern void poplevel_class (void); extern void poplevel_class (void);
extern tree pushdecl_with_scope (tree, cxx_scope *, bool); extern tree pushdecl_with_scope (tree, cxx_scope *, bool);
......
...@@ -11475,6 +11475,7 @@ static void ...@@ -11475,6 +11475,7 @@ static void
cp_parser_namespace_definition (cp_parser* parser) cp_parser_namespace_definition (cp_parser* parser)
{ {
tree identifier, attribs; tree identifier, attribs;
bool has_visibility;
/* Look for the `namespace' keyword. */ /* Look for the `namespace' keyword. */
cp_parser_require_keyword (parser, RID_NAMESPACE, "`namespace'"); cp_parser_require_keyword (parser, RID_NAMESPACE, "`namespace'");
...@@ -11494,9 +11495,18 @@ cp_parser_namespace_definition (cp_parser* parser) ...@@ -11494,9 +11495,18 @@ cp_parser_namespace_definition (cp_parser* parser)
/* Look for the `{' to start the namespace. */ /* Look for the `{' to start the namespace. */
cp_parser_require (parser, CPP_OPEN_BRACE, "`{'"); cp_parser_require (parser, CPP_OPEN_BRACE, "`{'");
/* Start the namespace. */ /* 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. */ /* Parse the body of the namespace. */
cp_parser_namespace_body (parser); cp_parser_namespace_body (parser);
#ifdef HANDLE_PRAGMA_VISIBILITY
if (has_visibility)
pop_visibility ();
#endif
/* Finish the namespace. */ /* Finish the namespace. */
pop_namespace (); pop_namespace ();
/* Look for the final `}'. */ /* Look for the final `}'. */
......
// PR c++/32470
// { dg-require-visibility }
// { dg-options "-fvisibility=hidden" }
// { dg-final { scan-hidden "_ZN4Test4testEv" } }
namespace std __attribute__((__visibility__("default"))) {
template<typename _CharT>
class basic_streambuf
{
friend void getline();
};
extern template class basic_streambuf<char>;
}
class Test
{
void test();
};
void Test::test() { }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment