aboutsummaryrefslogtreecommitdiff
path: root/gcc/c
diff options
context:
space:
mode:
authorIain Sandoe <iain@sandoe.co.uk>2020-11-08 09:04:07 +0000
committerIain Sandoe <iain@sandoe.co.uk>2021-09-01 15:09:38 +0100
commit8433baadec88e5f31fa141b6d78094e91256079d (patch)
treebbe8d1332389ecdee6c6849b903c0aa5d12c978d /gcc/c
parent21b4d0ef543d68187d258415b51d0d6676af89fd (diff)
downloadgcc-8433baadec88e5f31fa141b6d78094e91256079d.zip
gcc-8433baadec88e5f31fa141b6d78094e91256079d.tar.gz
gcc-8433baadec88e5f31fa141b6d78094e91256079d.tar.bz2
C-family: Add attribute 'unavailable'.
If an interface is marked 'deprecated' then, presumably, at some point it will be withdrawn and no longer available. The 'unavailable' attribute makes it possible to mark up interfaces to indicate this status. It is used quite extensively in some codebases where a single set of headers can be used to permit code generation for multiple system versions. From a configuration perspective, it also allows a compile test to determine that an interface is missing - rather than requiring a link test. The implementation follows the pattern of attribute deprecated, but produces an error (where deprecation produces a warning). This attribute has been implemented in clang for some years. Signed-off-by: Iain Sandoe <iain@sandoe.co.uk> gcc/c-family/ChangeLog: * c-attribs.c (handle_unavailable_attribute): New. gcc/c/ChangeLog: * c-decl.c (enum deprecated_states): Add unavailable state. (merge_decls): Copy unavailability. (quals_from_declspecs): Handle unavailable case. (start_decl): Amend the logic handling suppression of nested deprecation states to include unavailability. (smallest_type_quals_location): Amend comment. (grokdeclarator): Handle the unavailable deprecation state. (declspecs_add_type): Set TREE_UNAVAILABLE from the decl specs. * c-tree.h (struct c_declspecs): Add unavailable_p. * c-typeck.c (build_component_ref): Handle unavailability. (build_external_ref): Likewise. gcc/cp/ChangeLog: * call.c (build_over_call): Handle unavailable state in addition to deprecation. * class.c (type_build_ctor_call): Likewise. (type_build_dtor_call): Likewise. * cp-tree.h: Rename cp_warn_deprecated_use to cp_handle_deprecated_or_unavailable. * decl.c (duplicate_decls): Merge unavailability. (grokdeclarator): Handle unavailability in addition to deprecation. (type_is_unavailable): New. (grokparms): Handle unavailability in addition to deprecation. * decl.h (enum deprecated_states): Add UNAVAILABLE_DEPRECATED_SUPPRESS. * decl2.c (cplus_decl_attributes): Propagate unavailability to templates. (cp_warn_deprecated_use): Rename to ... (cp_handle_deprecated_or_unavailable): ... this and amend to handle the unavailable case. It remains a warning in the case of deprecation but becomes an error in the case of unavailability. (cp_warn_deprecated_use_scopes): Handle unavailability. (mark_used): Likewise. * parser.c (cp_parser_template_name): Likewise. (cp_parser_template_argument): Likewise. (cp_parser_parameter_declaration_list): Likewise. * typeck.c (build_class_member_access_expr): Likewise. (finish_class_member_access_expr): Likewise. * typeck2.c (build_functional_cast_1): Likewise. gcc/ChangeLog: * doc/extend.texi: Document unavailable attribute. * print-tree.c (print_node): Handle unavailable attribute. * tree-core.h (struct tree_base): Add a bit to carry unavailability. * tree.c (error_unavailable_use): New. * tree.h (TREE_UNAVAILABLE): New. (error_unavailable_use): New. gcc/objc/ChangeLog: * objc-act.c (objc_add_property_declaration): Register unavailable attribute. (maybe_make_artificial_property_decl): Set available. (objc_maybe_build_component_ref): Generalise to the method prototype to count availability. (objc_build_class_component_ref): Likewise. (build_private_template): Likewise. (objc_decl_method_attributes): Handle unavailable attribute. (lookup_method_in_hash_lists): Amend comments. (objc_finish_message_expr): Handle unavailability in addition to deprecation. (start_class): Likewise. (finish_class): Likewise. (lookup_protocol): Likewise. (objc_declare_protocol): Likewise. (start_protocol): Register unavailable attribute. (really_start_method): Likewise. (objc_gimplify_property_ref): Emit error on encountering an unavailable entity (and a warning for a deprecated one). gcc/testsuite/ChangeLog: * g++.dg/ext/attr-unavailable-1.C: New test. * g++.dg/ext/attr-unavailable-2.C: New test. * g++.dg/ext/attr-unavailable-3.C: New test. * g++.dg/ext/attr-unavailable-4.C: New test. * g++.dg/ext/attr-unavailable-5.C: New test. * g++.dg/ext/attr-unavailable-6.C: New test. * g++.dg/ext/attr-unavailable-7.C: New test. * g++.dg/ext/attr-unavailable-8.C: New test. * g++.dg/ext/attr-unavailable-9.C: New test. * gcc.dg/attr-unavailable-1.c: New test. * gcc.dg/attr-unavailable-2.c: New test. * gcc.dg/attr-unavailable-3.c: New test. * gcc.dg/attr-unavailable-4.c: New test. * gcc.dg/attr-unavailable-5.c: New test. * gcc.dg/attr-unavailable-6.c: New test. * obj-c++.dg/attributes/method-unavailable-1.mm: New test. * obj-c++.dg/attributes/method-unavailable-2.mm: New test. * obj-c++.dg/attributes/method-unavailable-3.mm: New test. * obj-c++.dg/property/at-property-unavailable-1.mm: New test. * obj-c++.dg/property/at-property-unavailable-2.mm: New test. * obj-c++.dg/property/dotsyntax-unavailable-1.mm: New test. * objc.dg/attributes/method-unavailable-1.m: New test. * objc.dg/attributes/method-unavailable-2.m: New test. * objc.dg/attributes/method-unavailable-3.m: New test. * objc.dg/property/at-property-unavailable-1.m: New test. * objc.dg/property/at-property-unavailable-2.m: New test. * objc.dg/property/dotsyntax-unavailable-1.m: New test.
Diffstat (limited to 'gcc/c')
-rw-r--r--gcc/c/c-decl.c39
-rw-r--r--gcc/c/c-tree.h2
-rw-r--r--gcc/c/c-typeck.c8
3 files changed, 38 insertions, 11 deletions
diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c
index 3482d82..771efa3 100644
--- a/gcc/c/c-decl.c
+++ b/gcc/c/c-decl.c
@@ -73,13 +73,16 @@ enum decl_context
TYPENAME}; /* Typename (inside cast or sizeof) */
/* 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. */
+ with __attribute__((deprecated)) or __attribute__((unavailable)).
+ An object declared as __attribute__((unavailable)) should suppress
+ any reports of being declared with unavailable or deprecated items.
+ An object declared as __attribute__((deprecated)) should suppress
+ warnings of uses of other deprecated items. */
enum deprecated_states {
DEPRECATED_NORMAL,
- DEPRECATED_SUPPRESS
+ DEPRECATED_SUPPRESS,
+ UNAVAILABLE_DEPRECATED_SUPPRESS
};
@@ -2644,6 +2647,10 @@ merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype)
if (TREE_DEPRECATED (newdecl))
TREE_DEPRECATED (olddecl) = 1;
+ /* Merge unavailability. */
+ if (TREE_UNAVAILABLE (newdecl))
+ TREE_UNAVAILABLE (olddecl) = 1;
+
/* If a decl is in a system header and the other isn't, keep the one on the
system header. Otherwise, keep source location of definition rather than
declaration and of prototype rather than non-prototype unless that
@@ -4892,6 +4899,7 @@ quals_from_declspecs (const struct c_declspecs *specs)
&& !specs->typedef_p
&& !specs->explicit_signed_p
&& !specs->deprecated_p
+ && !specs->unavailable_p
&& !specs->long_p
&& !specs->long_long_p
&& !specs->short_p
@@ -5094,9 +5102,14 @@ start_decl (struct c_declarator *declarator, struct c_declspecs *declspecs,
tree expr = NULL_TREE;
enum deprecated_states deprecated_state = DEPRECATED_NORMAL;
- /* An object declared as __attribute__((deprecated)) suppresses
+ /* An object declared as __attribute__((unavailable)) suppresses
+ warnings and errors from __attribute__((deprecated/unavailable))
+ components.
+ An object declared as __attribute__((deprecated)) suppresses
warnings of uses of other deprecated items. */
- if (lookup_attribute ("deprecated", attributes))
+ if (lookup_attribute ("unavailable", attributes))
+ deprecated_state = UNAVAILABLE_DEPRECATED_SUPPRESS;
+ else if (lookup_attribute ("deprecated", attributes))
deprecated_state = DEPRECATED_SUPPRESS;
decl = grokdeclarator (declarator, declspecs,
@@ -6233,7 +6246,7 @@ smallest_type_quals_location (const location_t *locations,
set to indicate whether operands in *EXPR can be used in constant
expressions.
DEPRECATED_STATE is a deprecated_states value indicating whether
- deprecation warnings should be suppressed.
+ deprecation/unavailability warnings should be suppressed.
In the TYPENAME case, DECLARATOR is really an absolute declarator.
It may also be so in the PARM case, for a prototype where the
@@ -6363,8 +6376,14 @@ grokdeclarator (const struct c_declarator *declarator,
if (decl_context == NORMAL && !funcdef_flag && current_scope->parm_flag)
decl_context = PARM;
- if (declspecs->deprecated_p && deprecated_state != DEPRECATED_SUPPRESS)
- warn_deprecated_use (declspecs->type, declspecs->decl_attr);
+ if (deprecated_state != UNAVAILABLE_DEPRECATED_SUPPRESS)
+ {
+ if (declspecs->unavailable_p)
+ error_unavailable_use (declspecs->type, declspecs->decl_attr);
+ else if (declspecs->deprecated_p
+ && deprecated_state != DEPRECATED_SUPPRESS)
+ warn_deprecated_use (declspecs->type, declspecs->decl_attr);
+ }
if ((decl_context == NORMAL || decl_context == FIELD)
&& current_scope == file_scope
@@ -10814,6 +10833,8 @@ declspecs_add_type (location_t loc, struct c_declspecs *specs,
specs->typespec_kind = spec.kind;
if (TREE_DEPRECATED (type))
specs->deprecated_p = true;
+ if (TREE_UNAVAILABLE (type))
+ specs->unavailable_p = true;
/* Handle type specifier keywords. */
if (TREE_CODE (type) == IDENTIFIER_NODE
diff --git a/gcc/c/c-tree.h b/gcc/c/c-tree.h
index a8a90ea..d50d0cb 100644
--- a/gcc/c/c-tree.h
+++ b/gcc/c/c-tree.h
@@ -370,6 +370,8 @@ struct c_declspecs {
BOOL_BITFIELD explicit_signed_p : 1;
/* Whether the specifiers include a deprecated typedef. */
BOOL_BITFIELD deprecated_p : 1;
+ /* Whether the specifiers include an unavailable typedef. */
+ BOOL_BITFIELD unavailable_p : 1;
/* Whether the type defaulted to "int" because there were no type
specifiers. */
BOOL_BITFIELD default_int_p : 1;
diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c
index d9f26d6..5849c5a 100644
--- a/gcc/c/c-typeck.c
+++ b/gcc/c/c-typeck.c
@@ -2558,7 +2558,9 @@ build_component_ref (location_t loc, tree datum, tree component,
|| (use_datum_quals && TREE_THIS_VOLATILE (datum)))
TREE_THIS_VOLATILE (ref) = 1;
- if (TREE_DEPRECATED (subdatum))
+ if (TREE_UNAVAILABLE (subdatum))
+ error_unavailable_use (subdatum, NULL_TREE);
+ else if (TREE_DEPRECATED (subdatum))
warn_deprecated_use (subdatum, NULL_TREE);
datum = ref;
@@ -2843,7 +2845,9 @@ build_external_ref (location_t loc, tree id, bool fun, tree *type)
if (TREE_TYPE (ref) == error_mark_node)
return error_mark_node;
- if (TREE_DEPRECATED (ref))
+ if (TREE_UNAVAILABLE (ref))
+ error_unavailable_use (ref, NULL_TREE);
+ else if (TREE_DEPRECATED (ref))
warn_deprecated_use (ref, NULL_TREE);
/* Recursive call does not count as usage. */