diff --git a/gcc/attribs.c b/gcc/attribs.c index 19e99ad3055..f342cd16bf3 100644 --- a/gcc/attribs.c +++ b/gcc/attribs.c @@ -82,6 +82,8 @@ static tree handle_no_limit_stack_attribute PARAMS ((tree *, tree, tree, int, bool *)); static tree handle_pure_attribute PARAMS ((tree *, tree, tree, int, bool *)); +static tree handle_deprecated_attribute PARAMS ((tree *, tree, tree, int, + bool *)); static tree handle_vector_size_attribute PARAMS ((tree *, tree, tree, int, bool *)); static tree vector_size_helper PARAMS ((tree, tree)); @@ -138,6 +140,8 @@ static const struct attribute_spec c_common_attribute_table[] = handle_no_limit_stack_attribute }, { "pure", 0, 0, true, false, false, handle_pure_attribute }, + { "deprecated", 0, 0, false, false, false, + handle_deprecated_attribute }, { "vector_size", 1, 1, false, true, false, handle_vector_size_attribute }, { NULL, 0, 0, false, false, false, NULL } @@ -1131,6 +1135,67 @@ handle_pure_attribute (node, name, args, flags, no_add_attrs) return NULL_TREE; } +/* Handle a "deprecated" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_deprecated_attribute (node, name, args, flags, no_add_attrs) + tree *node; + tree name; + tree args ATTRIBUTE_UNUSED; + int flags; + bool *no_add_attrs; +{ + tree type = NULL_TREE; + int warn = 0; + char *what = NULL; + + if (DECL_P (*node)) + { + tree decl = *node; + type = TREE_TYPE (decl); + + if (TREE_CODE (decl) == TYPE_DECL + || TREE_CODE (decl) == PARM_DECL + || TREE_CODE (decl) == VAR_DECL + || TREE_CODE (decl) == FUNCTION_DECL + || TREE_CODE (decl) == FIELD_DECL) + TREE_DEPRECATED (decl) = 1; + else + warn = 1; + } + else if (TYPE_P (*node)) + { + if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE)) + *node = build_type_copy (*node); + TREE_DEPRECATED (*node) = 1; + type = *node; + } + else + warn = 1; + + if (warn) + { + *no_add_attrs = true; + if (type && TYPE_NAME (type)) + { + if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE) + what = IDENTIFIER_POINTER (TYPE_NAME (*node)); + else if (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL + && DECL_NAME (TYPE_NAME (type))) + what = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type))); + } + if (what) + warning ("`%s' attribute ignored for `%s'", + IDENTIFIER_POINTER (name), what); + else + warning ("`%s' attribute ignored", + IDENTIFIER_POINTER (name)); + } + + return NULL_TREE; +} + /* Handle a "vector_size" attribute; arguments as in struct attribute_spec.handler. */ diff --git a/gcc/c-decl.c b/gcc/c-decl.c index d6e8ac33469..206c7718ba1 100644 --- a/gcc/c-decl.c +++ b/gcc/c-decl.c @@ -439,6 +439,18 @@ int warn_multichar = 1; #endif int dollars_in_ident = DOLLARS_IN_IDENTIFIERS; +/* States indicating how grokdeclarator() should handle declspecs marked + with __attribute__((deprecated)). An object declared as + __attribute__((deprecated)) suppresses warnings of uses of other + deprecated items. */ + +enum deprecated_states { + DEPRECATED_NORMAL, + DEPRECATED_SUPPRESS +}; + +static enum deprecated_states deprecated_state = DEPRECATED_NORMAL; + /* Decode the string P as a language-specific option for C. Return the number of strings consumed. Should not complain if it does not recognise the option. */ @@ -3420,9 +3432,18 @@ start_decl (declarator, declspecs, initialized, attributes) int initialized; tree attributes; { - tree decl = grokdeclarator (declarator, declspecs, - NORMAL, initialized); + tree decl; tree tem; + + /* An object declared as __attribute__((deprecated)) suppresses + warnings of uses of other deprecated items. */ + if (lookup_attribute ("deprecated", attributes)) + deprecated_state = DEPRECATED_SUPPRESS; + + decl = grokdeclarator (declarator, declspecs, + NORMAL, initialized); + + deprecated_state = DEPRECATED_NORMAL; if (warn_main > 0 && TREE_CODE (decl) != FUNCTION_DECL && MAIN_NAME_P (DECL_NAME (decl))) @@ -4091,6 +4112,14 @@ grokdeclarator (declarator, declspecs, decl_context, initialized) { tree id = TREE_VALUE (spec); + /* If the entire declaration is itself tagged as deprecated then + suppress reports of deprecated items. */ + if (id && TREE_DEPRECATED (id)) + { + if (deprecated_state != DEPRECATED_SUPPRESS) + warn_deprecated_use (id); + } + if (id == ridpointers[(int) RID_INT]) explicit_int = 1; if (id == ridpointers[(int) RID_CHAR]) diff --git a/gcc/c-typeck.c b/gcc/c-typeck.c index cf3a387e99f..2c476989c68 100644 --- a/gcc/c-typeck.c +++ b/gcc/c-typeck.c @@ -1199,6 +1199,10 @@ build_component_ref (datum, component) TREE_READONLY (ref) = 1; if (TREE_THIS_VOLATILE (datum) || TREE_THIS_VOLATILE (subdatum)) TREE_THIS_VOLATILE (ref) = 1; + + if (TREE_DEPRECATED (subdatum)) + warn_deprecated_use (subdatum); + datum = ref; } @@ -1415,6 +1419,9 @@ build_external_ref (id, fun) tree decl = lookup_name (id); tree objc_ivar = lookup_objc_ivar (id); + if (decl && TREE_DEPRECATED (decl)) + warn_deprecated_use (decl); + if (!decl || decl == error_mark_node || C_DECL_ANTICIPATED (decl)) { if (objc_ivar) diff --git a/gcc/cp/call.c b/gcc/cp/call.c index dfdf1aac867..0b8ec03375e 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -407,7 +407,10 @@ build_call (function, parms) throw without being declared throw(). */ nothrow = ((decl && TREE_NOTHROW (decl)) || TYPE_NOTHROW_P (TREE_TYPE (TREE_TYPE (function)))); - + + if (decl && TREE_DEPRECATED (decl)) + warn_deprecated_use (decl); + if (decl && DECL_CONSTRUCTOR_P (decl)) is_constructor = 1; diff --git a/gcc/cp/class.c b/gcc/cp/class.c index a1817e32809..6e9e34e8faf 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -2926,6 +2926,8 @@ add_implicitly_declared_members (t, cant_have_default_ctor, tree virtual_dtor = NULL_TREE; tree *f; + ++adding_implicit_members; + /* Destructor. */ if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t) && !TYPE_HAS_DESTRUCTOR (t)) { @@ -2985,6 +2987,8 @@ add_implicitly_declared_members (t, cant_have_default_ctor, *f = TYPE_METHODS (t); TYPE_METHODS (t) = implicit_fns; + --adding_implicit_members; + return virtual_dtor; } diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 9538921a2eb..c157466a572 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -3108,6 +3108,11 @@ extern int warn_overloaded_virtual; /* Nonzero means warn about use of multicharacter literals. */ extern int warn_multichar; +/* Set by add_implicitly_declared_members() to keep those members from + being flagged as deprecated or reported as using deprecated + types. */ +extern int adding_implicit_members; + /* Non-zero means warn if a non-templatized friend function is declared in a templatized class. This behavior is warned about with flag_guiding_decls in do_friend. */ diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 944fe93161b..ed163fdece7 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -302,6 +302,23 @@ tree anonymous_namespace_name; (Zero if we are at namespace scope, one inside the body of a function, two inside the body of a function in a local class, etc.) */ int function_depth; + +/* States indicating how grokdeclarator() should handle declspecs marked + with __attribute__((deprecated)). An object declared as + __attribute__((deprecated)) suppresses warnings of uses of other + deprecated items. */ + +enum deprecated_states { + DEPRECATED_NORMAL, + DEPRECATED_SUPPRESS +}; + +static enum deprecated_states deprecated_state = DEPRECATED_NORMAL; + +/* Set by add_implicitly_declared_members() to keep those members from + being flagged as deprecated or reported as using deprecated + types. */ +int adding_implicit_members = 0; /* For each binding contour we allocate a binding_level structure which records the names defined in that contour. @@ -7161,11 +7178,18 @@ start_decl (declarator, declspecs, initialized, attributes, prefix_attributes) used_extern_spec = 1; } + /* An object declared as __attribute__((deprecated)) suppresses + warnings of uses of other deprecated items. */ + if (lookup_attribute ("deprecated", attributes)) + deprecated_state = DEPRECATED_SUPPRESS; + attributes = chainon (attributes, prefix_attributes); decl = grokdeclarator (declarator, declspecs, NORMAL, initialized, &attributes); + deprecated_state = DEPRECATED_NORMAL; + if (decl == NULL_TREE || TREE_CODE (decl) == VOID_TYPE) return NULL_TREE; @@ -9992,6 +10016,14 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist) id = TREE_VALUE (spec); + /* If the entire declaration is itself tagged as deprecated then + suppress reports of deprecated items. */ + if (!adding_implicit_members && id && TREE_DEPRECATED (id)) + { + if (deprecated_state != DEPRECATED_SUPPRESS) + warn_deprecated_use (id); + } + if (TREE_CODE (id) == IDENTIFIER_NODE) { if (id == ridpointers[(int) RID_INT] diff --git a/gcc/cp/lex.c b/gcc/cp/lex.c index 82b14ae5623..a6d983a1012 100644 --- a/gcc/cp/lex.c +++ b/gcc/cp/lex.c @@ -1215,6 +1215,9 @@ do_identifier (token, parsing, args) else id = lastiddecl; + if (lexing && id && TREE_DEPRECATED (id)) + warn_deprecated_use (id); + /* Do Koenig lookup if appropriate (inside templates we build lookup expressions instead). diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index b939de70447..c189b6d37c8 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -2199,6 +2199,9 @@ build_component_ref (datum, component, basetype_path, protect) } } + if (TREE_DEPRECATED (field)) + warn_deprecated_use (field); + /* See if we have to do any conversions so that we pick up the field from the right context. */ if (DECL_FIELD_CONTEXT (field) != basetype) diff --git a/gcc/diagnostic.c b/gcc/diagnostic.c index d5664015979..ac3539beda1 100644 --- a/gcc/diagnostic.c +++ b/gcc/diagnostic.c @@ -1520,3 +1520,44 @@ default_diagnostic_finalizer (buffer, dc) { output_destroy_prefix (buffer); } + +void +warn_deprecated_use (node) + tree node; +{ + if (node && warn_deprecated_decl) + if (DECL_P (node)) + { + warning ("`%s' is deprecated (declared at %s:%d)", + IDENTIFIER_POINTER (DECL_NAME (node)), + DECL_SOURCE_FILE (node), DECL_SOURCE_LINE (node)); + } + else if (TYPE_P (node)) + { + char *what = NULL; + tree decl = TYPE_STUB_DECL (node); + + if (TREE_CODE (TYPE_NAME (node)) == IDENTIFIER_NODE) + what = IDENTIFIER_POINTER (TYPE_NAME (node)); + else if (TREE_CODE (TYPE_NAME (node)) == TYPE_DECL + && DECL_NAME (TYPE_NAME (node))) + what = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (node))); + + if (what) + { + if (decl) + warning ("`%s' is deprecated (declared at %s:%d)", what, + DECL_SOURCE_FILE (decl), DECL_SOURCE_LINE (decl)); + else + warning ("`%s' is deprecated", what); + } + else + { + if (decl) + warning ("type is deprecated (declared at %s:%d)", + DECL_SOURCE_FILE (decl), DECL_SOURCE_LINE (decl)); + else + warning ("type is deprecated"); + } + } +} diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index 2e22c1b7d9b..63095ba3c0f 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -1882,11 +1882,11 @@ attributes 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}, and @code{alias}. 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}). +@code{unused}, @code{deprecated}, @code{weak}, @code{malloc}, and +@code{alias}. 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}). You may also specify attributes with @samp{__} preceding and following each keyword. This allows you to use them in header files without @@ -2147,6 +2147,27 @@ 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. +@cindex @code{deprecated} attribute. +@item deprecated +The @code{deprecated} attribute results in a warning if the function +is used anywhere in the source file. This is useful when identifying +functions that are expected to be removed in a future version of a +program. The warning also includes the location of the declaration +of the deprecated function, to enable users to easily find further +information about why the function is deprecated, or what they should +do instead. Note that the warnings only occurs for uses: + +@smallexample +int old_fn () __attribute__ ((deprecated)); +int old_fn (); +int (*fn_ptr)() = old_fn; +@end smallexample + +results in a warning on line 3 but not line 2. + +The @code{deprecated} attribute can also be used for variables and +types (@pxref{Variable Attributes}, @pxref{Type Attributes}.) + @item weak @cindex @code{weak} attribute The @code{weak} attribute causes the declaration to be emitted as a weak @@ -2760,15 +2781,15 @@ section. The keyword @code{__attribute__} allows you to specify special attributes of variables or structure fields. This keyword is followed -by an attribute specification inside double parentheses. Nine +by an attribute specification inside double parentheses. Ten attributes are currently defined for variables: @code{aligned}, @code{mode}, @code{nocommon}, @code{packed}, @code{section}, -@code{transparent_union}, @code{unused}, @code{vector_size}, and -@code{weak}. Some other attributes are defined for variables on -particular target systems. Other attributes are available for functions -(@pxref{Function Attributes}) and for types (@pxref{Type Attributes}). -Other front ends might define more attributes (@pxref{C++ -Extensions,,Extensions to the C++ Language}). +@code{transparent_union}, @code{unused}, @code{deprecated}, +@code{vector_size}, and @code{weak}. Some other attributes are defined +for variables on particular target systems. Other attributes are +available for functions (@pxref{Function Attributes}) and for types +(@pxref{Type Attributes}). Other front ends might define more +attributes (@pxref{C++ Extensions,,Extensions to the C++ Language}). You may also specify attributes with @samp{__} preceding and following each keyword. This allows you to use them in header files without @@ -2970,6 +2991,26 @@ This attribute, attached to a variable, means that the variable is meant to be possibly unused. GCC will not produce a warning for this variable. +@item deprecated +The @code{deprecated} attribute results in a warning if the variable +is used anywhere in the source file. This is useful when identifying +variables that are expected to be removed in a future version of a +program. The warning also includes the location of the declaration +of the deprecated variable, to enable users to easily find further +information about why the variable is deprecated, or what they should +do instead. Note that the warnings only occurs for uses: + +@smallexample +extern int old_var __attribute__ ((deprecated)); +extern int old_var; +int new_fn () @{ return old_var; @} +@end smallexample + +results in a warning on line 3 but not line 2. + +The @code{deprecated} attribute can also be used for functions and +types (@pxref{Function Attributes}, @pxref{Type Attributes}.) + @item vector_size (@var{bytes}) This attribute specifies the vector size for the variable, measured in bytes. For example, the declaration: @@ -3029,10 +3070,10 @@ packed))}. The keyword @code{__attribute__} allows you to specify special attributes of @code{struct} and @code{union} types when you define such types. This keyword is followed by an attribute specification inside -double parentheses. Four attributes are currently defined for types: -@code{aligned}, @code{packed}, @code{transparent_union}, and @code{unused}. -Other attributes are defined for functions (@pxref{Function Attributes}) and -for variables (@pxref{Variable Attributes}). +double parentheses. Five attributes are currently defined for types: +@code{aligned}, @code{packed}, @code{transparent_union}, @code{unused}, +and @code{deprecated}. Other attributes are defined for functions +(@pxref{Function Attributes}) and for variables (@pxref{Variable Attributes}). You may also specify any one of these attributes with @samp{__} preceding and following its keyword. This allows you to use these @@ -3215,6 +3256,34 @@ the case with lock or thread classes, which are usually defined and then not referenced, but contain constructors and destructors that have nontrivial bookkeeping functions. +@item deprecated +The @code{deprecated} attribute results in a warning if the type +is used anywhere in the source file. This is useful when identifying +types that are expected to be removed in a future version of a program. +If possible, the warning also includes the location of the declaration +of the deprecated type, to enable users to easily find further +information about why the type is deprecated, or what they should do +instead. Note that the warnings only occur for uses and then only +if the type is being applied to a identifier that itself is not being +declared as deprecated. + +@smallexample +typedef int T1 __attribute__ ((deprecated)); +T1 x; +typedef T1 T2; +T2 y; +typedef T1 T3 __attribute__ ((deprecated)); +T3 z __attribute__ ((deprecated)); +@end smallexample + +results in a warning on line 2 and 3 but not lines 4, 5, or 6. No +warning is issued for line 4 because T2 is not explicitly +deprecated. Line 5 has no warning because T3 is explicitly +deprecated. Similarly for line 6. + +The @code{deprecated} attribute can also be used for functions and +variables (@pxref{Function Attributes}, @pxref{Variable Attributes}.) + @end table To specify multiple attributes, separate them by commas within the diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index d5eaeefe9b5..9fac575ae78 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -213,7 +213,8 @@ in the following sections. -fsyntax-only -pedantic -pedantic-errors @gol -w -W -Wall -Waggregate-return @gol -Wcast-align -Wcast-qual -Wchar-subscripts -Wcomment @gol --Wconversion -Wdisabled-optimization -Wdiv-by-zero -Werror @gol +-Wconversion -Wno-deprecated-declarations @gol +-Wdisabled-optimization -Wdiv-by-zero -Werror @gol -Wfloat-equal -Wformat -Wformat=2 @gol -Wformat-nonliteral -Wformat-security @gol -Wimplicit -Wimplicit-int @gol @@ -2506,6 +2507,13 @@ case, and some functions for which @code{format} attributes are appropriate may not be detected. This option has no effect unless @option{-Wformat} is enabled (possibly by @option{-Wall}). +@item -Wno-deprecated-declarations +@opindex Wno-deprecated-declarations +Do not warn about uses of functions, variables, and types marked as +deprecated by using the @code{deprecated} attribute. +(@pxref{Function Attributes}, @pxref{Variable Attributes}, +@pxref{Type Attributes}.) + @item -Wpacked @opindex Wpacked Warn if a structure is given the packed attribute, but the packed diff --git a/gcc/flags.h b/gcc/flags.h index 49fdaa0aa35..65353e61677 100644 --- a/gcc/flags.h +++ b/gcc/flags.h @@ -169,6 +169,11 @@ extern int warn_padded; extern int warn_disabled_optimization; +/* Nonzero means warn about uses of __attribute__((deprecated)) + declarations. */ + +extern int warn_deprecated_decl; + /* Nonzero if generating code to do profiling. */ extern int profile_flag; diff --git a/gcc/print-tree.c b/gcc/print-tree.c index 4cef3f5e7a5..669c03e499d 100644 --- a/gcc/print-tree.c +++ b/gcc/print-tree.c @@ -294,6 +294,8 @@ print_node (file, prefix, node, indent) fputs (" protected", file); if (TREE_STATIC (node)) fputs (" static", file); + if (TREE_DEPRECATED (node)) + fputs (" deprecated", file); if (TREE_LANG_FLAG_0 (node)) fputs (" tree_0", file); if (TREE_LANG_FLAG_1 (node)) diff --git a/gcc/toplev.c b/gcc/toplev.c index da508a763f2..4d0e4b5c5ac 100644 --- a/gcc/toplev.c +++ b/gcc/toplev.c @@ -1464,6 +1464,11 @@ int warn_disabled_optimization; int warn_missing_noreturn; +/* Nonzero means warn about uses of __attribute__((deprecated)) + declarations. */ + +int warn_deprecated_decl = 1; + /* Likewise for -W. */ static const lang_independent_options W_options[] = @@ -1502,6 +1507,8 @@ static const lang_independent_options W_options[] = N_("Warn when padding is required to align struct members") }, {"disabled-optimization", &warn_disabled_optimization, 1, N_("Warn when an optimization pass is disabled") }, + {"deprecated-declarations", &warn_deprecated_decl, 1, + N_("Warn about uses of __attribute__((deprecated)) declarations") }, {"missing-noreturn", &warn_missing_noreturn, 1, N_("Warn about functions which might be candidates for attribute noreturn") } }; diff --git a/gcc/toplev.h b/gcc/toplev.h index 15cc264bbbd..41ccedc46d0 100644 --- a/gcc/toplev.h +++ b/gcc/toplev.h @@ -87,6 +87,7 @@ extern void error_for_asm PARAMS ((struct rtx_def *, const char *, ...)); extern void warning_for_asm PARAMS ((struct rtx_def *, const char *, ...)); +extern void warn_deprecated_use PARAMS ((union tree_node *)); extern int do_float_handler PARAMS ((void (*) (PTR), PTR)); #ifdef BUFSIZ diff --git a/gcc/tree.h b/gcc/tree.h index 642b5554389..adcb0f23621 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -139,6 +139,7 @@ struct tree_common unsigned private_flag : 1; unsigned protected_flag : 1; unsigned bounded_flag : 1; + unsigned deprecated_flag : 1; unsigned lang_flag_0 : 1; unsigned lang_flag_1 : 1; @@ -260,7 +261,13 @@ struct tree_common expressions, VAR_DECL, PARM_DECL, FIELD_DECL, FUNCTION_DECL, IDENTIFIER_NODE TYPE_BOUNDED in - ..._TYPE */ + ..._TYPE + + deprecated_flag: + + TREE_DEPRECATED in + ..._DECL +*/ /* Define accessors for the fields that all tree nodes have (though some fields are not used for all kinds of nodes). */ @@ -651,6 +658,10 @@ extern void tree_class_check_failed PARAMS ((const tree, int, #define TREE_BOUNDED(NODE) ((NODE)->common.bounded_flag) +/* Nonzero in a IDENTIFIER_NODE if the use of the name is defined as a + deprecated feature by __attribute__((deprecated)). */ +#define TREE_DEPRECATED(NODE) ((NODE)->common.deprecated_flag) + /* These flags are available for each language front end to use internally. */ #define TREE_LANG_FLAG_0(NODE) ((NODE)->common.lang_flag_0) #define TREE_LANG_FLAG_1(NODE) ((NODE)->common.lang_flag_1)