attribs.c (handle_noinline_attribute): New function.
* attribs.c (handle_noinline_attribute): New function. (handle_used_attribute): Likewise. (c_common_attribute_table): Added noinline and used. * doc/extend.texi (Function Attributes): Document them. * c-decl.c (duplicate_decls): Propagate DECL_UNINLINABLE. Warn when merging inline with attribute noinline. (start_decl, start_function): Warn if inline and attribute noinline appear in the same declaration. From-SVN: r46334
This commit is contained in:
parent
97055d5c4e
commit
9162542e3d
@ -1,3 +1,14 @@
|
||||
2001-10-18 Alexandre Oliva <aoliva@redhat.com>
|
||||
|
||||
* attribs.c (handle_noinline_attribute): New function.
|
||||
(handle_used_attribute): Likewise.
|
||||
(c_common_attribute_table): Added noinline and used.
|
||||
* doc/extend.texi (Function Attributes): Document them.
|
||||
* c-decl.c (duplicate_decls): Propagate DECL_UNINLINABLE.
|
||||
Warn when merging inline with attribute noinline.
|
||||
(start_decl, start_function): Warn if inline and attribute
|
||||
noinline appear in the same declaration.
|
||||
|
||||
2001-10-17 Neil Booth <neil@daikokuya.demon.co.uk>
|
||||
|
||||
* config.gcc: Update c4x and i370 for C front end-specific
|
||||
|
@ -49,6 +49,10 @@ static tree handle_common_attribute PARAMS ((tree *, tree, tree, int,
|
||||
bool *));
|
||||
static tree handle_noreturn_attribute PARAMS ((tree *, tree, tree, int,
|
||||
bool *));
|
||||
static tree handle_noinline_attribute PARAMS ((tree *, tree, tree, int,
|
||||
bool *));
|
||||
static tree handle_used_attribute PARAMS ((tree *, tree, tree, int,
|
||||
bool *));
|
||||
static tree handle_unused_attribute PARAMS ((tree *, tree, tree, int,
|
||||
bool *));
|
||||
static tree handle_const_attribute PARAMS ((tree *, tree, tree, int,
|
||||
@ -100,6 +104,10 @@ static const struct attribute_spec c_common_attribute_table[] =
|
||||
handle_noreturn_attribute },
|
||||
{ "volatile", 0, 0, true, false, false,
|
||||
handle_noreturn_attribute },
|
||||
{ "noinline", 0, 0, true, false, false,
|
||||
handle_noinline_attribute },
|
||||
{ "used", 0, 0, true, false, false,
|
||||
handle_used_attribute },
|
||||
{ "unused", 0, 0, false, false, false,
|
||||
handle_unused_attribute },
|
||||
/* The same comments as for noreturn attributes apply to const ones. */
|
||||
@ -509,6 +517,51 @@ handle_noreturn_attribute (node, name, args, flags, no_add_attrs)
|
||||
return NULL_TREE;
|
||||
}
|
||||
|
||||
/* Handle a "noinline" attribute; arguments as in
|
||||
struct attribute_spec.handler. */
|
||||
|
||||
static tree
|
||||
handle_noinline_attribute (node, name, args, flags, no_add_attrs)
|
||||
tree *node;
|
||||
tree name;
|
||||
tree args ATTRIBUTE_UNUSED;
|
||||
int flags ATTRIBUTE_UNUSED;
|
||||
bool *no_add_attrs;
|
||||
{
|
||||
if (TREE_CODE (*node) == FUNCTION_DECL)
|
||||
DECL_UNINLINABLE (*node) = 1;
|
||||
else
|
||||
{
|
||||
warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
|
||||
*no_add_attrs = true;
|
||||
}
|
||||
|
||||
return NULL_TREE;
|
||||
}
|
||||
|
||||
/* Handle a "used" attribute; arguments as in
|
||||
struct attribute_spec.handler. */
|
||||
|
||||
static tree
|
||||
handle_used_attribute (node, name, args, flags, no_add_attrs)
|
||||
tree *node;
|
||||
tree name;
|
||||
tree args ATTRIBUTE_UNUSED;
|
||||
int flags ATTRIBUTE_UNUSED;
|
||||
bool *no_add_attrs;
|
||||
{
|
||||
if (TREE_CODE (*node) == FUNCTION_DECL)
|
||||
TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (*node))
|
||||
= TREE_USED (*node) = 1;
|
||||
else
|
||||
{
|
||||
warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
|
||||
*no_add_attrs = true;
|
||||
}
|
||||
|
||||
return NULL_TREE;
|
||||
}
|
||||
|
||||
/* Handle a "unused" attribute; arguments as in
|
||||
struct attribute_spec.handler. */
|
||||
|
||||
|
55
gcc/c-decl.c
55
gcc/c-decl.c
@ -1405,8 +1405,43 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
|
||||
int errmsg = 0;
|
||||
|
||||
if (DECL_P (olddecl))
|
||||
DECL_ATTRIBUTES (newdecl)
|
||||
= (*targetm.merge_decl_attributes) (olddecl, newdecl);
|
||||
{
|
||||
if (TREE_CODE (newdecl) == FUNCTION_DECL
|
||||
&& TREE_CODE (olddecl) == FUNCTION_DECL
|
||||
&& (DECL_UNINLINABLE (newdecl) || DECL_UNINLINABLE (olddecl)))
|
||||
{
|
||||
if (DECL_DECLARED_INLINE_P (newdecl)
|
||||
&& DECL_UNINLINABLE (newdecl)
|
||||
&& lookup_attribute ("noinline", DECL_ATTRIBUTES (newdecl)))
|
||||
/* Already warned elsewhere. */;
|
||||
else if (DECL_DECLARED_INLINE_P (olddecl)
|
||||
&& DECL_UNINLINABLE (olddecl)
|
||||
&& lookup_attribute ("noinline", DECL_ATTRIBUTES (olddecl)))
|
||||
/* Already warned. */;
|
||||
else if (DECL_DECLARED_INLINE_P (newdecl)
|
||||
&& ! DECL_DECLARED_INLINE_P (olddecl)
|
||||
&& DECL_UNINLINABLE (olddecl)
|
||||
&& lookup_attribute ("noinline", DECL_ATTRIBUTES (olddecl)))
|
||||
{
|
||||
warning_with_decl (newdecl,
|
||||
"function `%s' redeclared as inline");
|
||||
warning_with_decl (olddecl,
|
||||
"previous declaration of function `%s' with attribute noinline");
|
||||
}
|
||||
else if (DECL_DECLARED_INLINE_P (olddecl)
|
||||
&& DECL_UNINLINABLE (newdecl)
|
||||
&& lookup_attribute ("noinline", DECL_ATTRIBUTES (newdecl)))
|
||||
{
|
||||
warning_with_decl (newdecl,
|
||||
"function `%s' redeclared with attribute noinline");
|
||||
warning_with_decl (olddecl,
|
||||
"previous declaration of function `%s' was inline");
|
||||
}
|
||||
}
|
||||
|
||||
DECL_ATTRIBUTES (newdecl)
|
||||
= (*targetm.merge_decl_attributes) (olddecl, newdecl);
|
||||
}
|
||||
|
||||
if (TREE_CODE (newtype) == ERROR_MARK
|
||||
|| TREE_CODE (oldtype) == ERROR_MARK)
|
||||
@ -1983,6 +2018,9 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
|
||||
DECL_DECLARED_INLINE_P (olddecl) = 1;
|
||||
|
||||
DECL_DECLARED_INLINE_P (newdecl) = DECL_DECLARED_INLINE_P (olddecl);
|
||||
|
||||
DECL_UNINLINABLE (newdecl) = DECL_UNINLINABLE (olddecl)
|
||||
= (DECL_UNINLINABLE (newdecl) || DECL_UNINLINABLE (olddecl));
|
||||
}
|
||||
|
||||
if (DECL_BUILT_IN (olddecl))
|
||||
@ -3483,6 +3521,13 @@ start_decl (declarator, declspecs, initialized, attributes)
|
||||
/* Set attributes here so if duplicate decl, will have proper attributes. */
|
||||
decl_attributes (&decl, attributes, 0);
|
||||
|
||||
if (TREE_CODE (decl) == FUNCTION_DECL
|
||||
&& DECL_DECLARED_INLINE_P (decl)
|
||||
&& DECL_UNINLINABLE (decl)
|
||||
&& lookup_attribute ("noinline", DECL_ATTRIBUTES (decl)))
|
||||
warning_with_decl (decl,
|
||||
"inline function `%s' given attribute noinline");
|
||||
|
||||
/* Add this decl to the current binding level.
|
||||
TEM may equal DECL or it may be a previous decl of the same name. */
|
||||
tem = pushdecl (decl);
|
||||
@ -6022,6 +6067,12 @@ start_function (declspecs, declarator, attributes)
|
||||
|
||||
decl_attributes (&decl1, attributes, 0);
|
||||
|
||||
if (DECL_DECLARED_INLINE_P (decl1)
|
||||
&& DECL_UNINLINABLE (decl1)
|
||||
&& lookup_attribute ("noinline", DECL_ATTRIBUTES (decl1)))
|
||||
warning_with_decl (decl1,
|
||||
"inline function `%s' given attribute noinline");
|
||||
|
||||
announce_function (decl1);
|
||||
|
||||
if (!COMPLETE_OR_VOID_TYPE_P (TREE_TYPE (TREE_TYPE (decl1))))
|
||||
|
@ -1925,13 +1925,14 @@ carefully.
|
||||
|
||||
The keyword @code{__attribute__} allows you to specify special
|
||||
attributes when making a declaration. This keyword is followed by an
|
||||
attribute specification inside double parentheses. Fourteen attributes,
|
||||
@code{noreturn}, @code{pure}, @code{const}, @code{format},
|
||||
@code{format_arg}, @code{no_instrument_function}, @code{section},
|
||||
@code{constructor}, @code{destructor}, @code{unused}, @code{weak},
|
||||
@code{malloc}, @code{alias} and @code{no_check_memory_usage} are
|
||||
currently defined for functions. Several other attributes are defined
|
||||
for functions on particular target systems. Other attributes, including
|
||||
attribute specification inside double parentheses. The following
|
||||
attributs are currently defined for functions on all targets:
|
||||
@code{noreturn}, @code{noinline}, @code{pure}, @code{const},
|
||||
@code{format}, @code{format_arg}, @code{no_instrument_function},
|
||||
@code{section}, @code{constructor}, @code{destructor}, @code{used},
|
||||
@code{unused}, @code{weak}, @code{malloc}, @code{alias} and
|
||||
@code{no_check_memory_usage}. Several other attributes are defined for
|
||||
functions on particular target systems. Other attributes, including
|
||||
@code{section} are supported for variables declarations (@pxref{Variable
|
||||
Attributes}) and for types (@pxref{Type Attributes}).
|
||||
|
||||
@ -1987,6 +1988,11 @@ typedef void voidfn ();
|
||||
volatile voidfn fatal;
|
||||
@end smallexample
|
||||
|
||||
@cindex @code{noinline} function attribute
|
||||
@item noinline
|
||||
This function attribute prevents a function from being considered for
|
||||
inlining.
|
||||
|
||||
@cindex @code{pure} function attribute
|
||||
@item pure
|
||||
Many functions have no effects except the return value and their
|
||||
@ -2174,12 +2180,20 @@ the program.
|
||||
|
||||
These attributes are not currently implemented for Objective-C@.
|
||||
|
||||
@cindex @code{unused} attribute.
|
||||
@item unused
|
||||
This attribute, attached to a function, means that the function is meant
|
||||
to be possibly unused. GCC will not produce a warning for this
|
||||
function. GNU C++ does not currently support this attribute as
|
||||
definitions without parameters are valid in C++.
|
||||
|
||||
@cindex @code{used} attribute.
|
||||
@item used
|
||||
This attribute, attached to a function, means that code must be emitted
|
||||
for the function even if it appears that the function is not referenced.
|
||||
This is useful, for example, when the function is referenced only in
|
||||
inline assembly.
|
||||
|
||||
@item weak
|
||||
@cindex @code{weak} attribute
|
||||
The @code{weak} attribute causes the declaration to be emitted as a weak
|
||||
|
Loading…
Reference in New Issue
Block a user