Commit d2af6a68 by Jakub Jelinek Committed by Jakub Jelinek

expr.c (expand_expr_real_1): Use get_callee_fndecl instead of checking…

expr.c (expand_expr_real_1): Use get_callee_fndecl instead of checking CALL_EXPR_FN directly to test for...

	* expr.c (expand_expr_real_1) <case CALL_EXPR>: Use get_callee_fndecl
	instead of checking CALL_EXPR_FN directly to test for builtins.
	If error or warning attributes are present, print
	error resp. warning.
	* c-common.c (handle_error_attribute): New function.
	(c_common_attribute_table): Add error and warning
	attributes.
	* doc/extend.texi: Document error and warning attributes.

	* gcc.dg/va-arg-pack-len-1.c: Use error and warning
	attributes.
	* gcc.dg/va-arg-pack-len-2.c: New test.
	* g++.dg/ext/va-arg-pack-len-1.C: Use error and warning
	attributes.
	* g++.dg/ext/va-arg-pack-len-2.C: New test.

From-SVN: r128687
parent d752cfdb
2007-09-23 Jakub Jelinek <jakub@redhat.com>
* expr.c (expand_expr_real_1) <case CALL_EXPR>: Use get_callee_fndecl
instead of checking CALL_EXPR_FN directly to test for builtins.
If error or warning attributes are present, print
error resp. warning.
* c-common.c (handle_error_attribute): New function.
(c_common_attribute_table): Add error and warning
attributes.
* doc/extend.texi: Document error and warning attributes.
* tree.h (block_nonartificial_location): New prototype.
* tree.c (block_nonartificial_location): New function.
* dwarf2out.c (gen_subprogram_die): Add DW_AT_artificial
......@@ -518,6 +518,7 @@ static tree handle_always_inline_attribute (tree *, tree, tree, int,
static tree handle_gnu_inline_attribute (tree *, tree, tree, int, bool *);
static tree handle_artificial_attribute (tree *, tree, tree, int, bool *);
static tree handle_flatten_attribute (tree *, tree, tree, int, bool *);
static tree handle_error_attribute (tree *, tree, tree, int, bool *);
static tree handle_used_attribute (tree *, tree, tree, int, bool *);
static tree handle_unused_attribute (tree *, tree, tree, int, bool *);
static tree handle_externally_visible_attribute (tree *, tree, tree, int,
......@@ -663,6 +664,10 @@ const struct attribute_spec c_common_attribute_table[] =
handle_cold_attribute },
{ "hot", 0, 0, true, false, false,
handle_hot_attribute },
{ "warning", 1, 1, true, false, false,
handle_error_attribute },
{ "error", 1, 1, true, false, false,
handle_error_attribute },
{ NULL, 0, 0, false, false, false, NULL }
};
......@@ -4923,6 +4928,26 @@ handle_flatten_attribute (tree *node, tree name,
return NULL_TREE;
}
/* Handle a "warning" or "error" attribute; arguments as in
struct attribute_spec.handler. */
static tree
handle_error_attribute (tree *node, tree name, tree args,
int ARG_UNUSED (flags), bool *no_add_attrs)
{
if (TREE_CODE (*node) == FUNCTION_DECL
|| TREE_CODE (TREE_VALUE (args)) == STRING_CST)
/* Do nothing else, just set the attribute. We'll get at
it later with lookup_attribute. */
;
else
{
warning (OPT_Wattributes, "%qE attribute ignored", name);
*no_add_attrs = true;
}
return NULL_TREE;
}
/* Handle a "used" attribute; arguments as in
struct attribute_spec.handler. */
......
......@@ -1803,7 +1803,8 @@ attributes are currently defined for functions on all targets:
@code{destructor}, @code{used}, @code{unused}, @code{deprecated},
@code{weak}, @code{malloc}, @code{alias}, @code{warn_unused_result},
@code{nonnull}, @code{gnu_inline}, @code{externally_visible},
@code{hot}, @code{cold} and @code{artificial}.
@code{hot}, @code{cold}, @code{artificial}, @code{error}
and @code{warning}.
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
......@@ -1941,6 +1942,30 @@ Whether the function itself is considered for inlining depends on its size and
the current inlining parameters. The @code{flatten} attribute only works
reliably in unit-at-a-time mode.
@item error ("@var{message}")
@cindex @code{error} function attribute
If this attribute is used on a function declaration and a call to such a function
is not eliminated through dead code elimination or other optimizations, an error
which will include @var{message} will be diagnosed. This is useful
for compile time checking, especially together with @code{__builtin_constant_p}
and inline functions where checking the inline function arguments is not
possible through @code{extern char [(condition) ? 1 : -1];} tricks.
While it is possible to leave the function undefined and thus invoke
a link failure, when using this attribute the problem will be diagnosed
earlier and with exact location of the call even in presence of inline
functions or when not emitting debugging information.
@item warning ("@var{message}")
@cindex @code{warning} function attribute
If this attribute is used on a function declaration and a call to such a function
is not eliminated through dead code elimination or other optimizations, a warning
which will include @var{message} will be diagnosed. This is useful
for compile time checking, especially together with @code{__builtin_constant_p}
and inline functions. While it is possible to define the function with
a message in @code{.gnu.warning*} section, when using this attribute the problem
will be diagnosed earlier and with exact location of the call even in presence
of inline functions or when not emitting debugging information.
@item cdecl
@cindex functions that do pop the argument stack on the 386
@opindex mrtd
......
......@@ -8002,21 +8002,32 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
inlining. */
if (CALL_EXPR_VA_ARG_PACK (exp))
error ("invalid use of %<__builtin_va_arg_pack ()%>");
/* Check for a built-in function. */
if (TREE_CODE (CALL_EXPR_FN (exp)) == ADDR_EXPR
&& (TREE_CODE (TREE_OPERAND (CALL_EXPR_FN (exp), 0))
== FUNCTION_DECL)
&& DECL_BUILT_IN (TREE_OPERAND (CALL_EXPR_FN (exp), 0)))
{
if (DECL_BUILT_IN_CLASS (TREE_OPERAND (CALL_EXPR_FN (exp), 0))
== BUILT_IN_FRONTEND)
return lang_hooks.expand_expr (exp, original_target,
tmode, modifier,
alt_rtl);
else
return expand_builtin (exp, target, subtarget, tmode, ignore);
}
{
tree fndecl = get_callee_fndecl (exp), attr;
if (fndecl
&& (attr = lookup_attribute ("error",
DECL_ATTRIBUTES (fndecl))) != NULL)
error ("call to %qs declared with attribute error: %s",
lang_hooks.decl_printable_name (fndecl, 1),
TREE_STRING_POINTER (TREE_VALUE (TREE_VALUE (attr))));
if (fndecl
&& (attr = lookup_attribute ("warning",
DECL_ATTRIBUTES (fndecl))) != NULL)
warning (0, "call to %qs declared with attribute warning: %s",
lang_hooks.decl_printable_name (fndecl, 1),
TREE_STRING_POINTER (TREE_VALUE (TREE_VALUE (attr))));
/* Check for a built-in function. */
if (fndecl && DECL_BUILT_IN (fndecl))
{
if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_FRONTEND)
return lang_hooks.expand_expr (exp, original_target,
tmode, modifier, alt_rtl);
else
return expand_builtin (exp, target, subtarget, tmode, ignore);
}
}
return expand_call (exp, target, ignore);
case NON_LVALUE_EXPR:
......
2007-09-23 Jakub Jelinek <jakub@redhat.com>
* gcc.dg/va-arg-pack-len-1.c: Use error and warning
attributes.
* gcc.dg/va-arg-pack-len-2.c: New test.
* g++.dg/ext/va-arg-pack-len-1.C: Use error and warning
attributes.
* g++.dg/ext/va-arg-pack-len-2.C: New test.
PR middle-end/28755
* gcc.dg/pr28755.c: New test.
......@@ -3,8 +3,10 @@
#include <stdarg.h>
extern "C" int warn_open_missing_mode (void);
extern "C" int warn_open_too_many_arguments (void);
extern "C" int error_open_missing_mode (void)
__attribute__((__error__ ("open with O_CREAT needs 3 arguments, only 2 were given")));
extern "C" int warn_open_too_many_arguments (void)
__attribute__((__warning__ ("open called with more than 3 arguments")));
extern "C" void abort (void);
char expected_char;
......@@ -83,7 +85,7 @@ myopen (const char *path, int oflag, ...)
{
if ((oflag & 0x40) != 0 && __builtin_va_arg_pack_len () < 1)
{
warn_open_missing_mode ();
error_open_missing_mode ();
return myopen2 (path, oflag);
}
return myopenva (path, oflag, __builtin_va_arg_pack ());
......
// { dg-do compile }
// { dg-options "-O2" }
#include <stdarg.h>
extern int error_open_missing_mode (void)
__attribute__((__error__ ("open with O_CREAT needs 3 arguments, only 2 were given")));
extern int warn_open_too_many_arguments (void)
__attribute__((__warning__ ("open called with more than 3 arguments")));
extern int myopen2 (const char *path, int oflag);
extern int myopenva (const char *path, int oflag, ...);
extern inline __attribute__((always_inline, gnu_inline)) int
myopen (const char *path, int oflag, ...)
{
if (__builtin_va_arg_pack_len () > 1)
warn_open_too_many_arguments (); // { dg-warning "called with more than 3" }
if (__builtin_constant_p (oflag))
{
if ((oflag & 0x40) != 0 && __builtin_va_arg_pack_len () < 1)
{
error_open_missing_mode (); // { dg-error "needs 3 arguments, only 2 were given" }
return myopen2 (path, oflag);
}
return myopenva (path, oflag, __builtin_va_arg_pack ());
}
if (__builtin_va_arg_pack_len () < 1)
return myopen2 (path, oflag);
return myopenva (path, oflag, __builtin_va_arg_pack ());
}
int
main (void)
{
myopen ("h", 0x43);
myopen ("i", 0x43, 0644, 0655);
return 0;
}
......@@ -3,8 +3,10 @@
#include <stdarg.h>
extern int warn_open_missing_mode (void);
extern int warn_open_too_many_arguments (void);
extern int error_open_missing_mode (void)
__attribute__((__error__ ("open with O_CREAT needs 3 arguments, only 2 were given")));
extern int warn_open_too_many_arguments (void)
__attribute__((__warning__ ("open called with more than 3 arguments")));
extern void abort (void);
char expected_char;
......@@ -83,7 +85,7 @@ myopen (const char *path, int oflag, ...)
{
if ((oflag & 0x40) != 0 && __builtin_va_arg_pack_len () < 1)
{
warn_open_missing_mode ();
error_open_missing_mode ();
return myopen2 (path, oflag);
}
return myopenva (path, oflag, __builtin_va_arg_pack ());
......
/* { dg-do compile } */
/* { dg-options "-O2" } */
#include <stdarg.h>
extern int error_open_missing_mode (void)
__attribute__((__error__ ("open with O_CREAT needs 3 arguments, only 2 were given")));
extern int warn_open_too_many_arguments (void)
__attribute__((__warning__ ("open called with more than 3 arguments")));
extern int myopen2 (const char *path, int oflag);
extern int myopenva (const char *path, int oflag, ...);
extern inline __attribute__((always_inline, gnu_inline)) int
myopen (const char *path, int oflag, ...)
{
if (__builtin_va_arg_pack_len () > 1)
warn_open_too_many_arguments (); /* { dg-warning "called with more than 3" } */
if (__builtin_constant_p (oflag))
{
if ((oflag & 0x40) != 0 && __builtin_va_arg_pack_len () < 1)
{
error_open_missing_mode (); /* { dg-error "needs 3 arguments, only 2 were given" } */
return myopen2 (path, oflag);
}
return myopenva (path, oflag, __builtin_va_arg_pack ());
}
if (__builtin_va_arg_pack_len () < 1)
return myopen2 (path, oflag);
return myopenva (path, oflag, __builtin_va_arg_pack ());
}
int
main (void)
{
myopen ("h", 0x43);
myopen ("i", 0x43, 0644, 0655);
return 0;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment