mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-03-19 01:40:39 +08:00
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:
parent
ed0ea5602b
commit
6431177a55
@ -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.
|
||||
|
@ -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.
|
||||
|
||||
|
@ -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
166
gcc/builtin-attrs.def
Normal 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
|
102
gcc/c-common.c
102
gcc/c-common.c
@ -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
|
||||
}
|
||||
|
@ -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));
|
||||
|
23
gcc/c-decl.c
23
gcc/c-decl.c
@ -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
|
||||
|
@ -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).
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
28
gcc/testsuite/gcc.dg/format/attr-5.c
Normal file
28
gcc/testsuite/gcc.dg/format/attr-5.c
Normal 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;
|
||||
}
|
21
gcc/testsuite/gcc.dg/format/attr-6.c
Normal file
21
gcc/testsuite/gcc.dg/format/attr-6.c
Normal 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" } */
|
||||
}
|
13
gcc/tree.h
13
gcc/tree.h
@ -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;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user