re PR c++/28407 (Issue with anonymous namespace)
PR c++/28407 * cp/decl.c (grokvardecl): Set DECL_THIS_STATIC on file-scope const variables with implicit internal linkage. * cp/tree.c (decl_linkage): Only return lk_external if it's set. PR c++/28409 * cp/decl2.c (constrain_visibility): Ignore the anonymous namespace for extern C decls. (VISIBILITY_STATIC): Rename to VISIBILITY_ANON. Don't override explicit visibility. * cp/decl2.c (constrain_visibility): Remove specified and reason parameters. Don't touch decls that already have explicit visibility. (determine_visibility): Do copy DECL_VISIBILITY_SPECIFIED from template. (determine_visibility_from_class): Reverse sense of DECL_VISIBILITY_SPECIFIED test for target-specific visibility rules. (constrain_class_visibility): Only complain about member visibility if the member type is another class. Don't change visibility of the current class. * tree.c (remove_attribute): New fn. * tree.h: Declare it. From-SVN: r115622
This commit is contained in:
parent
e67b81d140
commit
b70f0f48c7
14 changed files with 248 additions and 63 deletions
|
@ -1,3 +1,7 @@
|
|||
2006-07-20 Jason Merrill <jason@redhat.com>
|
||||
|
||||
* tree.c (remove_attribute): New fn.
|
||||
|
||||
2006-07-20 Paul Brook <paul@codesourcery.com>
|
||||
|
||||
PR 27363
|
||||
|
|
|
@ -1,3 +1,25 @@
|
|||
2006-07-20 Jason Merrill <jason@redhat.com>
|
||||
|
||||
PR c++/28407
|
||||
* decl.c (grokvardecl): Set DECL_THIS_STATIC on file-scope
|
||||
const variables with implicit internal linkage.
|
||||
* tree.c (decl_linkage): Only return lk_external if it's set.
|
||||
|
||||
PR c++/28409
|
||||
* decl2.c (constrain_visibility): Ignore the anonymous namespace
|
||||
for extern "C" decls.
|
||||
(VISIBILITY_STATIC): Rename to VISIBILITY_ANON.
|
||||
|
||||
* decl2.c (constrain_visibility): Remove specified and reason
|
||||
parameters. Don't touch decls that already have explicit visibility.
|
||||
(determine_visibility): Do copy DECL_VISIBILITY_SPECIFIED from
|
||||
template.
|
||||
(determine_visibility_from_class): Reverse sense of
|
||||
DECL_VISIBILITY_SPECIFIED test for target-specific visibility rules.
|
||||
(constrain_class_visibility): Only complain about member visibility
|
||||
if the member type is another class. Don't change visibility of the
|
||||
current class.
|
||||
|
||||
2006-07-19 Mark Mitchell <mark@codesourcery.com>
|
||||
|
||||
PR c++/28338
|
||||
|
|
|
@ -5246,6 +5246,14 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p,
|
|||
{
|
||||
layout_var_decl (decl);
|
||||
maybe_commonize_var (decl);
|
||||
if (DECL_NAMESPACE_SCOPE_P (decl) && !TREE_PUBLIC (decl)
|
||||
&& !DECL_THIS_STATIC (decl) && !DECL_ARTIFICIAL (decl))
|
||||
{
|
||||
/* This is a const variable with implicit 'static'. Set
|
||||
DECL_THIS_STATIC so we can tell it from variables that are
|
||||
!TREE_PUBLIC because of the anonymous namespace. */
|
||||
DECL_THIS_STATIC (decl) = 1;
|
||||
}
|
||||
}
|
||||
|
||||
make_rtl_for_nonlocal_decl (decl, init, asmspec);
|
||||
|
|
130
gcc/cp/decl2.c
130
gcc/cp/decl2.c
|
@ -1536,7 +1536,7 @@ maybe_emit_vtables (tree ctype)
|
|||
/* A special return value from type_visibility meaning internal
|
||||
linkage. */
|
||||
|
||||
enum { VISIBILITY_STATIC = VISIBILITY_INTERNAL+1 };
|
||||
enum { VISIBILITY_ANON = VISIBILITY_INTERNAL+1 };
|
||||
|
||||
/* walk_tree helper function for type_visibility. */
|
||||
|
||||
|
@ -1552,7 +1552,7 @@ min_vis_r (tree *tp, int *walk_subtrees, void *data)
|
|||
{
|
||||
if (!TREE_PUBLIC (TYPE_MAIN_DECL (*tp)))
|
||||
{
|
||||
*vis_p = VISIBILITY_STATIC;
|
||||
*vis_p = VISIBILITY_ANON;
|
||||
return *tp;
|
||||
}
|
||||
else if (CLASSTYPE_VISIBILITY (*tp) > *vis_p)
|
||||
|
@ -1572,29 +1572,28 @@ type_visibility (tree type)
|
|||
return vis;
|
||||
}
|
||||
|
||||
/* Limit the visibility of DECL to VISIBILITY. SPECIFIED is true if the
|
||||
constraint comes from an attribute or pragma; REASON is the source of
|
||||
the constraint. */
|
||||
/* Limit the visibility of DECL to VISIBILITY, if not explicitly
|
||||
specified (or if VISIBILITY is static). */
|
||||
|
||||
static bool
|
||||
constrain_visibility (tree decl, int visibility, bool specified,
|
||||
const char *reason)
|
||||
constrain_visibility (tree decl, int visibility)
|
||||
{
|
||||
if (visibility == VISIBILITY_STATIC)
|
||||
if (visibility == VISIBILITY_ANON)
|
||||
{
|
||||
TREE_PUBLIC (decl) = 0;
|
||||
DECL_INTERFACE_KNOWN (decl) = 1;
|
||||
if (DECL_LANG_SPECIFIC (decl))
|
||||
DECL_NOT_REALLY_EXTERN (decl) = 1;
|
||||
/* extern "C" declarations aren't affected by the anonymous
|
||||
namespace. */
|
||||
if (!DECL_EXTERN_C_P (decl))
|
||||
{
|
||||
TREE_PUBLIC (decl) = 0;
|
||||
DECL_INTERFACE_KNOWN (decl) = 1;
|
||||
if (DECL_LANG_SPECIFIC (decl))
|
||||
DECL_NOT_REALLY_EXTERN (decl) = 1;
|
||||
}
|
||||
}
|
||||
else if (visibility > DECL_VISIBILITY (decl))
|
||||
else if (visibility > DECL_VISIBILITY (decl)
|
||||
&& !DECL_VISIBILITY_SPECIFIED (decl))
|
||||
{
|
||||
if (lookup_attribute ("visibility", DECL_ATTRIBUTES (decl)))
|
||||
warning (OPT_Wattributes, "%q+D: visibility attribute requests "
|
||||
"greater visibility than its %s allows", decl, reason);
|
||||
DECL_VISIBILITY (decl) = visibility;
|
||||
if (!DECL_VISIBILITY_SPECIFIED (decl))
|
||||
DECL_VISIBILITY_SPECIFIED (decl) = specified;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -1627,13 +1626,13 @@ constrain_visibility_for_template (tree decl, tree targs)
|
|||
|| TREE_CODE (arg) == FUNCTION_DECL)
|
||||
{
|
||||
if (! TREE_PUBLIC (arg))
|
||||
vis = VISIBILITY_STATIC;
|
||||
vis = VISIBILITY_ANON;
|
||||
else
|
||||
vis = DECL_VISIBILITY (arg);
|
||||
}
|
||||
}
|
||||
if (vis)
|
||||
constrain_visibility (decl, vis, false, "template parameter");
|
||||
constrain_visibility (decl, vis);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1735,8 +1734,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))),
|
||||
false, "type");
|
||||
(decl, type_visibility (TREE_TYPE (DECL_NAME (decl))));
|
||||
}
|
||||
else if (use_template)
|
||||
/* Template instantiations and specializations get visibility based
|
||||
|
@ -1752,43 +1750,42 @@ determine_visibility (tree decl)
|
|||
|
||||
if (use_template)
|
||||
{
|
||||
/* If the specialization doesn't specify visibility, use the
|
||||
visibility from the template. */
|
||||
tree tinfo = (TREE_CODE (decl) == TYPE_DECL
|
||||
? TYPE_TEMPLATE_INFO (TREE_TYPE (decl))
|
||||
: DECL_TEMPLATE_INFO (decl));
|
||||
tree args = TI_ARGS (tinfo);
|
||||
int depth = TMPL_ARGS_DEPTH (args);
|
||||
tree pattern = DECL_TEMPLATE_RESULT (TI_TEMPLATE (tinfo));
|
||||
|
||||
/* If the template has explicit visibility and the specialization
|
||||
doesn't, use the visibility from the template. */
|
||||
if (!DECL_VISIBILITY_SPECIFIED (decl))
|
||||
{
|
||||
tree pattern = DECL_TEMPLATE_RESULT (TI_TEMPLATE (tinfo));
|
||||
DECL_VISIBILITY (decl) = DECL_VISIBILITY (pattern);
|
||||
DECL_VISIBILITY_SPECIFIED (decl)
|
||||
= DECL_VISIBILITY_SPECIFIED (pattern);
|
||||
}
|
||||
|
||||
/* FIXME should TMPL_ARGS_DEPTH really return 1 for null input? */
|
||||
if (args && depth > template_class_depth (class_type))
|
||||
/* Don't let it have more visibility than its template type
|
||||
arguments. */
|
||||
/* Limit visibility based on its template arguments. */
|
||||
constrain_visibility_for_template (decl, args);
|
||||
}
|
||||
|
||||
|
||||
if (class_type)
|
||||
determine_visibility_from_class (decl, class_type);
|
||||
|
||||
/* Don't let it have more visibility than its type. */
|
||||
if (TREE_CODE (decl) != TYPE_DECL)
|
||||
if (constrain_visibility (decl, type_visibility (TREE_TYPE (decl)),
|
||||
false, "type"))
|
||||
if (constrain_visibility (decl, type_visibility (TREE_TYPE (decl))))
|
||||
warning (OPT_Wattributes, "\
|
||||
%q+D declared with greater visibility than its type",
|
||||
lowering visibility of %q+D to match its type",
|
||||
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_STATIC,
|
||||
false, "namespace");
|
||||
constrain_visibility (decl, VISIBILITY_ANON);
|
||||
}
|
||||
|
||||
/* By default, static data members and function members receive
|
||||
|
@ -1806,11 +1803,13 @@ determine_visibility_from_class (tree decl, tree class_type)
|
|||
&& TREE_CODE (decl) == FUNCTION_DECL
|
||||
&& DECL_DECLARED_INLINE_P (decl))
|
||||
DECL_VISIBILITY (decl) = VISIBILITY_HIDDEN;
|
||||
|
||||
/* The decl can't have more visibility than its class. */
|
||||
constrain_visibility (decl, CLASSTYPE_VISIBILITY (class_type),
|
||||
CLASSTYPE_VISIBILITY_SPECIFIED (class_type),
|
||||
"class");
|
||||
else if (!DECL_VISIBILITY_SPECIFIED (decl))
|
||||
{
|
||||
/* Default to the class visibility. */
|
||||
DECL_VISIBILITY (decl) = CLASSTYPE_VISIBILITY (class_type);
|
||||
DECL_VISIBILITY_SPECIFIED (decl)
|
||||
= CLASSTYPE_VISIBILITY_SPECIFIED (class_type);
|
||||
}
|
||||
|
||||
/* Give the target a chance to override the visibility associated
|
||||
with DECL. */
|
||||
|
@ -1823,8 +1822,8 @@ determine_visibility_from_class (tree decl, tree class_type)
|
|||
&& !DECL_CONSTRUCTION_VTABLE_P (decl)))
|
||||
&& TREE_PUBLIC (decl)
|
||||
&& !DECL_REALLY_EXTERN (decl)
|
||||
&& DECL_VISIBILITY_SPECIFIED (decl)
|
||||
&& (!class_type || !CLASSTYPE_VISIBILITY_SPECIFIED (class_type)))
|
||||
&& !DECL_VISIBILITY_SPECIFIED (decl)
|
||||
&& !CLASSTYPE_VISIBILITY_SPECIFIED (class_type))
|
||||
targetm.cxx.determine_class_data_visibility (decl);
|
||||
}
|
||||
|
||||
|
@ -1834,25 +1833,50 @@ determine_visibility_from_class (tree decl, tree class_type)
|
|||
void
|
||||
constrain_class_visibility (tree type)
|
||||
{
|
||||
tree decl = TYPE_MAIN_DECL (type);
|
||||
tree binfo = TYPE_BINFO (type);
|
||||
tree binfo;
|
||||
tree t;
|
||||
int i;
|
||||
|
||||
for (t = TYPE_FIELDS (type); t; t = TREE_CHAIN (t))
|
||||
if (TREE_CODE (t) == FIELD_DECL)
|
||||
if (constrain_visibility (decl, type_visibility (TREE_TYPE (t)),
|
||||
false, "field type"))
|
||||
warning (OPT_Wattributes, "\
|
||||
%qT declared with greater visibility than the type of its field %qD",
|
||||
type, t);
|
||||
int vis = type_visibility (type);
|
||||
|
||||
if (vis == VISIBILITY_ANON)
|
||||
return;
|
||||
|
||||
/* Don't warn about visibility if the class has explicit visibility. */
|
||||
if (CLASSTYPE_VISIBILITY_SPECIFIED (type))
|
||||
vis = VISIBILITY_INTERNAL;
|
||||
|
||||
for (t = TYPE_FIELDS (type); t; t = TREE_CHAIN (t))
|
||||
if (TREE_CODE (t) == FIELD_DECL && TREE_TYPE (t) != error_mark_node)
|
||||
{
|
||||
int subvis = type_visibility (TREE_TYPE (t));
|
||||
|
||||
if (subvis == VISIBILITY_ANON)
|
||||
warning (0, "\
|
||||
%qT has a field %qD whose type uses the anonymous namespace",
|
||||
type, t);
|
||||
else if (vis < VISIBILITY_HIDDEN
|
||||
&& subvis >= VISIBILITY_HIDDEN)
|
||||
warning (OPT_Wattributes, "\
|
||||
%qT declared with greater visibility than the type of its field %qD",
|
||||
type, t);
|
||||
}
|
||||
|
||||
binfo = TYPE_BINFO (type);
|
||||
for (i = 0; BINFO_BASE_ITERATE (binfo, i, t); ++i)
|
||||
if (constrain_visibility (decl, type_visibility (TREE_TYPE (t)),
|
||||
false, "base type"))
|
||||
warning (OPT_Wattributes, "\
|
||||
{
|
||||
int subvis = type_visibility (TREE_TYPE (t));
|
||||
|
||||
if (subvis == VISIBILITY_ANON)
|
||||
warning (0, "\
|
||||
%qT has a base %qT whose type uses the anonymous namespace",
|
||||
type, TREE_TYPE (t));
|
||||
else if (vis < VISIBILITY_HIDDEN
|
||||
&& subvis >= VISIBILITY_HIDDEN)
|
||||
warning (OPT_Wattributes, "\
|
||||
%qT declared with greater visibility than its base %qT",
|
||||
type, TREE_TYPE (t));
|
||||
type, TREE_TYPE (t));
|
||||
}
|
||||
}
|
||||
|
||||
/* DECL is a FUNCTION_DECL or VAR_DECL. If the object file linkage
|
||||
|
|
14
gcc/cp/pt.c
14
gcc/cp/pt.c
|
@ -6589,7 +6589,12 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
|
|||
|
||||
/* Possibly limit visibility based on template args. */
|
||||
DECL_VISIBILITY (r) = VISIBILITY_DEFAULT;
|
||||
DECL_VISIBILITY_SPECIFIED (r) = 0;
|
||||
if (DECL_VISIBILITY_SPECIFIED (t))
|
||||
{
|
||||
DECL_VISIBILITY_SPECIFIED (r) = 0;
|
||||
DECL_ATTRIBUTES (r)
|
||||
= remove_attribute ("visibility", DECL_ATTRIBUTES (r));
|
||||
}
|
||||
determine_visibility (r);
|
||||
}
|
||||
break;
|
||||
|
@ -6791,7 +6796,12 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
|
|||
{
|
||||
/* Possibly limit visibility based on template args. */
|
||||
DECL_VISIBILITY (r) = VISIBILITY_DEFAULT;
|
||||
DECL_VISIBILITY_SPECIFIED (r) = 0;
|
||||
if (DECL_VISIBILITY_SPECIFIED (t))
|
||||
{
|
||||
DECL_VISIBILITY_SPECIFIED (r) = 0;
|
||||
DECL_ATTRIBUTES (r)
|
||||
= remove_attribute ("visibility", DECL_ATTRIBUTES (r));
|
||||
}
|
||||
determine_visibility (r);
|
||||
}
|
||||
|
||||
|
|
|
@ -2195,6 +2195,9 @@ decl_linkage (tree decl)
|
|||
if (TREE_PUBLIC (decl))
|
||||
return lk_external;
|
||||
|
||||
if (TREE_CODE (decl) == NAMESPACE_DECL)
|
||||
return lk_external;
|
||||
|
||||
/* Linkage of a CONST_DECL depends on the linkage of the enumeration
|
||||
type. */
|
||||
if (TREE_CODE (decl) == CONST_DECL)
|
||||
|
@ -2214,6 +2217,14 @@ decl_linkage (tree decl)
|
|||
if (decl_function_context (decl))
|
||||
return lk_none;
|
||||
|
||||
/* Members of the anonymous namespace also have TREE_PUBLIC unset, but
|
||||
are considered to have external linkage for language purposes. DECLs
|
||||
really meant to have internal linkage have DECL_THIS_STATIC set. */
|
||||
if (TREE_CODE (decl) == TYPE_DECL
|
||||
|| ((TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == FUNCTION_DECL)
|
||||
&& !DECL_THIS_STATIC (decl)))
|
||||
return lk_external;
|
||||
|
||||
/* Everything else has internal linkage. */
|
||||
return lk_internal;
|
||||
}
|
||||
|
|
|
@ -2413,16 +2413,16 @@ In C++, the visibility attribute applies to types as well as functions
|
|||
and objects, because in C++ types have linkage. A class must not have
|
||||
greater visibility than its non-static data member types and bases,
|
||||
and class members default to the visibility of their class. Also, a
|
||||
declaration must not have greater visibility than its type.
|
||||
declaration without explicit visibility is limited to the visibility
|
||||
of its type.
|
||||
|
||||
In C++, you can mark member functions and static member variables of a
|
||||
class with the visibility attribute. This is useful if if you know a
|
||||
particular method or static member variable should only be used from
|
||||
one shared object; then you can mark it hidden while the rest of the
|
||||
class has default visibility. Care must be taken to avoid breaking
|
||||
the One Definition Rule; for example, it is not useful to mark a
|
||||
method which is defined inside a class definition as hidden without
|
||||
marking the whole class as hidden.
|
||||
the One Definition Rule; for example, it is usually not useful to mark
|
||||
an inline method as hidden without marking the whole class as hidden.
|
||||
|
||||
A C++ namespace declaration can also have the visibility attribute.
|
||||
This attribute applies only to the particular namespace body, not to
|
||||
|
@ -2435,6 +2435,9 @@ restriction is implicitly propagated to the template instantiation.
|
|||
Otherwise, template instantiations and specializations default to the
|
||||
visibility of their template.
|
||||
|
||||
If both the template and enclosing class have explicit visibility, the
|
||||
visibility from the template is used.
|
||||
|
||||
@item warn_unused_result
|
||||
@cindex @code{warn_unused_result} attribute
|
||||
The @code{warn_unused_result} attribute causes a warning to be emitted
|
||||
|
@ -3668,6 +3671,13 @@ applied to class, struct, union and enum types. Unlike other type
|
|||
attributes, the attribute must appear between the initial keyword and
|
||||
the name of the type; it cannot appear after the body of the type.
|
||||
|
||||
Note that the type visibility is applied to vague linkage entities
|
||||
associated with the class (vtable, typeinfo node, etc.). In
|
||||
particular, if a class is thrown as an exception in one shared object
|
||||
and caught in another, the class must have default visibility.
|
||||
Otherwise the two shared objects will be unable to use the same
|
||||
typeinfo node and exception handling will break.
|
||||
|
||||
@subsection ARM Type Attributes
|
||||
|
||||
On those ARM targets that support @code{dllimport} (such as Symbian
|
||||
|
|
17
gcc/testsuite/g++.dg/ext/visibility/template6.C
Normal file
17
gcc/testsuite/g++.dg/ext/visibility/template6.C
Normal file
|
@ -0,0 +1,17 @@
|
|||
// Test for explicit visibility taking precedence
|
||||
|
||||
// { dg-require-visibility "" }
|
||||
// { dg-final { scan-not-hidden "_ZN1AIiE1fEv" } }
|
||||
|
||||
template <class T> struct A
|
||||
{
|
||||
// This attribute takes precedence over...
|
||||
__attribute ((visibility ("default"))) void f ();
|
||||
};
|
||||
|
||||
template <class T>
|
||||
void A<T>::f ()
|
||||
{ }
|
||||
|
||||
// ...this attribute.
|
||||
template struct __attribute ((visibility ("hidden"))) A<int>;
|
|
@ -14,6 +14,6 @@ struct B
|
|||
N::A a;
|
||||
};
|
||||
|
||||
B f () { } // { dg-warning "visibility" }
|
||||
N::A f () { } // { dg-warning "visibility" }
|
||||
|
||||
struct C: public N::A { }; // { dg-warning "visibility" }
|
||||
|
|
|
@ -1,11 +1,32 @@
|
|||
// Warn when a class member is specified to have greater visibility than
|
||||
// its class.
|
||||
// Tests for various visibility mismatch situations.
|
||||
|
||||
// { dg-require-visibility "" }
|
||||
|
||||
// { dg-final { scan-not-hidden "_ZN1A1fEv" } }
|
||||
|
||||
struct __attribute ((visibility ("hidden"))) A
|
||||
{
|
||||
__attribute ((visibility ("default"))) void f (); // { dg-warning "visibility" }
|
||||
// This is OK, A::f gets default visibility.
|
||||
__attribute ((visibility ("default"))) void f ();
|
||||
};
|
||||
|
||||
void A::f() { }
|
||||
|
||||
// This gets a warning; it should have explicit visibility of some sort.
|
||||
A* afactory1() { return new A; } // { dg-warning "visibility" }
|
||||
|
||||
// This is OK.
|
||||
__attribute ((visibility ("default"))) A*
|
||||
afactory2 () { return new A; }
|
||||
|
||||
// This gets a warning.
|
||||
struct B
|
||||
{ // { dg-warning "visibility" }
|
||||
A a;
|
||||
};
|
||||
|
||||
// This one has explicit visibility, so it doesn't get a warning.
|
||||
struct __attribute ((visibility ("default"))) C
|
||||
{
|
||||
A a;
|
||||
};
|
||||
|
|
21
gcc/testsuite/g++.dg/lookup/anon5.C
Normal file
21
gcc/testsuite/g++.dg/lookup/anon5.C
Normal file
|
@ -0,0 +1,21 @@
|
|||
// PR c++/28409
|
||||
// shouldIbevisible should be emitted because it's an extern "C" decl with
|
||||
// external linkage, even though it's in the anonymous namespace.
|
||||
|
||||
namespace
|
||||
{
|
||||
extern "C" int shouldIbevisible()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
namespace t
|
||||
{
|
||||
extern "C" int shouldIbevisible(void);
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
return t::shouldIbevisible();
|
||||
}
|
10
gcc/testsuite/g++.dg/template/anon4.C
Normal file
10
gcc/testsuite/g++.dg/template/anon4.C
Normal file
|
@ -0,0 +1,10 @@
|
|||
// PR c++/28407
|
||||
// A declaration in the anonymous namespace still has external linkage.
|
||||
|
||||
template <int *P> class A { };
|
||||
namespace
|
||||
{
|
||||
int i;
|
||||
}
|
||||
|
||||
A<&i> a;
|
22
gcc/tree.c
22
gcc/tree.c
|
@ -3499,6 +3499,28 @@ lookup_attribute (const char *attr_name, tree list)
|
|||
return NULL_TREE;
|
||||
}
|
||||
|
||||
/* Remove any instances of attribute ATTR_NAME in LIST and return the
|
||||
modified list. */
|
||||
|
||||
tree
|
||||
remove_attribute (const char *attr_name, tree list)
|
||||
{
|
||||
tree *p;
|
||||
size_t attr_len = strlen (attr_name);
|
||||
|
||||
for (p = &list; *p; )
|
||||
{
|
||||
tree l = *p;
|
||||
gcc_assert (TREE_CODE (TREE_PURPOSE (l)) == IDENTIFIER_NODE);
|
||||
if (is_attribute_with_length_p (attr_name, attr_len, TREE_PURPOSE (l)))
|
||||
*p = TREE_CHAIN (l);
|
||||
else
|
||||
p = &TREE_CHAIN (l);
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
/* Return an attribute list that is the union of a1 and a2. */
|
||||
|
||||
tree
|
||||
|
|
|
@ -3696,6 +3696,11 @@ extern int is_attribute_p (const char *, tree);
|
|||
|
||||
extern tree lookup_attribute (const char *, tree);
|
||||
|
||||
/* Remove any instances of attribute ATTR_NAME in LIST and return the
|
||||
modified list. */
|
||||
|
||||
extern tree remove_attribute (const char *, tree);
|
||||
|
||||
/* Given two attributes lists, return a list of their union. */
|
||||
|
||||
extern tree merge_attributes (tree, tree);
|
||||
|
|
Loading…
Add table
Reference in a new issue