aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2007-10-04 04:48:23 -0400
committerJason Merrill <jason@gcc.gnu.org>2007-10-04 04:48:23 -0400
commit65567efaa82178fcfe63bee2c81f06a541cd72a4 (patch)
treebae096b4fe2cf8e3db8b3a02fa456bfff47ef358
parentdcdc83a1857653c02c8997e5787c6a41244bdb95 (diff)
downloadgcc-65567efaa82178fcfe63bee2c81f06a541cd72a4.zip
gcc-65567efaa82178fcfe63bee2c81f06a541cd72a4.tar.gz
gcc-65567efaa82178fcfe63bee2c81f06a541cd72a4.tar.bz2
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
-rw-r--r--gcc/cp/ChangeLog9
-rw-r--r--gcc/cp/name-lookup.c94
-rw-r--r--gcc/cp/name-lookup.h8
-rw-r--r--gcc/cp/parser.c12
-rw-r--r--gcc/testsuite/g++.dg/ext/visibility/namespace2.C20
5 files changed, 90 insertions, 53 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 2e33534..0cec087 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,5 +1,14 @@
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.
diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
index 70a395b..a7bb710 100644
--- a/gcc/cp/name-lookup.c
+++ b/gcc/cp/name-lookup.c
@@ -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);
}
diff --git a/gcc/cp/name-lookup.h b/gcc/cp/name-lookup.h
index 88551f2..7da57be 100644
--- a/gcc/cp/name-lookup.h
+++ b/gcc/cp/name-lookup.h
@@ -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);
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index ede0d7e..3720b55 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -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 `}'. */
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 0000000..5e6e71f
--- /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<typename _CharT>
+ class basic_streambuf
+ {
+ friend void getline();
+ };
+ extern template class basic_streambuf<char>;
+}
+
+class Test
+{
+ void test();
+};
+void Test::test() { }