aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2011-11-07 12:51:40 -0500
committerJason Merrill <jason@gcc.gnu.org>2011-11-07 12:51:40 -0500
commit6d87092d196c96ef596c7877b40409d00af6ee7a (patch)
treee9aa9f3cd40d0c2eafea7c00b8df253911a81565 /gcc
parentc7e6757f2a0c3c391bd71d4ddb85843170377ce5 (diff)
downloadgcc-6d87092d196c96ef596c7877b40409d00af6ee7a.zip
gcc-6d87092d196c96ef596c7877b40409d00af6ee7a.tar.gz
gcc-6d87092d196c96ef596c7877b40409d00af6ee7a.tar.bz2
re PR c++/35688 (template visibility not overridden by template arguments)
PR c++/35688 * decl2.c (constrain_visibility): Return void. Add tmpl parm which gives the constraint priority over an attribute. (constrain_visibility_for_template, determine_visibility): Adjust. * pt.c (instantiate_class_template_1): Call determine_visibility. From-SVN: r181102
Diffstat (limited to 'gcc')
-rw-r--r--gcc/c-family/ChangeLog5
-rw-r--r--gcc/c-family/c-common.c27
-rw-r--r--gcc/c-family/c-common.h1
-rw-r--r--gcc/cp/ChangeLog6
-rw-r--r--gcc/cp/decl2.c27
-rw-r--r--gcc/cp/pt.c2
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/g++.dg/ext/visibility/template8.C26
8 files changed, 65 insertions, 34 deletions
diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog
index 7b30b3b..04134ec 100644
--- a/gcc/c-family/ChangeLog
+++ b/gcc/c-family/ChangeLog
@@ -1,3 +1,8 @@
+2011-11-07 Jason Merrill <jason@redhat.com>
+
+ PR c++/35688
+ * c-common.c, c-common.h: Revert yesterday's changes.
+
2011-11-06 Jason Merrill <jason@redhat.com>
PR c++/35688
diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index 92fb363..0329bc7 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -7073,22 +7073,6 @@ handle_visibility_attribute (tree *node, tree name, tree args,
return NULL_TREE;
}
-/* Returns true iff DECL actually has visibility specified by an attribute.
- We check for an explicit attribute, rather than just checking
- DECL_VISIBILITY_SPECIFIED, to distinguish the use of an attribute from
- the use of a "#pragma GCC visibility push(...)"; in the latter case we
- still want other considerations to be able to overrule the #pragma. */
-
-bool
-decl_has_visibility_attr (tree decl)
-{
- tree attrs = DECL_ATTRIBUTES (decl);
- return (lookup_attribute ("visibility", attrs)
- || (TARGET_DLLIMPORT_DECL_ATTRIBUTES
- && (lookup_attribute ("dllimport", attrs)
- || lookup_attribute ("dllexport", attrs))));
-}
-
/* Determine the ELF symbol visibility for DECL, which is either a
variable or a function. It is an error to use this function if a
definition of DECL is not available in this translation unit.
@@ -7104,8 +7088,15 @@ c_determine_visibility (tree decl)
/* If the user explicitly specified the visibility with an
attribute, honor that. DECL_VISIBILITY will have been set during
- the processing of the attribute. */
- if (decl_has_visibility_attr (decl))
+ the processing of the attribute. We check for an explicit
+ attribute, rather than just checking DECL_VISIBILITY_SPECIFIED,
+ to distinguish the use of an attribute from the use of a "#pragma
+ GCC visibility push(...)"; in the latter case we still want other
+ considerations to be able to overrule the #pragma. */
+ if (lookup_attribute ("visibility", DECL_ATTRIBUTES (decl))
+ || (TARGET_DLLIMPORT_DECL_ATTRIBUTES
+ && (lookup_attribute ("dllimport", DECL_ATTRIBUTES (decl))
+ || lookup_attribute ("dllexport", DECL_ATTRIBUTES (decl)))))
return true;
/* Set default visibility to whatever the user supplied with
diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index f914d49..bff6956 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -775,7 +775,6 @@ extern void overflow_warning (location_t, tree);
extern void warn_logical_operator (location_t, enum tree_code, tree,
enum tree_code, tree, enum tree_code, tree);
extern void check_main_parameter_types (tree decl);
-extern bool decl_has_visibility_attr (tree);
extern bool c_determine_visibility (tree);
extern bool same_scalar_type_ignoring_signedness (tree, tree);
extern void mark_valid_location_for_stdc_pragma (bool);
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 41922ae..c66c9dc 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,5 +1,11 @@
2011-11-07 Jason Merrill <jason@redhat.com>
+ PR c++/35688
+ * decl2.c (constrain_visibility): Return void. Add tmpl parm
+ which gives the constraint priority over an attribute.
+ (constrain_visibility_for_template, determine_visibility): Adjust.
+ * pt.c (instantiate_class_template_1): Call determine_visibility.
+
PR c++/33255
* decl.c (save_function_data): Clear local_typedefs.
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index 80fb0c3..17be3ad 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -1954,10 +1954,12 @@ type_visibility (tree type)
}
/* Limit the visibility of DECL to VISIBILITY, if not explicitly
- specified (or if VISIBILITY is static). */
+ specified (or if VISIBILITY is static). If TMPL is true, this
+ constraint is for a template argument, and takes precedence
+ over explicitly-specified visibility on the template. */
-static bool
-constrain_visibility (tree decl, int visibility)
+static void
+constrain_visibility (tree decl, int visibility, bool tmpl)
{
if (visibility == VISIBILITY_ANON)
{
@@ -1974,16 +1976,11 @@ constrain_visibility (tree decl, int visibility)
DECL_NOT_REALLY_EXTERN (decl) = 1;
}
}
- /* We check decl_has_visibility_attr rather than
- DECL_VISIBILITY_SPECIFIED here because we want other considerations
- to override visibility from a namespace or #pragma. */
else if (visibility > DECL_VISIBILITY (decl)
- && !decl_has_visibility_attr (decl))
+ && (tmpl || !DECL_VISIBILITY_SPECIFIED (decl)))
{
DECL_VISIBILITY (decl) = (enum symbol_visibility) visibility;
- return true;
}
- return false;
}
/* Constrain the visibility of DECL based on the visibility of its template
@@ -2019,7 +2016,7 @@ constrain_visibility_for_template (tree decl, tree targs)
}
}
if (vis)
- constrain_visibility (decl, vis);
+ constrain_visibility (decl, vis, true);
}
}
@@ -2132,7 +2129,7 @@ determine_visibility (tree decl)
if (underlying_vis == VISIBILITY_ANON
|| (CLASS_TYPE_P (underlying_type)
&& CLASSTYPE_VISIBILITY_SPECIFIED (underlying_type)))
- constrain_visibility (decl, underlying_vis);
+ constrain_visibility (decl, underlying_vis, false);
else
DECL_VISIBILITY (decl) = VISIBILITY_DEFAULT;
}
@@ -2140,7 +2137,7 @@ determine_visibility (tree decl)
{
/* tinfo visibility is based on the type it's for. */
constrain_visibility
- (decl, type_visibility (TREE_TYPE (DECL_NAME (decl))));
+ (decl, type_visibility (TREE_TYPE (DECL_NAME (decl))), false);
/* Give the target a chance to override the visibility associated
with DECL. */
@@ -2207,14 +2204,14 @@ determine_visibility (tree decl)
if (decl_anon_ns_mem_p (decl))
/* Names in an anonymous namespace get internal linkage.
This might change once we implement export. */
- constrain_visibility (decl, VISIBILITY_ANON);
+ constrain_visibility (decl, VISIBILITY_ANON, false);
else if (TREE_CODE (decl) != TYPE_DECL)
{
/* Propagate anonymity from type to decl. */
int tvis = type_visibility (TREE_TYPE (decl));
if (tvis == VISIBILITY_ANON
|| ! DECL_VISIBILITY_SPECIFIED (decl))
- constrain_visibility (decl, tvis);
+ constrain_visibility (decl, tvis, false);
}
else if (no_linkage_check (TREE_TYPE (decl), /*relaxed_p=*/true))
/* DR 757: A type without linkage shall not be used as the type of a
@@ -2225,7 +2222,7 @@ determine_visibility (tree decl)
Since non-extern "C" decls need to be defined in the same
translation unit, we can make the type internal. */
- constrain_visibility (decl, VISIBILITY_ANON);
+ constrain_visibility (decl, VISIBILITY_ANON, false);
/* If visibility changed and DECL already has DECL_RTL, ensure
symbol flags are updated. */
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 493e3e6..52f4d47 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -8600,6 +8600,8 @@ instantiate_class_template_1 (tree type)
{
CLASSTYPE_VISIBILITY_SPECIFIED (type) = 1;
CLASSTYPE_VISIBILITY (type) = CLASSTYPE_VISIBILITY (pattern);
+ /* Adjust visibility for template arguments. */
+ determine_visibility (TYPE_MAIN_DECL (type));
}
CLASSTYPE_FINAL (type) = CLASSTYPE_FINAL (pattern);
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 46f702a..b9c39d3 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2011-11-07 Jason Merrill <jason@redhat.com>
+
+ PR c++/35688
+ * g++.dg/ext/visibility/template8.C: New.
+
2011-11-07 Jakub Jelinek <jakub@redhat.com>
PR tree-optimization/50789
diff --git a/gcc/testsuite/g++.dg/ext/visibility/template8.C b/gcc/testsuite/g++.dg/ext/visibility/template8.C
new file mode 100644
index 0000000..e491882
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/visibility/template8.C
@@ -0,0 +1,26 @@
+// PR c++/35688
+// { dg-require-visibility "" }
+// { dg-options "-fvisibility=hidden" }
+
+// { dg-final { scan-hidden "_Z1gI1BEvT_" } }
+// { dg-final { scan-hidden "_Z1gI1AI1BEEvT_" } }
+
+// Test that template argument visibility takes priority even over an
+// explicit visibility attribute on a template.
+
+template <class T>
+struct __attribute ((visibility ("default"))) A { };
+template <class T>
+void g(T) __attribute ((visibility ("default")));
+
+struct B { };
+
+template <class T>
+void g(T)
+{ }
+
+int main()
+{
+ g(B());
+ g(A<B>());
+}