diff options
author | Iain Sandoe <iain@sandoe.co.uk> | 2020-11-08 09:04:07 +0000 |
---|---|---|
committer | Iain Sandoe <iain@sandoe.co.uk> | 2021-09-01 15:09:38 +0100 |
commit | 8433baadec88e5f31fa141b6d78094e91256079d (patch) | |
tree | bbe8d1332389ecdee6c6849b903c0aa5d12c978d /gcc/cp/decl.c | |
parent | 21b4d0ef543d68187d258415b51d0d6676af89fd (diff) | |
download | gcc-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/cp/decl.c')
-rw-r--r-- | gcc/cp/decl.c | 66 |
1 files changed, 59 insertions, 7 deletions
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index e981ead..146979b 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -2418,6 +2418,10 @@ duplicate_decls (tree newdecl, tree olddecl, bool hiding, bool was_hidden) if (TREE_DEPRECATED (newdecl)) TREE_DEPRECATED (olddecl) = 1; + /* Merge unavailability. */ + if (TREE_UNAVAILABLE (newdecl)) + TREE_UNAVAILABLE (olddecl) = 1; + /* Preserve function specific target and optimization options */ if (TREE_CODE (newdecl) == FUNCTION_DECL) { @@ -11757,20 +11761,24 @@ grokdeclarator (const cp_declarator *declarator, if (attrlist && *attrlist == error_mark_node) *attrlist = NULL_TREE; - /* An object declared as __attribute__((deprecated)) suppresses - warnings of uses of other deprecated items. */ + /* An object declared as __attribute__((unavailable)) suppresses + any reports of being declared with unavailable or deprecated + items. An object declared as __attribute__((deprecated)) + suppresses warnings of uses of other deprecated items. */ auto ds = make_temp_override (deprecated_state); - if (attrlist && lookup_attribute ("deprecated", *attrlist)) + if (attrlist && lookup_attribute ("unavailable", *attrlist)) + deprecated_state = UNAVAILABLE_DEPRECATED_SUPPRESS; + else if (attrlist && lookup_attribute ("deprecated", *attrlist)) deprecated_state = DEPRECATED_SUPPRESS; - cp_warn_deprecated_use (type); + cp_handle_deprecated_or_unavailable (type); if (type && TREE_CODE (type) == TYPE_DECL) { cp_warn_deprecated_use_scopes (CP_DECL_CONTEXT (type)); typedef_decl = type; type = TREE_TYPE (typedef_decl); if (DECL_ARTIFICIAL (typedef_decl)) - cp_warn_deprecated_use (type); + cp_handle_deprecated_or_unavailable (type); } /* No type at all: default to `int', and set DEFAULTED_INT because it was not a user-defined typedef. */ @@ -14417,6 +14425,43 @@ type_is_deprecated (tree type) return NULL_TREE; } +/* Returns an unavailable type used within TYPE, or NULL_TREE if none. */ + +static tree +type_is_unavailable (tree type) +{ + enum tree_code code; + if (TREE_UNAVAILABLE (type)) + return type; + if (TYPE_NAME (type)) + { + if (TREE_UNAVAILABLE (TYPE_NAME (type))) + return type; + else + { + cp_warn_deprecated_use_scopes (CP_DECL_CONTEXT (TYPE_NAME (type))); + return NULL_TREE; + } + } + + /* Do warn about using typedefs to a deprecated class. */ + if (OVERLOAD_TYPE_P (type) && type != TYPE_MAIN_VARIANT (type)) + return type_is_deprecated (TYPE_MAIN_VARIANT (type)); + + code = TREE_CODE (type); + + if (code == POINTER_TYPE || code == REFERENCE_TYPE + || code == OFFSET_TYPE || code == FUNCTION_TYPE + || code == METHOD_TYPE || code == ARRAY_TYPE) + return type_is_unavailable (TREE_TYPE (type)); + + if (TYPE_PTRMEMFUNC_P (type)) + return type_is_unavailable + (TREE_TYPE (TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (type)))); + + return NULL_TREE; +} + /* Decode the list of parameter types for a function type. Given the list of things declared inside the parens, return a list of types. @@ -14476,11 +14521,18 @@ grokparms (tree parmlist, tree *parms) if (type != error_mark_node) { - if (deprecated_state != DEPRECATED_SUPPRESS) + if (deprecated_state != UNAVAILABLE_DEPRECATED_SUPPRESS) + { + tree unavailtype = type_is_unavailable (type); + if (unavailtype) + cp_handle_deprecated_or_unavailable (unavailtype); + } + if (deprecated_state != DEPRECATED_SUPPRESS + && deprecated_state != UNAVAILABLE_DEPRECATED_SUPPRESS) { tree deptype = type_is_deprecated (type); if (deptype) - cp_warn_deprecated_use (deptype); + cp_handle_deprecated_or_unavailable (deptype); } /* [dcl.fct] "A parameter with volatile-qualified type is |