Commit 1fd77946 authored by jason's avatar jason
Browse files

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.


git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@129003 138bc75d-0d04-0410-961f-82ee72b054a4
parent ce2aba1e
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
* mangle.c (write_type) [TYPEOF_TYPE]: Just sorry.
......
......@@ -1364,11 +1364,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;
......@@ -3027,20 +3022,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;
......@@ -3107,38 +3141,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);
}
......
......@@ -255,11 +255,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. */
......@@ -307,10 +303,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);
......
......@@ -11475,6 +11475,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'");
......@@ -11494,9 +11495,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 `}'. */
......
// 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