attribs.c (decl_attributes): Possibly call insert_default_attributes to insert default attributes on...

* attribs.c (decl_attributes): Possibly call
	insert_default_attributes to insert default attributes on
	functions in a lazy manner.
	* builtin-attrs.def: New file; define the default format and
	format_arg attributes.
	* c-common.c (c_format_attribute_table): Move to earlier in the
	file.
	(c_common_nodes_and_builtins): Initialize format_attribute_table.
	(enum built_in_attribute, built_in_attributes,
	c_attrs_initialized, c_init_attributes,
	c_common_insert_default_attributes): New.
	(c_common_lang_init): Don't initialize format_attribute_table.  Do
	call c_init_attributes.
	* Makefile.in (c-common.o): Depend on builtin-attrs.def.
	* c-common.h (init_function_format_info): Don't declare.
	(c_common_insert_default_attributes): Declare.
	* c-decl.c (implicitly_declare, builtin_function): Call
	decl_attributes.
	(init_decl_processing): Don't call init_function_format_info.
	(insert_default_attributes): New.
	* c-format.c (handle_format_attribute,
	handle_format_arg_attribute): Be quiet about inappropriate
	declaration when applying default attributes.
	(init_function_format_info): Remove.
	* tree.h (enum attribute_flags): Add ATTR_FLAG_BUILT_IN.
	(insert_default_attributes): Declare.

cp:
	* decl.c (init_decl_processing): Don't call
	init_function_format_info.  Initialize lang_attribute_table
	earlier.
	(builtin_function): Call decl_attributes.
	(insert_default_attributes): New.

testsuite:
	* gcc.dg/format/attr-5.c, gcc.dg/format/attr-6.c: New tests.

From-SVN: r45942
This commit is contained in:
Joseph Myers 2001-10-02 08:12:25 +01:00 committed by Joseph Myers
parent ed0ea5602b
commit 6431177a55
14 changed files with 419 additions and 103 deletions

View File

@ -1,3 +1,32 @@
2001-10-02 Joseph S. Myers <jsm28@cam.ac.uk>
* attribs.c (decl_attributes): Possibly call
insert_default_attributes to insert default attributes on
functions in a lazy manner.
* builtin-attrs.def: New file; define the default format and
format_arg attributes.
* c-common.c (c_format_attribute_table): Move to earlier in the
file.
(c_common_nodes_and_builtins): Initialize format_attribute_table.
(enum built_in_attribute, built_in_attributes,
c_attrs_initialized, c_init_attributes,
c_common_insert_default_attributes): New.
(c_common_lang_init): Don't initialize format_attribute_table. Do
call c_init_attributes.
* Makefile.in (c-common.o): Depend on builtin-attrs.def.
* c-common.h (init_function_format_info): Don't declare.
(c_common_insert_default_attributes): Declare.
* c-decl.c (implicitly_declare, builtin_function): Call
decl_attributes.
(init_decl_processing): Don't call init_function_format_info.
(insert_default_attributes): New.
* c-format.c (handle_format_attribute,
handle_format_arg_attribute): Be quiet about inappropriate
declaration when applying default attributes.
(init_function_format_info): Remove.
* tree.h (enum attribute_flags): Add ATTR_FLAG_BUILT_IN.
(insert_default_attributes): Declare.
2001-10-02 Joseph S. Myers <jsm28@cam.ac.uk>
* c-format.c (CPLUSPLUS_STD_VER): Define to STD_C94.

View File

@ -1249,7 +1249,7 @@ s-under: $(GCC_PASSES)
c-common.o : c-common.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(OBSTACK_H) \
$(C_COMMON_H) flags.h toplev.h output.h c-pragma.h $(RTL_H) $(GGC_H) \
$(EXPR_H) $(TM_P_H) builtin-types.def $(TARGET_H)
$(EXPR_H) $(TM_P_H) builtin-types.def builtin-attrs.def $(TARGET_H)
# A file used by all variants of C and some other languages.

View File

@ -241,7 +241,11 @@ init_attributes ()
information, in the form of a bitwise OR of flags in enum attribute_flags
from tree.h. Depending on these flags, some attributes may be
returned to be applied at a later stage (for example, to apply
a decl attribute to the declaration rather than to its type). */
a decl attribute to the declaration rather than to its type). If
ATTR_FLAG_BUILT_IN is not set and *NODE is a DECL, then also consider
whether there might be some default attributes to apply to this DECL;
if so, decl_attributes will be called recusrively with those attributes
and ATTR_FLAG_BUILT_IN set. */
tree
decl_attributes (node, attributes, flags)
@ -256,6 +260,10 @@ decl_attributes (node, attributes, flags)
(*targetm.insert_attributes) (*node, &attributes);
if (DECL_P (*node) && TREE_CODE (*node) == FUNCTION_DECL
&& !(flags & (int) ATTR_FLAG_BUILT_IN))
insert_default_attributes (*node);
for (a = attributes; a; a = TREE_CHAIN (a))
{
tree name = TREE_PURPOSE (a);

166
gcc/builtin-attrs.def Normal file
View File

@ -0,0 +1,166 @@
/* Copyright (C) 2001 Free Software Foundation, Inc.
Contributed by Joseph Myers <jsm28@cam.ac.uk>.
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 2, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to the Free
Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA. */
/* This header provides a declarative way of describing the attributes
that are applied to some functions by default.
Before including this header, you must define the following macros.
In each case where there is an ENUM, it is an identifier used to
reference the tree in subsequent definitions.
DEF_ATTR_NULL_TREE (ENUM)
Constructs a NULL_TREE.
DEF_ATTR_INT (ENUM, VALUE)
Constructs an INTEGER_CST with value VALUE (an integer representable
in HOST_WIDE_INT).
DEF_ATTR_IDENT (ENUM, STRING)
Constructs an IDENTIFIER_NODE for STRING.
DEF_ATTR_TREE_LIST (ENUM, PURPOSE, VALUE, CHAIN)
Constructs a TREE_LIST with given PURPOSE, VALUE and CHAIN (given
as previous ENUM names).
DEF_FN_ATTR (NAME, ATTRS, PREDICATE)
Specifies that the function with name NAME (a previous ENUM for an
IDENTIFIER_NODE) has attributes ATTRS (a previous ENUM) if
PREDICATE is true. */
DEF_ATTR_NULL_TREE (ATTR_NULL)
/* Note that below we must avoid whitespace in arguments of CONCAT*. */
/* Construct a tree for a given integer and a list containing it. */
#define DEF_ATTR_FOR_INT(VALUE) \
DEF_ATTR_INT (CONCAT2 (ATTR_,VALUE), VALUE) \
DEF_ATTR_TREE_LIST (CONCAT2 (ATTR_LIST_,VALUE), ATTR_NULL, \
CONCAT2 (ATTR_,VALUE), ATTR_NULL)
DEF_ATTR_FOR_INT (0)
DEF_ATTR_FOR_INT (1)
DEF_ATTR_FOR_INT (2)
DEF_ATTR_FOR_INT (3)
DEF_ATTR_FOR_INT (4)
#undef DEF_ATTR_FOR_INT
/* Construct a tree for a list of two integers. */
#define DEF_LIST_INT_INT(VALUE1, VALUE2) \
DEF_ATTR_TREE_LIST (CONCAT4 (ATTR_LIST_,VALUE1,_,VALUE2), ATTR_NULL, \
CONCAT2 (ATTR_,VALUE1), CONCAT2 (ATTR_LIST_,VALUE2))
DEF_LIST_INT_INT (1,0)
DEF_LIST_INT_INT (1,2)
DEF_LIST_INT_INT (2,0)
DEF_LIST_INT_INT (2,3)
DEF_LIST_INT_INT (3,0)
DEF_LIST_INT_INT (3,4)
#undef DEF_LIST_INT_INT
DEF_ATTR_IDENT (ATTR_PRINTF, "printf")
DEF_ATTR_IDENT (ATTR_SCANF, "scanf")
DEF_ATTR_IDENT (ATTR_STRFTIME, "strftime")
DEF_ATTR_IDENT (ATTR_STRFMON, "strfmon")
DEF_ATTR_IDENT (ATTR_FORMAT, "format")
DEF_ATTR_IDENT (ATTR_FORMAT_ARG, "format_arg")
/* Construct a tree for a format attribute. */
#define DEF_FORMAT_ATTRIBUTE(TYPE, VALUES) \
DEF_ATTR_TREE_LIST (CONCAT4 (ATTR_,TYPE,_,VALUES), ATTR_NULL, \
CONCAT2 (ATTR_,TYPE), CONCAT2 (ATTR_LIST_,VALUES)) \
DEF_ATTR_TREE_LIST (CONCAT4 (ATTR_FORMAT_,TYPE,_,VALUES), ATTR_FORMAT, \
CONCAT4 (ATTR_,TYPE,_,VALUES), ATTR_NULL)
DEF_FORMAT_ATTRIBUTE(PRINTF,1_0)
DEF_FORMAT_ATTRIBUTE(PRINTF,1_2)
DEF_FORMAT_ATTRIBUTE(PRINTF,2_0)
DEF_FORMAT_ATTRIBUTE(PRINTF,2_3)
DEF_FORMAT_ATTRIBUTE(PRINTF,3_0)
DEF_FORMAT_ATTRIBUTE(PRINTF,3_4)
DEF_FORMAT_ATTRIBUTE(SCANF,1_0)
DEF_FORMAT_ATTRIBUTE(SCANF,1_2)
DEF_FORMAT_ATTRIBUTE(SCANF,2_0)
DEF_FORMAT_ATTRIBUTE(SCANF,2_3)
DEF_FORMAT_ATTRIBUTE(STRFTIME,3_0)
DEF_FORMAT_ATTRIBUTE(STRFMON,3_4)
#undef DEF_FORMAT_ATTRIBUTE
DEF_ATTR_TREE_LIST (ATTR_FORMAT_ARG_1, ATTR_FORMAT_ARG, ATTR_LIST_1, ATTR_NULL)
DEF_ATTR_TREE_LIST (ATTR_FORMAT_ARG_2, ATTR_FORMAT_ARG, ATTR_LIST_2, ATTR_NULL)
/* Define an attribute for a function, along with the IDENTIFIER_NODE. */
#define DEF_FN_ATTR_IDENT(NAME, ATTRS, PREDICATE) \
DEF_ATTR_IDENT (CONCAT2(ATTR_,NAME), STRINGX(NAME)) \
DEF_FN_ATTR (CONCAT2(ATTR_,NAME), ATTRS, PREDICATE)
/* The ISO C functions are always checked (whether <stdio.h> is
included or not), since it is common to call printf without
including <stdio.h>. There shouldn't be a problem with this,
since ISO C reserves these function names whether you include the
header file or not. In any case, the checking is harmless. With
-ffreestanding, these default attributes are disabled, and must be
specified manually if desired. */
/* __builtin functions should be checked unconditionally, even with
-ffreestanding. */
DEF_FN_ATTR_IDENT (__builtin_printf, ATTR_FORMAT_PRINTF_1_2, true)
DEF_FN_ATTR_IDENT (__builtin_fprintf, ATTR_FORMAT_PRINTF_2_3, true)
/* Functions from ISO/IEC 9899:1990. */
#define DEF_C89_ATTR(NAME, ATTRS) DEF_FN_ATTR_IDENT (NAME, ATTRS, flag_hosted)
DEF_C89_ATTR (printf, ATTR_FORMAT_PRINTF_1_2)
DEF_C89_ATTR (fprintf, ATTR_FORMAT_PRINTF_2_3)
DEF_C89_ATTR (sprintf, ATTR_FORMAT_PRINTF_2_3)
DEF_C89_ATTR (scanf, ATTR_FORMAT_SCANF_1_2)
DEF_C89_ATTR (fscanf, ATTR_FORMAT_SCANF_2_3)
DEF_C89_ATTR (sscanf, ATTR_FORMAT_SCANF_2_3)
DEF_C89_ATTR (vprintf, ATTR_FORMAT_PRINTF_1_0)
DEF_C89_ATTR (vfprintf, ATTR_FORMAT_PRINTF_2_0)
DEF_C89_ATTR (vsprintf, ATTR_FORMAT_PRINTF_2_0)
DEF_C89_ATTR (strftime, ATTR_FORMAT_STRFTIME_3_0)
#undef DEF_C89_ATTR
/* ISO C99 adds the snprintf and vscanf family functions. */
#define DEF_C99_ATTR(NAME, ATTRS) \
DEF_FN_ATTR_IDENT (NAME, ATTRS, \
(flag_hosted \
&& (flag_isoc99 || flag_noniso_default_format_attributes)))
DEF_C99_ATTR (snprintf, ATTR_FORMAT_PRINTF_3_4)
DEF_C99_ATTR (vsnprintf, ATTR_FORMAT_PRINTF_3_0)
DEF_C99_ATTR (vscanf, ATTR_FORMAT_SCANF_1_0)
DEF_C99_ATTR (vfscanf, ATTR_FORMAT_SCANF_2_0)
DEF_C99_ATTR (vsscanf, ATTR_FORMAT_SCANF_2_0)
#undef DEF_C99_ATTR
/* Functions not in any version of ISO C. */
#define DEF_EXT_ATTR(NAME, ATTRS) \
DEF_FN_ATTR_IDENT (NAME, ATTRS, \
flag_hosted && flag_noniso_default_format_attributes)
/* Uniforum/GNU gettext functions. */
DEF_EXT_ATTR (gettext, ATTR_FORMAT_ARG_1)
DEF_EXT_ATTR (dgettext, ATTR_FORMAT_ARG_2)
DEF_EXT_ATTR (dcgettext, ATTR_FORMAT_ARG_2)
/* X/Open strfmon function. */
DEF_EXT_ATTR (strfmon, ATTR_FORMAT_STRFMON_3_4)
#undef DEF_EXT_ATTR
#undef DEF_FN_ATTR_IDENT

View File

@ -2324,6 +2324,18 @@ c_alignof_expr (expr)
return fold (build1 (NOP_EXPR, c_size_type_node, t));
}
/* Give the specifications for the format attributes, used by C and all
descendents. */
static const struct attribute_spec c_format_attribute_table[] =
{
{ "format", 3, 3, true, false, false,
handle_format_attribute },
{ "format_arg", 1, 1, true, false, false,
handle_format_arg_attribute },
{ NULL, 0, 0, false, false, false, NULL }
};
/* Build tree nodes and builtin functions common to both C and C++ language
frontends. */
@ -2369,6 +2381,10 @@ c_common_nodes_and_builtins ()
tree va_list_ref_type_node;
tree va_list_arg_type_node;
/* We must initialize this before any builtin functions (which might have
attributes) are declared. (c_common_lang_init is too late.) */
format_attribute_table = c_format_attribute_table;
/* Define `int' and `char' first so that dbx will output them first. */
record_builtin_type (RID_INT, NULL, integer_type_node);
record_builtin_type (RID_CHAR, "char", char_type_node);
@ -3774,24 +3790,34 @@ boolean_increment (code, arg)
return val;
}
/* Give the specifications for the format attributes, used by C and all
descendents. */
/* Handle C and C++ default attributes. */
static const struct attribute_spec c_format_attribute_table[] =
enum built_in_attribute
{
{ "format", 3, 3, true, false, false,
handle_format_attribute },
{ "format_arg", 1, 1, true, false, false,
handle_format_arg_attribute },
{ NULL, 0, 0, false, false, false, NULL }
#define DEF_ATTR_NULL_TREE(ENUM) ENUM,
#define DEF_ATTR_INT(ENUM, VALUE) ENUM,
#define DEF_ATTR_IDENT(ENUM, STRING) ENUM,
#define DEF_ATTR_TREE_LIST(ENUM, PURPOSE, VALUE, CHAIN) ENUM,
#define DEF_FN_ATTR(NAME, ATTRS, PREDICATE) /* No entry needed in enum. */
#include "builtin-attrs.def"
#undef DEF_ATTR_NULL_TREE
#undef DEF_ATTR_INT
#undef DEF_ATTR_IDENT
#undef DEF_ATTR_TREE_LIST
#undef DEF_FN_ATTR
ATTR_LAST
};
static tree built_in_attributes[(int) ATTR_LAST];
static bool c_attrs_initialized = false;
static void c_init_attributes PARAMS ((void));
/* Do the parts of lang_init common to C and C++. */
void
c_common_lang_init ()
{
format_attribute_table = c_format_attribute_table;
/* If still "unspecified", make it match -fbounded-pointers. */
if (flag_bounds_check < 0)
flag_bounds_check = flag_bounded_pointers;
@ -3808,4 +3834,60 @@ c_common_lang_init ()
warning ("-Wformat-security ignored without -Wformat");
if (warn_missing_format_attribute && !warn_format)
warning ("-Wmissing-format-attribute ignored without -Wformat");
if (!c_attrs_initialized)
c_init_attributes ();
}
static void
c_init_attributes ()
{
/* Fill in the built_in_attributes array. */
#define DEF_ATTR_NULL_TREE(ENUM) \
built_in_attributes[(int) ENUM] = NULL_TREE;
#define DEF_ATTR_INT(ENUM, VALUE) \
built_in_attributes[(int) ENUM] = build_int_2 (VALUE, VALUE < 0 ? -1 : 0);
#define DEF_ATTR_IDENT(ENUM, STRING) \
built_in_attributes[(int) ENUM] = get_identifier (STRING);
#define DEF_ATTR_TREE_LIST(ENUM, PURPOSE, VALUE, CHAIN) \
built_in_attributes[(int) ENUM] \
= tree_cons (built_in_attributes[(int) PURPOSE], \
built_in_attributes[(int) VALUE], \
built_in_attributes[(int) CHAIN]);
#define DEF_FN_ATTR(NAME, ATTRS, PREDICATE) /* No initialization needed. */
#include "builtin-attrs.def"
#undef DEF_ATTR_NULL_TREE
#undef DEF_ATTR_INT
#undef DEF_ATTR_IDENT
#undef DEF_ATTR_TREE_LIST
#undef DEF_FN_ATTR
ggc_add_tree_root (built_in_attributes, (int) ATTR_LAST);
c_attrs_initialized = true;
}
/* Depending on the name of DECL, apply default attributes to it. */
void
c_common_insert_default_attributes (decl)
tree decl;
{
tree name = DECL_NAME (decl);
if (!c_attrs_initialized)
c_init_attributes ();
#define DEF_ATTR_NULL_TREE(ENUM) /* Nothing needed after initialization. */
#define DEF_ATTR_INT(ENUM, VALUE)
#define DEF_ATTR_IDENT(ENUM, STRING)
#define DEF_ATTR_TREE_LIST(ENUM, PURPOSE, VALUE, CHAIN)
#define DEF_FN_ATTR(NAME, ATTRS, PREDICATE) \
if ((PREDICATE) && name == built_in_attributes[(int) NAME]) \
decl_attributes (&decl, built_in_attributes[(int) ATTRS], \
ATTR_FLAG_BUILT_IN);
#include "builtin-attrs.def"
#undef DEF_ATTR_NULL_TREE
#undef DEF_ATTR_INT
#undef DEF_ATTR_IDENT
#undef DEF_ATTR_TREE_LIST
#undef DEF_FN_ATTR
}

View File

@ -503,13 +503,13 @@ extern const char *fname_as_string PARAMS ((int));
extern tree fname_decl PARAMS ((unsigned, tree));
extern const char *fname_string PARAMS ((unsigned));
extern void init_function_format_info PARAMS ((void));
extern void check_function_format PARAMS ((int *, tree, tree, tree));
extern void set_Wformat PARAMS ((int));
extern tree handle_format_attribute PARAMS ((tree *, tree, tree,
int, bool *));
extern tree handle_format_arg_attribute PARAMS ((tree *, tree, tree,
int, bool *));
extern void c_common_insert_default_attributes PARAMS ((tree));
extern void c_apply_type_quals_to_decl PARAMS ((int, tree));
extern tree c_sizeof PARAMS ((tree));
extern tree c_alignof PARAMS ((tree));

View File

@ -2505,7 +2505,7 @@ tree
implicitly_declare (functionid)
tree functionid;
{
register tree decl;
tree decl;
int traditional_warning = 0;
/* Only one "implicit declaration" warning per identifier. */
int implicit_warning;
@ -2555,6 +2555,9 @@ implicitly_declare (functionid)
gen_aux_info_record (decl, 0, 1, 0);
/* Possibly apply some default attributes to this implicit declaration. */
decl_attributes (&decl, NULL_TREE, 0);
return decl;
}
@ -3056,9 +3059,6 @@ init_decl_processing ()
make_fname_decl = c_make_fname_decl;
start_fname_decls ();
/* Prepare to check format strings against argument lists. */
init_function_format_info ();
incomplete_decl_finalize_hook = finish_incomplete_decl;
/* Record our roots. */
@ -3152,8 +3152,23 @@ builtin_function (name, type, function_code, class, library_name)
if (name[0] != '_' || name[1] != '_')
C_DECL_ANTICIPATED (decl) = 1;
/* Possibly apply some default attributes to this built-in function. */
decl_attributes (&decl, NULL_TREE, 0);
return decl;
}
/* Apply default attributes to a function, if a system function with default
attributes. */
void
insert_default_attributes (decl)
tree decl;
{
if (!TREE_PUBLIC (decl))
return;
c_common_insert_default_attributes (decl);
}
/* Called when a declaration is seen that contains no names to declare.
If its type is a reference to a structure, union or enum inherited

View File

@ -89,7 +89,7 @@ handle_format_attribute (node, name, args, flags, no_add_attrs)
tree *node;
tree name ATTRIBUTE_UNUSED;
tree args;
int flags ATTRIBUTE_UNUSED;
int flags;
bool *no_add_attrs;
{
tree decl = *node;
@ -177,7 +177,8 @@ handle_format_attribute (node, name, args, flags, no_add_attrs)
|| (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_VALUE (argument)))
!= char_type_node))
{
error ("format string arg not a string type");
if (!(flags & (int) ATTR_FLAG_BUILT_IN))
error ("format string arg not a string type");
*no_add_attrs = true;
return NULL_TREE;
}
@ -191,7 +192,8 @@ handle_format_attribute (node, name, args, flags, no_add_attrs)
if (arg_num != first_arg_num)
{
error ("args to be formatted is not '...'");
if (!(flags & (int) ATTR_FLAG_BUILT_IN))
error ("args to be formatted is not '...'");
*no_add_attrs = true;
return NULL_TREE;
}
@ -218,7 +220,7 @@ handle_format_arg_attribute (node, name, args, flags, no_add_attrs)
tree *node;
tree name ATTRIBUTE_UNUSED;
tree args;
int flags ATTRIBUTE_UNUSED;
int flags;
bool *no_add_attrs;
{
tree decl = *node;
@ -268,7 +270,8 @@ handle_format_arg_attribute (node, name, args, flags, no_add_attrs)
|| (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_VALUE (argument)))
!= char_type_node))
{
error ("format string arg not a string type");
if (!(flags & (int) ATTR_FLAG_BUILT_IN))
error ("format string arg not a string type");
*no_add_attrs = true;
return NULL_TREE;
}
@ -278,7 +281,8 @@ handle_format_arg_attribute (node, name, args, flags, no_add_attrs)
|| (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (TREE_TYPE (decl))))
!= char_type_node))
{
error ("function does not return string type");
if (!(flags & (int) ATTR_FLAG_BUILT_IN))
error ("function does not return string type");
*no_add_attrs = true;
return NULL_TREE;
}
@ -310,80 +314,6 @@ typedef struct international_format_info
static international_format_info *international_format_list = NULL;
/* Initialize the table of functions to perform format checking on.
The ISO C functions are always checked (whether <stdio.h> is
included or not), since it is common to call printf without
including <stdio.h>. There shouldn't be a problem with this,
since ISO C reserves these function names whether you include the
header file or not. In any case, the checking is harmless. With
-ffreestanding, these default attributes are disabled, and must be
specified manually if desired.
Also initialize the name of function that modify the format string for
internationalization purposes. */
void
init_function_format_info ()
{
/* __builtin functions should be checked unconditionally, even with
-ffreestanding. */
record_function_format (get_identifier ("__builtin_printf"), NULL_TREE,
printf_format_type, 1, 2);
record_function_format (get_identifier ("__builtin_fprintf"), NULL_TREE,
printf_format_type, 2, 3);
if (flag_hosted)
{
/* Functions from ISO/IEC 9899:1990. */
record_function_format (get_identifier ("printf"), NULL_TREE,
printf_format_type, 1, 2);
record_function_format (get_identifier ("fprintf"), NULL_TREE,
printf_format_type, 2, 3);
record_function_format (get_identifier ("sprintf"), NULL_TREE,
printf_format_type, 2, 3);
record_function_format (get_identifier ("scanf"), NULL_TREE,
scanf_format_type, 1, 2);
record_function_format (get_identifier ("fscanf"), NULL_TREE,
scanf_format_type, 2, 3);
record_function_format (get_identifier ("sscanf"), NULL_TREE,
scanf_format_type, 2, 3);
record_function_format (get_identifier ("vprintf"), NULL_TREE,
printf_format_type, 1, 0);
record_function_format (get_identifier ("vfprintf"), NULL_TREE,
printf_format_type, 2, 0);
record_function_format (get_identifier ("vsprintf"), NULL_TREE,
printf_format_type, 2, 0);
record_function_format (get_identifier ("strftime"), NULL_TREE,
strftime_format_type, 3, 0);
}
if (flag_hosted && (flag_isoc99 || flag_noniso_default_format_attributes))
{
/* ISO C99 adds the snprintf and vscanf family functions. */
record_function_format (get_identifier ("snprintf"), NULL_TREE,
printf_format_type, 3, 4);
record_function_format (get_identifier ("vsnprintf"), NULL_TREE,
printf_format_type, 3, 0);
record_function_format (get_identifier ("vscanf"), NULL_TREE,
scanf_format_type, 1, 0);
record_function_format (get_identifier ("vfscanf"), NULL_TREE,
scanf_format_type, 2, 0);
record_function_format (get_identifier ("vsscanf"), NULL_TREE,
scanf_format_type, 2, 0);
}
if (flag_hosted && flag_noniso_default_format_attributes)
{
/* Uniforum/GNU gettext functions, not in ISO C. */
record_international_format (get_identifier ("gettext"), NULL_TREE, 1);
record_international_format (get_identifier ("dgettext"), NULL_TREE, 2);
record_international_format (get_identifier ("dcgettext"), NULL_TREE, 2);
/* X/Open strfmon function. */
record_function_format (get_identifier ("strfmon"), NULL_TREE,
strfmon_format_type, 3, 4);
}
}
/* Record information for argument format checking. FUNCTION_IDENT is
the identifier node for the name of the function to check (its decl
need not exist yet).

View File

@ -1,3 +1,11 @@
2001-10-02 Joseph S. Myers <jsm28@cam.ac.uk>
* decl.c (init_decl_processing): Don't call
init_function_format_info. Initialize lang_attribute_table
earlier.
(builtin_function): Call decl_attributes.
(insert_default_attributes): New.
2001-10-01 Jason Merrill <jason_merrill@redhat.com>
* decl.c (grokdeclarator): Copy array typedef handling from C

View File

@ -6350,6 +6350,8 @@ init_decl_processing ()
std_node = current_namespace;
pop_namespace ();
lang_attribute_table = cp_attribute_table;
c_common_nodes_and_builtins ();
java_byte_type_node = record_builtin_java_type ("__java_byte", 8);
@ -6487,14 +6489,9 @@ init_decl_processing ()
make_fname_decl = cp_make_fname_decl;
start_fname_decls ();
/* Prepare to check format strings against argument lists. */
init_function_format_info ();
/* Show we use EH for cleanups. */
using_eh_for_cleanups ();
lang_attribute_table = cp_attribute_table;
/* Maintain consistency. Perhaps we should just complain if they
say -fwritable-strings? */
if (flag_writable_strings)
@ -6643,6 +6640,9 @@ builtin_function (name, type, code, class, libname)
if (name[0] != '_' || name[1] != '_')
DECL_ANTICIPATED (decl) = 1;
/* Possibly apply some default attributes to this built-in function. */
decl_attributes (&decl, NULL_TREE, 0);
return decl;
}
@ -6765,6 +6765,20 @@ push_throw_library_fn (name, type)
TREE_NOTHROW (fn) = 0;
return fn;
}
/* Apply default attributes to a function, if a system function with default
attributes. */
void
insert_default_attributes (decl)
tree decl;
{
if (!DECL_EXTERN_C_FUNCTION_P (decl))
return;
if (!TREE_PUBLIC (decl))
return;
c_common_insert_default_attributes (decl);
}
/* When we call finish_struct for an anonymous union, we create
default copy constructors and such. But, an anonymous union

View File

@ -1,3 +1,7 @@
2001-10-02 Joseph S. Myers <jsm28@cam.ac.uk>
* gcc.dg/format/attr-5.c, gcc.dg/format/attr-6.c: New tests.
2001-10-02 Joseph S. Myers <jsm28@cam.ac.uk>
* g++.dg/warn/format1.C: New test.

View File

@ -0,0 +1,28 @@
/* Test for format attributes: test default attributes are silently ignored
when a function is redeclared in an inappropriate manner. */
/* Origin: Joseph Myers <jsm28@cam.ac.uk> */
/* { dg-do compile } */
/* { dg-options "-std=gnu99 -Wformat" } */
/* We can't #include "format.h" here. */
/* This scanf declaration is static, so can't be the system function. */
static int scanf(const char *restrict, ...);
/* This sscanf declaration doesn't have variable arguments, so isn't
compatible with a format attribute. */
extern int sscanf(const char *restrict, const char *restrict, int *);
void
foo (const char *s, int *p)
{
scanf("%ld", p); /* { dg-bogus "format" "static" } */
sscanf(s, "%ld", p); /* { dg-bogus "format" "wrong type" } */
}
/* Dummy definition of scanf. */
static int
scanf (const char *restrict fmt, ...)
{
return 0;
}

View File

@ -0,0 +1,21 @@
/* Test for format attributes: test default attributes are applied
to implicit declarations. */
/* Origin: Joseph Myers <jsm28@cam.ac.uk> */
/* { dg-do compile } */
/* { dg-options "-std=gnu89 -Wformat" } */
/* We can't #include "format.h" here. */
/* Technically, none of the format functions should be implicitly declared;
either the implicit type is wrong, the function has variable arguments
or it requires a type declared in a header. However, some bad programming
practice uses implicit declarations of some of these functions.
Note that printf is not used in this test because of the declaration
of it as a built-in function. */
void
foo (const char *s, int *p)
{
scanf("%ld", p); /* { dg-warning "format" "implicit scanf" } */
}

View File

@ -2140,7 +2140,11 @@ enum attribute_flags
ATTR_FLAG_ARRAY_NEXT = 4,
/* The type passed in is a structure, union or enumeration type being
created, and should be modified in place. */
ATTR_FLAG_TYPE_IN_PLACE = 8
ATTR_FLAG_TYPE_IN_PLACE = 8,
/* The attributes are being applied by default to a library function whose
name indicates known behavior, and should be silently ignored if they
are not in fact compatible with the function type. */
ATTR_FLAG_BUILT_IN = 16
};
/* Default versions of target-overridable functions. */
@ -2920,6 +2924,13 @@ extern int setjmp_call_p PARAMS ((tree));
a decl attribute to the declaration rather than to its type). */
extern tree decl_attributes PARAMS ((tree *, tree, int));
/* The following function must be provided by front ends
using attribs.c. */
/* Possibly apply default attributes to a function (represented by
a FUNCTION_DECL). */
extern void insert_default_attributes PARAMS ((tree));
/* Table of machine-independent attributes for checking formats, if used. */
extern const struct attribute_spec *format_attribute_table;