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
This commit is contained in:
parent
c7e6757f2a
commit
6d87092d19
|
@ -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>
|
2011-11-06 Jason Merrill <jason@redhat.com>
|
||||||
|
|
||||||
PR c++/35688
|
PR c++/35688
|
||||||
|
|
|
@ -7073,22 +7073,6 @@ handle_visibility_attribute (tree *node, tree name, tree args,
|
||||||
return NULL_TREE;
|
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
|
/* 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
|
variable or a function. It is an error to use this function if a
|
||||||
definition of DECL is not available in this translation unit.
|
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
|
/* If the user explicitly specified the visibility with an
|
||||||
attribute, honor that. DECL_VISIBILITY will have been set during
|
attribute, honor that. DECL_VISIBILITY will have been set during
|
||||||
the processing of the attribute. */
|
the processing of the attribute. We check for an explicit
|
||||||
if (decl_has_visibility_attr (decl))
|
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;
|
return true;
|
||||||
|
|
||||||
/* Set default visibility to whatever the user supplied with
|
/* Set default visibility to whatever the user supplied with
|
||||||
|
|
|
@ -775,7 +775,6 @@ extern void overflow_warning (location_t, tree);
|
||||||
extern void warn_logical_operator (location_t, enum tree_code, tree,
|
extern void warn_logical_operator (location_t, enum tree_code, tree,
|
||||||
enum tree_code, tree, enum tree_code, tree);
|
enum tree_code, tree, enum tree_code, tree);
|
||||||
extern void check_main_parameter_types (tree decl);
|
extern void check_main_parameter_types (tree decl);
|
||||||
extern bool decl_has_visibility_attr (tree);
|
|
||||||
extern bool c_determine_visibility (tree);
|
extern bool c_determine_visibility (tree);
|
||||||
extern bool same_scalar_type_ignoring_signedness (tree, tree);
|
extern bool same_scalar_type_ignoring_signedness (tree, tree);
|
||||||
extern void mark_valid_location_for_stdc_pragma (bool);
|
extern void mark_valid_location_for_stdc_pragma (bool);
|
||||||
|
|
|
@ -1,5 +1,11 @@
|
||||||
2011-11-07 Jason Merrill <jason@redhat.com>
|
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
|
PR c++/33255
|
||||||
* decl.c (save_function_data): Clear local_typedefs.
|
* decl.c (save_function_data): Clear local_typedefs.
|
||||||
|
|
||||||
|
|
|
@ -1954,10 +1954,12 @@ type_visibility (tree type)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Limit the visibility of DECL to VISIBILITY, if not explicitly
|
/* 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
|
static void
|
||||||
constrain_visibility (tree decl, int visibility)
|
constrain_visibility (tree decl, int visibility, bool tmpl)
|
||||||
{
|
{
|
||||||
if (visibility == VISIBILITY_ANON)
|
if (visibility == VISIBILITY_ANON)
|
||||||
{
|
{
|
||||||
|
@ -1974,16 +1976,11 @@ constrain_visibility (tree decl, int visibility)
|
||||||
DECL_NOT_REALLY_EXTERN (decl) = 1;
|
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)
|
else if (visibility > DECL_VISIBILITY (decl)
|
||||||
&& !decl_has_visibility_attr (decl))
|
&& (tmpl || !DECL_VISIBILITY_SPECIFIED (decl)))
|
||||||
{
|
{
|
||||||
DECL_VISIBILITY (decl) = (enum symbol_visibility) visibility;
|
DECL_VISIBILITY (decl) = (enum symbol_visibility) visibility;
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Constrain the visibility of DECL based on the visibility of its template
|
/* 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)
|
if (vis)
|
||||||
constrain_visibility (decl, vis);
|
constrain_visibility (decl, vis, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2132,7 +2129,7 @@ determine_visibility (tree decl)
|
||||||
if (underlying_vis == VISIBILITY_ANON
|
if (underlying_vis == VISIBILITY_ANON
|
||||||
|| (CLASS_TYPE_P (underlying_type)
|
|| (CLASS_TYPE_P (underlying_type)
|
||||||
&& CLASSTYPE_VISIBILITY_SPECIFIED (underlying_type)))
|
&& CLASSTYPE_VISIBILITY_SPECIFIED (underlying_type)))
|
||||||
constrain_visibility (decl, underlying_vis);
|
constrain_visibility (decl, underlying_vis, false);
|
||||||
else
|
else
|
||||||
DECL_VISIBILITY (decl) = VISIBILITY_DEFAULT;
|
DECL_VISIBILITY (decl) = VISIBILITY_DEFAULT;
|
||||||
}
|
}
|
||||||
|
@ -2140,7 +2137,7 @@ determine_visibility (tree decl)
|
||||||
{
|
{
|
||||||
/* tinfo visibility is based on the type it's for. */
|
/* tinfo visibility is based on the type it's for. */
|
||||||
constrain_visibility
|
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
|
/* Give the target a chance to override the visibility associated
|
||||||
with DECL. */
|
with DECL. */
|
||||||
|
@ -2207,14 +2204,14 @@ determine_visibility (tree decl)
|
||||||
if (decl_anon_ns_mem_p (decl))
|
if (decl_anon_ns_mem_p (decl))
|
||||||
/* Names in an anonymous namespace get internal linkage.
|
/* Names in an anonymous namespace get internal linkage.
|
||||||
This might change once we implement export. */
|
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)
|
else if (TREE_CODE (decl) != TYPE_DECL)
|
||||||
{
|
{
|
||||||
/* Propagate anonymity from type to decl. */
|
/* Propagate anonymity from type to decl. */
|
||||||
int tvis = type_visibility (TREE_TYPE (decl));
|
int tvis = type_visibility (TREE_TYPE (decl));
|
||||||
if (tvis == VISIBILITY_ANON
|
if (tvis == VISIBILITY_ANON
|
||||||
|| ! DECL_VISIBILITY_SPECIFIED (decl))
|
|| ! DECL_VISIBILITY_SPECIFIED (decl))
|
||||||
constrain_visibility (decl, tvis);
|
constrain_visibility (decl, tvis, false);
|
||||||
}
|
}
|
||||||
else if (no_linkage_check (TREE_TYPE (decl), /*relaxed_p=*/true))
|
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
|
/* 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
|
Since non-extern "C" decls need to be defined in the same
|
||||||
translation unit, we can make the type internal. */
|
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
|
/* If visibility changed and DECL already has DECL_RTL, ensure
|
||||||
symbol flags are updated. */
|
symbol flags are updated. */
|
||||||
|
|
|
@ -8600,6 +8600,8 @@ instantiate_class_template_1 (tree type)
|
||||||
{
|
{
|
||||||
CLASSTYPE_VISIBILITY_SPECIFIED (type) = 1;
|
CLASSTYPE_VISIBILITY_SPECIFIED (type) = 1;
|
||||||
CLASSTYPE_VISIBILITY (type) = CLASSTYPE_VISIBILITY (pattern);
|
CLASSTYPE_VISIBILITY (type) = CLASSTYPE_VISIBILITY (pattern);
|
||||||
|
/* Adjust visibility for template arguments. */
|
||||||
|
determine_visibility (TYPE_MAIN_DECL (type));
|
||||||
}
|
}
|
||||||
CLASSTYPE_FINAL (type) = CLASSTYPE_FINAL (pattern);
|
CLASSTYPE_FINAL (type) = CLASSTYPE_FINAL (pattern);
|
||||||
|
|
||||||
|
|
|
@ -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>
|
2011-11-07 Jakub Jelinek <jakub@redhat.com>
|
||||||
|
|
||||||
PR tree-optimization/50789
|
PR tree-optimization/50789
|
||||||
|
|
|
@ -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>());
|
||||||
|
}
|
Loading…
Reference in New Issue