From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mx2.suse.de (mx2.suse.de [195.135.220.15]) by sourceware.org (Postfix) with ESMTPS id E3F8F386102F for ; Tue, 10 Nov 2020 11:58:48 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org E3F8F386102F Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=suse.de Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=rguenther@suse.de X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.221.27]) by mx2.suse.de (Postfix) with ESMTP id B7BD9ABCC; Tue, 10 Nov 2020 11:58:47 +0000 (UTC) Date: Tue, 10 Nov 2020 12:58:47 +0100 (CET) From: Richard Biener Sender: rguenther@c653.arch.suse.de To: Iain Sandoe cc: GCC-patches@gcc.gnu.org, Jason Merrill , Joseph Myers Subject: Re: [PATCH] C-family : Add attribute 'unavailable'. In-Reply-To: <8F49B2BF-2BFA-45EB-B780-75F76AD271E0@sandoe.co.uk> Message-ID: References: <8F49B2BF-2BFA-45EB-B780-75F76AD271E0@sandoe.co.uk> User-Agent: Alpine 2.21 (LSU 202 2017-01-01) MIME-Version: 1.0 Content-Type: text/plain; charset=US-ASCII X-Spam-Status: No, score=-11.2 required=5.0 tests=BAYES_00, GIT_PATCH_0, KAM_DMARC_STATUS, RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 10 Nov 2020 11:58:56 -0000 On Tue, 10 Nov 2020, Iain Sandoe wrote: > Hi Richard, > > Richard Biener wrote: > > >On Mon, 9 Nov 2020, Iain Sandoe wrote: > > > >>Hi, > >> > >>I?ve been carrying this patch around on my Darwin branches for a very long > >>time? > >> > >>tested across the Darwin patch and on x86_64-linux-gnu, > >>OK for master? > >>thanks > >>Iain > >> > >>===== commit message > >> > >>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. > >> > >>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: > >> > >>* lto-streamer-out.c (hash_tree): Stream TREE_UNAVAILABLE. > >>* 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. > > > >Why'd you need to stream this in LTO, more specifically only handle > >it in hashing? It should be all frontend operation. > > I followed the existing implementation for TREE_DEPRECATED (). > > Presumably, that entry should also be removed - I will remove and re-test (it > wasn?t > obvious to me why the entry was present, the deprecation/unavailable stuff > should > be done by end of gimplification). deprecated_flag is overloaded, we likely use this accessor because it isn't guarded by any tree code check. We definitely need the bit for SSA_NAMEs. > >You're targeting only DECLs can you use a bit from decl_common where decl > >specific bits exist instead? > > .. except that we are also targeting types. Ah, I see, using a bit in tree-base is fine then. Please document its use in near to the other flags like deprecated_flag: TREE_DEPRECATED in all decls all types so overloads can be added for other tree kinds. Richard. > We could use a bit in decl_common for decls and in tree_type_common for types, > I suppose, but that would then mean that every test for unavailable would grow > an > additional check to discriminate. > > (if we do that, then presumably, as a separate patch, we might as well move > TREE_DEPRECATED in the same way - since otherwise the impl. is different for > no obvious reason). > > thanks > Iain > > > > > >Thanks, > >Richard. > > > >>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. > >>--- > >>gcc/c-family/c-attribs.c | 69 +++++++++++ > >>gcc/c/c-decl.c | 39 ++++-- > >>gcc/c/c-tree.h | 2 + > >>gcc/c/c-typeck.c | 8 +- > >>gcc/cp/call.c | 4 +- > >>gcc/cp/class.c | 2 + > >>gcc/cp/cp-tree.h | 2 +- > >>gcc/cp/decl.c | 66 ++++++++-- > >>gcc/cp/decl.h | 3 +- > >>gcc/cp/decl2.c | 58 +++++++-- > >>gcc/cp/parser.c | 32 +++-- > >>gcc/cp/typeck.c | 9 +- > >>gcc/cp/typeck2.c | 2 +- > >>gcc/lto-streamer-out.c | 1 + > >>gcc/objc/objc-act.c | 81 +++++++++---- > >>gcc/print-tree.c | 2 + > >>gcc/testsuite/g++.dg/ext/attr-unavailable-1.C | 113 ++++++++++++++++++ > >>gcc/testsuite/g++.dg/ext/attr-unavailable-2.C | 10 ++ > >>gcc/testsuite/g++.dg/ext/attr-unavailable-3.C | 14 +++ > >>gcc/testsuite/g++.dg/ext/attr-unavailable-4.C | 11 ++ > >>gcc/testsuite/g++.dg/ext/attr-unavailable-5.C | 6 + > >>gcc/testsuite/g++.dg/ext/attr-unavailable-6.C | 110 +++++++++++++++++ > >>gcc/testsuite/g++.dg/ext/attr-unavailable-7.C | 19 +++ > >>gcc/testsuite/g++.dg/ext/attr-unavailable-8.C | 17 +++ > >>gcc/testsuite/g++.dg/ext/attr-unavailable-9.C | 17 +++ > >>gcc/testsuite/gcc.dg/attr-unavailable-1.c | 88 ++++++++++++++ > >>gcc/testsuite/gcc.dg/attr-unavailable-2.c | 6 + > >>gcc/testsuite/gcc.dg/attr-unavailable-3.c | 10 ++ > >>gcc/testsuite/gcc.dg/attr-unavailable-4.c | 88 ++++++++++++++ > >>gcc/testsuite/gcc.dg/attr-unavailable-5.c | 6 + > >>gcc/testsuite/gcc.dg/attr-unavailable-6.c | 11 ++ > >>.../attributes/method-unavailable-1.mm | 34 ++++++ > >>.../attributes/method-unavailable-2.mm | 24 ++++ > >>.../attributes/method-unavailable-3.mm | 22 ++++ > >>.../property/at-property-unavailable-1.mm | 38 ++++++ > >>.../property/at-property-unavailable-2.mm | 26 ++++ > >>.../property/dotsyntax-unavailable-1.mm | 42 +++++++ > >>.../objc.dg/attributes/method-unavailable-1.m | 34 ++++++ > >>.../objc.dg/attributes/method-unavailable-2.m | 24 ++++ > >>.../objc.dg/attributes/method-unavailable-3.m | 22 ++++ > >>.../property/at-property-unavailable-1.m | 38 ++++++ > >>.../property/at-property-unavailable-2.m | 26 ++++ > >>.../property/dotsyntax-unavailable-1.m | 42 +++++++ > >>gcc/tree-core.h | 10 +- > >>gcc/tree.c | 72 +++++++++++ > >>gcc/tree.h | 6 + > >>46 files changed, 1302 insertions(+), 64 deletions(-) > >>create mode 100644 gcc/testsuite/g++.dg/ext/attr-unavailable-1.C > >>create mode 100644 gcc/testsuite/g++.dg/ext/attr-unavailable-2.C > >>create mode 100644 gcc/testsuite/g++.dg/ext/attr-unavailable-3.C > >>create mode 100644 gcc/testsuite/g++.dg/ext/attr-unavailable-4.C > >>create mode 100644 gcc/testsuite/g++.dg/ext/attr-unavailable-5.C > >>create mode 100644 gcc/testsuite/g++.dg/ext/attr-unavailable-6.C > >>create mode 100644 gcc/testsuite/g++.dg/ext/attr-unavailable-7.C > >>create mode 100644 gcc/testsuite/g++.dg/ext/attr-unavailable-8.C > >>create mode 100644 gcc/testsuite/g++.dg/ext/attr-unavailable-9.C > >>create mode 100644 gcc/testsuite/gcc.dg/attr-unavailable-1.c > >>create mode 100644 gcc/testsuite/gcc.dg/attr-unavailable-2.c > >>create mode 100644 gcc/testsuite/gcc.dg/attr-unavailable-3.c > >>create mode 100644 gcc/testsuite/gcc.dg/attr-unavailable-4.c > >>create mode 100644 gcc/testsuite/gcc.dg/attr-unavailable-5.c > >>create mode 100644 gcc/testsuite/gcc.dg/attr-unavailable-6.c > >>create mode 100644 > >>gcc/testsuite/obj-c++.dg/attributes/method-unavailable-1.mm > >>create mode 100644 > >>gcc/testsuite/obj-c++.dg/attributes/method-unavailable-2.mm > >>create mode 100644 > >>gcc/testsuite/obj-c++.dg/attributes/method-unavailable-3.mm > >>create mode 100644 > >>gcc/testsuite/obj-c++.dg/property/at-property-unavailable-1.mm > >>create mode 100644 > >>gcc/testsuite/obj-c++.dg/property/at-property-unavailable-2.mm > >>create mode 100644 > >>gcc/testsuite/obj-c++.dg/property/dotsyntax-unavailable-1.mm > >>create mode 100644 gcc/testsuite/objc.dg/attributes/method-unavailable-1.m > >>create mode 100644 gcc/testsuite/objc.dg/attributes/method-unavailable-2.m > >>create mode 100644 gcc/testsuite/objc.dg/attributes/method-unavailable-3.m > >>create mode 100644 > >>gcc/testsuite/objc.dg/property/at-property-unavailable-1.m > >>create mode 100644 > >>gcc/testsuite/objc.dg/property/at-property-unavailable-2.m > >>create mode 100644 gcc/testsuite/objc.dg/property/dotsyntax-unavailable-1.m > >> > >>diff --git a/gcc/c-family/c-attribs.c b/gcc/c-family/c-attribs.c > >>index f1680820ecd..067dfabe0a4 100644 > >>--- a/gcc/c-family/c-attribs.c > >>+++ b/gcc/c-family/c-attribs.c > >>@@ -120,6 +120,8 @@ static tree handle_pure_attribute (tree *, tree, tree, > >>int, bool *); > >>static tree handle_tm_attribute (tree *, tree, tree, int, bool *); > >>static tree handle_tm_wrap_attribute (tree *, tree, tree, int, bool *); > >>static tree handle_novops_attribute (tree *, tree, tree, int, bool *); > >>+static tree handle_unavailable_attribute (tree *, tree, tree, int, > >>+ bool *); > >>static tree handle_vector_size_attribute (tree *, tree, tree, int, > >>bool *) ATTRIBUTE_NONNULL(3); > >>static tree handle_nonnull_attribute (tree *, tree, tree, int, bool *); > >>@@ -391,6 +393,8 @@ const struct attribute_spec c_common_attribute_table[] = > >>handle_novops_attribute, NULL }, > >>{ "deprecated", 0, 1, false, false, false, false, > >>handle_deprecated_attribute, NULL }, > >>+ { "unavailable", 0, 1, false, false, false, false, > >>+ handle_unavailable_attribute, NULL }, > >>{ "vector_size", 1, 1, false, true, false, true, > >>handle_vector_size_attribute, NULL }, > >>{ "visibility", 1, 1, false, false, false, false, > >>@@ -3737,6 +3741,71 @@ handle_deprecated_attribute (tree *node, tree name, > >>return NULL_TREE; > >>} > >> > >>+/* Handle a "unavailable" attribute; arguments as in > >>+ struct attribute_spec.handler. */ > >>+ > >>+static tree > >>+handle_unavailable_attribute (tree *node, tree name, > >>+ tree args, int flags, > >>+ bool *no_add_attrs) > >>+{ > >>+ tree type = NULL_TREE; > >>+ int warn = 0; > >>+ tree what = NULL_TREE; > >>+ > >>+ if (!args) > >>+ *no_add_attrs = true; > >>+ else if (TREE_CODE (TREE_VALUE (args)) != STRING_CST) > >>+ { > >>+ error ("the message attached to % is not a string"); > >>+ *no_add_attrs = true; > >>+ } > >>+ > >>+ if (DECL_P (*node)) > >>+ { > >>+ tree decl = *node; > >>+ type = TREE_TYPE (decl); > >>+ > >>+ if (TREE_CODE (decl) == TYPE_DECL > >>+ || TREE_CODE (decl) == PARM_DECL > >>+ || VAR_OR_FUNCTION_DECL_P (decl) > >>+ || TREE_CODE (decl) == FIELD_DECL > >>+ || TREE_CODE (decl) == CONST_DECL > >>+ || objc_method_decl (TREE_CODE (decl))) > >>+ TREE_UNAVAILABLE (decl) = 1; > >>+ else > >>+ warn = 1; > >>+ } > >>+ else if (TYPE_P (*node)) > >>+ { > >>+ if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE)) > >>+ *node = build_variant_type_copy (*node); > >>+ TREE_UNAVAILABLE (*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 = TYPE_NAME (*node); > >>+ else if (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL > >>+ && DECL_NAME (TYPE_NAME (type))) > >>+ what = DECL_NAME (TYPE_NAME (type)); > >>+ } > >>+ if (what) > >>+ warning (OPT_Wattributes, "%qE attribute ignored for %qE", name, what); > >>+ else > >>+ warning (OPT_Wattributes, "%qE attribute ignored", name); > >>+ } > >>+ > >>+ return NULL_TREE; > >>+} > >>+ > >>/* Return the "base" type from TYPE that is suitable to apply attribute > >>vector_size to by stripping arrays, function types, etc. */ > >>static tree > >>diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c > >>index f19c82c81dd..27c6f13e8f2 100644 > >>--- a/gcc/c/c-decl.c > >>+++ b/gcc/c/c-decl.c > >>@@ -70,13 +70,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 > >>}; > >> > >> > >>@@ -2630,6 +2633,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 > >>@@ -4868,6 +4875,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 > >>@@ -5070,9 +5078,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, > >>@@ -6190,7 +6203,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 > >>@@ -6320,8 +6333,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 > >>@@ -10753,6 +10772,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 1f783db7dbc..292874cc317 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 96840377d90..16b6f776214 100644 > >>--- a/gcc/c/c-typeck.c > >>+++ b/gcc/c/c-typeck.c > >>@@ -2504,7 +2504,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; > >>@@ -2789,7 +2791,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. */ > >>diff --git a/gcc/cp/call.c b/gcc/cp/call.c > >>index 9861be1f856..3df6c48e237 100644 > >>--- a/gcc/cp/call.c > >>+++ b/gcc/cp/call.c > >>@@ -9078,7 +9078,7 @@ build_over_call (struct z_candidate *cand, int flags, > >>tsubst_flags_t complain) > >>already_used = true; > >>} > >>else > >>- cp_warn_deprecated_use (fn, complain); > >>+ cp_handle_deprecated_or_unavailable (fn, complain); > >> > >>/* If we're creating a temp and we already have one, don't create a > >>new one. If we're not creating a temp but we get one, use > >>@@ -9148,7 +9148,7 @@ build_over_call (struct z_candidate *cand, int flags, > >>tsubst_flags_t complain) > >>TREE_NO_WARNING (val) = 1; > >>} > >> > >>- cp_warn_deprecated_use (fn, complain); > >>+ cp_handle_deprecated_or_unavailable (fn, complain); > >> > >>return val; > >>} > >>diff --git a/gcc/cp/class.c b/gcc/cp/class.c > >>index c03737294eb..f594d473325 100644 > >>--- a/gcc/cp/class.c > >>+++ b/gcc/cp/class.c > >>@@ -5678,6 +5678,7 @@ type_build_ctor_call (tree t) > >>tree fn = *iter; > >>if (!DECL_ARTIFICIAL (fn) > >>|| TREE_DEPRECATED (fn) > >>+ || TREE_UNAVAILABLE (fn) > >>|| DECL_DELETED_FN (fn)) > >>return true; > >>} > >>@@ -5706,6 +5707,7 @@ type_build_dtor_call (tree t) > >>tree fn = *iter; > >>if (!DECL_ARTIFICIAL (fn) > >>|| TREE_DEPRECATED (fn) > >>+ || TREE_UNAVAILABLE (fn) > >>|| DECL_DELETED_FN (fn)) > >>return true; > >>} > >>diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h > >>index 052291c40fe..7912cf511ed 100644 > >>--- a/gcc/cp/cp-tree.h > >>+++ b/gcc/cp/cp-tree.h > >>@@ -6303,7 +6303,7 @@ extern bool is_list_ctor (tree); > >>extern void validate_conversion_obstack (void); > >>extern void mark_versions_used (tree); > >>extern bool unsafe_return_slot_p (tree); > >>-extern bool cp_warn_deprecated_use (tree, tsubst_flags_t = > >>tf_warning_or_error); > >>+extern bool cp_handle_deprecated_or_unavailable (tree, tsubst_flags_t = > >>tf_warning_or_error); > >>extern void cp_warn_deprecated_use_scopes (tree); > >>extern tree get_function_version_dispatcher (tree); > >> > >>diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c > >>index 62648841ac3..bdd290f6d02 100644 > >>--- a/gcc/cp/decl.c > >>+++ b/gcc/cp/decl.c > >>@@ -2350,6 +2350,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) > >>{ > >>@@ -11398,20 +11402,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. */ > >>temp_override ds (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. */ > >>@@ -14027,6 +14035,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. > >>@@ -14086,11 +14131,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 > >>diff --git a/gcc/cp/decl.h b/gcc/cp/decl.h > >>index 3252dd8a011..475a00d8a2f 100644 > >>--- a/gcc/cp/decl.h > >>+++ b/gcc/cp/decl.h > >>@@ -44,7 +44,8 @@ extern void name_unnamed_type (tree, tree); > >> > >>enum deprecated_states { > >>DEPRECATED_NORMAL, > >>- DEPRECATED_SUPPRESS > >>+ DEPRECATED_SUPPRESS, > >>+ UNAVAILABLE_DEPRECATED_SUPPRESS > >>}; > >> > >>extern enum deprecated_states deprecated_state; > >>diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c > >>index 1bc7b7e0197..590f8a3c157 100644 > >>--- a/gcc/cp/decl2.c > >>+++ b/gcc/cp/decl2.c > >>@@ -1608,6 +1608,17 @@ cplus_decl_attributes (tree *decl, tree attributes, > >>int flags) > >>if (*decl == pattern) > >>TREE_DEPRECATED (tmpl) = true; > >>} > >>+ > >>+ /* Likewise, propagate unavailability out to the template. */ > >>+ if (TREE_UNAVAILABLE (*decl)) > >>+ if (tree ti = get_template_info (*decl)) > >>+ { > >>+ tree tmpl = TI_TEMPLATE (ti); > >>+ tree pattern = (TYPE_P (*decl) ? TREE_TYPE (tmpl) > >>+ : DECL_TEMPLATE_RESULT (tmpl)); > >>+ if (*decl == pattern) > >>+ TREE_UNAVAILABLE (tmpl) = true; > >>+ } > >>} > >> > >>/* Walks through the namespace- or function-scope anonymous union > >>@@ -5389,14 +5400,47 @@ maybe_instantiate_decl (tree decl) > >>} > >>} > >> > >>-/* Maybe warn if DECL is deprecated, subject to COMPLAIN. Returns whether > >>or > >>- not a warning was emitted. */ > >>+/* Error if the DECL is unavailable (unless this is currently suppressed). > >>+ Maybe warn if DECL is deprecated, subject to COMPLAIN. Returns true if > >>+ an error or warning was emitted. */ > >> > >>bool > >>-cp_warn_deprecated_use (tree decl, tsubst_flags_t complain) > >>+cp_handle_deprecated_or_unavailable (tree decl, tsubst_flags_t complain) > >>{ > >>- if (!(complain & tf_warning) || !decl > >>- || deprecated_state == DEPRECATED_SUPPRESS) > >>+ if (!decl) > >>+ return false; > >>+ > >>+ if ((complain & tf_error) > >>+ && deprecated_state != UNAVAILABLE_DEPRECATED_SUPPRESS) > >>+ { > >>+ if (TREE_UNAVAILABLE (decl)) > >>+ { > >>+ error_unavailable_use (decl, NULL_TREE); > >>+ return true; > >>+ } > >>+ else > >>+ { > >>+ /* Perhaps this is an unavailable typedef. */ > >>+ if (TYPE_P (decl) > >>+ && TYPE_NAME (decl) > >>+ && TREE_UNAVAILABLE (TYPE_NAME (decl))) > >>+ { > >>+ decl = TYPE_NAME (decl); > >>+ /* Don't error within members of a unavailable type. */ > >>+ if (TYPE_P (decl) > >>+ && currently_open_class (decl)) > >>+ return false; > >>+ > >>+ error_unavailable_use (decl, NULL_TREE); > >>+ return true; > >>+ } > >>+ } > >>+ /* Carry on to consider deprecatedness. */ > >>+ } > >>+ > >>+ if (!(complain & tf_warning) > >>+ || deprecated_state == DEPRECATED_SUPPRESS > >>+ || deprecated_state == UNAVAILABLE_DEPRECATED_SUPPRESS) > >>return false; > >> > >>if (!TREE_DEPRECATED (decl)) > >>@@ -5455,7 +5499,7 @@ cp_warn_deprecated_use_scopes (tree scope) > >>&& scope != error_mark_node > >>&& scope != global_namespace) > >>{ > >>- if (cp_warn_deprecated_use (scope)) > >>+ if (cp_handle_deprecated_or_unavailable (scope)) > >>return; > >>if (TYPE_P (scope)) > >>scope = CP_TYPE_CONTEXT (scope); > >>@@ -5567,7 +5611,7 @@ mark_used (tree decl, tsubst_flags_t complain) > >>TREE_USED (decl) = true; > >>} > >> > >>- cp_warn_deprecated_use (decl, complain); > >>+ cp_handle_deprecated_or_unavailable (decl, complain); > >> > >>/* We can only check DECL_ODR_USED on variables or functions with > >>DECL_LANG_SPECIFIC set, and these are also the only decls that we > >>diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c > >>index 323d7424a83..00595c0365b 100644 > >>--- a/gcc/cp/parser.c > >>+++ b/gcc/cp/parser.c > >>@@ -17170,18 +17170,26 @@ cp_parser_template_name (cp_parser* parser, > >>/* If DECL is a template, then the name was a template-name. */ > >>if (TREE_CODE (decl) == TEMPLATE_DECL) > >>{ > >>- if (TREE_DEPRECATED (decl) > >>- && deprecated_state != DEPRECATED_SUPPRESS) > >>+ if ((TREE_DEPRECATED (decl) || TREE_UNAVAILABLE (decl)) > >>+ && deprecated_state != UNAVAILABLE_DEPRECATED_SUPPRESS) > >>{ > >>tree d = DECL_TEMPLATE_RESULT (decl); > >>tree attr; > >>if (TREE_CODE (d) == TYPE_DECL) > >>- attr = lookup_attribute ("deprecated", > >>- TYPE_ATTRIBUTES (TREE_TYPE (d))); > >>+ attr = TYPE_ATTRIBUTES (TREE_TYPE (d)); > >>else > >>- attr = lookup_attribute ("deprecated", > >>- DECL_ATTRIBUTES (d)); > >>- warn_deprecated_use (decl, attr); > >>+ attr = DECL_ATTRIBUTES (d); > >>+ if (TREE_UNAVAILABLE (decl)) > >>+ { > >>+ attr = lookup_attribute ("unavailable", attr); > >>+ error_unavailable_use (decl, attr); > >>+ } > >>+ else if (TREE_DEPRECATED (decl) > >>+ && deprecated_state != DEPRECATED_SUPPRESS) > >>+ { > >>+ attr = lookup_attribute ("deprecated", attr); > >>+ warn_deprecated_use (decl, attr); > >>+ } > >>} > >>} > >>else > >>@@ -17432,7 +17440,9 @@ cp_parser_template_argument (cp_parser* parser) > >>} > >>if (cp_parser_parse_definitely (parser)) > >>{ > >>- if (TREE_DEPRECATED (argument)) > >>+ if (TREE_UNAVAILABLE (argument)) > >>+ error_unavailable_use (argument, NULL_TREE); > >>+ else if (TREE_DEPRECATED (argument)) > >>warn_deprecated_use (argument, NULL_TREE); > >>return argument; > >>} > >>@@ -22930,9 +22940,9 @@ cp_parser_parameter_declaration_list (cp_parser* > >>parser, cp_parser_flags flags) > >>/*template_parm_p=*/false, > >>&parenthesized_p); > >> > >>- /* We don't know yet if the enclosing context is deprecated, so wait > >>- and warn in grokparms if appropriate. */ > >>- deprecated_state = DEPRECATED_SUPPRESS; > >>+ /* We don't know yet if the enclosing context is unavailable or > >>deprecated, > >>+ so wait and deal with it in grokparms if appropriate. */ > >>+ deprecated_state = UNAVAILABLE_DEPRECATED_SUPPRESS; > >> > >>if (parameter) > >>{ > >>diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c > >>index 08e0c80f9b0..7d1e2fd27a6 100644 > >>--- a/gcc/cp/typeck.c > >>+++ b/gcc/cp/typeck.c > >>@@ -2514,7 +2514,10 @@ build_class_member_access_expr (cp_expr object, tree > >>member, > >>member_scope = DECL_CLASS_CONTEXT (member); > >>if (!mark_used (member, complain) && !(complain & tf_error)) > >>return error_mark_node; > >>- if (TREE_DEPRECATED (member)) > >>+ > >>+ if (TREE_UNAVAILABLE (member)) > >>+ error_unavailable_use (member, NULL_TREE); > >>+ else if (TREE_DEPRECATED (member)) > >>warn_deprecated_use (member, NULL_TREE); > >>} > >>else > >>@@ -3217,7 +3220,9 @@ finish_class_member_access_expr (cp_expr object, tree > >>name, bool template_p, > >>} > >>} > >> > >>- if (TREE_DEPRECATED (member)) > >>+ if (TREE_UNAVAILABLE (member)) > >>+ error_unavailable_use (member, NULL_TREE); > >>+ else if (TREE_DEPRECATED (member)) > >>warn_deprecated_use (member, NULL_TREE); > >> > >>if (template_p) > >>diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c > >>index 445e2a211c8..4d014dac88f 100644 > >>--- a/gcc/cp/typeck2.c > >>+++ b/gcc/cp/typeck2.c > >>@@ -2293,7 +2293,7 @@ build_functional_cast_1 (location_t loc, tree exp, > >>tree parms, > >>type = TREE_TYPE (exp); > >> > >>if (DECL_ARTIFICIAL (exp)) > >>- cp_warn_deprecated_use (type); > >>+ cp_handle_deprecated_or_unavailable (type); > >>} > >>else > >>type = exp; > >>diff --git a/gcc/lto-streamer-out.c b/gcc/lto-streamer-out.c > >>index 0ca2796da9c..2c164daf3b4 100644 > >>--- a/gcc/lto-streamer-out.c > >>+++ b/gcc/lto-streamer-out.c > >>@@ -1212,6 +1212,7 @@ hash_tree (struct streamer_tree_cache_d *cache, > >>hash_map *map, > >>hstate.add_flag (TREE_STATIC (t)); > >>hstate.add_flag (TREE_PROTECTED (t)); > >>hstate.add_flag (TREE_DEPRECATED (t)); > >>+ hstate.add_flag (TREE_UNAVAILABLE (t)); > >>if (code != TREE_BINFO) > >>hstate.add_flag (TREE_PRIVATE (t)); > >>if (TYPE_P (t)) > >>diff --git a/gcc/objc/objc-act.c b/gcc/objc/objc-act.c > >>index b9ed32d51d0..fc247220a62 100644 > >>--- a/gcc/objc/objc-act.c > >>+++ b/gcc/objc/objc-act.c > >>@@ -1275,6 +1275,7 @@ objc_add_property_declaration (location_t location, > >>tree decl, > >>TREE_TYPE (property_decl) = TREE_TYPE (decl); > >>DECL_SOURCE_LOCATION (property_decl) = DECL_SOURCE_LOCATION (decl); > >>TREE_DEPRECATED (property_decl) = TREE_DEPRECATED (decl); > >>+ TREE_UNAVAILABLE (property_decl) = TREE_UNAVAILABLE (decl); > >> > >>/* Add property-specific information. */ > >>PROPERTY_NAME (property_decl) = DECL_NAME (decl); > >>@@ -1390,6 +1391,7 @@ maybe_make_artificial_property_decl (tree interface, > >>tree implementation, > >>TREE_TYPE (property_decl) = type; > >>DECL_SOURCE_LOCATION (property_decl) = input_location; > >>TREE_DEPRECATED (property_decl) = 0; > >>+ TREE_UNAVAILABLE (property_decl) = 0; > >>DECL_ARTIFICIAL (property_decl) = 1; > >> > >>/* Add property-specific information. Note that one of > >>@@ -1668,7 +1670,7 @@ objc_maybe_build_component_ref (tree object, tree > >>property_ident) > >>{ > >>tree expression; > >>tree getter_call; > >>- tree deprecated_method_prototype = NULL_TREE; > >>+ tree method_prototype_avail = NULL_TREE; > >> > >>/* We have an additional nasty problem here; if this > >>PROPERTY_REF needs to become a 'getter', then the conversion > >>@@ -1702,10 +1704,10 @@ objc_maybe_build_component_ref (tree object, tree > >>property_ident) > >>is deprecated, but record the fact that the getter is > >>deprecated by setting PROPERTY_REF_DEPRECATED_GETTER to > >>the method prototype. */ > >>- &deprecated_method_prototype); > >>+ &method_prototype_avail); > >> > >>expression = build4 (PROPERTY_REF, TREE_TYPE(x), object, x, getter_call, > >>- deprecated_method_prototype); > >>+ method_prototype_avail); > >>SET_EXPR_LOCATION (expression, input_location); > >>TREE_SIDE_EFFECTS (expression) = 1; > >> > >>@@ -1755,7 +1757,9 @@ objc_build_class_component_ref (tree class_name, tree > >>property_ident) > >>} > >>else > >>{ > >>- if (TREE_DEPRECATED (rtype)) > >>+ if (TREE_UNAVAILABLE (rtype)) > >>+ error ("class %qE is unavailable", class_name); > >>+ else if (TREE_DEPRECATED (rtype)) > >>warning (OPT_Wdeprecated_declarations, "class %qE is deprecated", > >>class_name); > >>} > >> > >>@@ -1767,17 +1771,17 @@ objc_build_class_component_ref (tree class_name, > >>tree property_ident) > >>{ > >>tree expression; > >>tree getter_call; > >>- tree deprecated_method_prototype = NULL_TREE; > >>+ tree method_prototype_avail = NULL_TREE; > >> > >>if (PROPERTY_HAS_NO_GETTER (x)) > >>getter_call = NULL_TREE; > >>else > >>getter_call = objc_finish_message_expr > >>(object, PROPERTY_GETTER_NAME (x), NULL_TREE, > >>- &deprecated_method_prototype); > >>+ &method_prototype_avail); > >> > >>expression = build4 (PROPERTY_REF, TREE_TYPE(x), object, x, getter_call, > >>- deprecated_method_prototype); > >>+ method_prototype_avail); > >>SET_EXPR_LOCATION (expression, input_location); > >>TREE_SIDE_EFFECTS (expression) = 1; > >> > >>@@ -4548,6 +4552,8 @@ build_private_template (tree klass) > >>/* Copy the attributes from the class to the type. */ > >>if (TREE_DEPRECATED (klass)) > >>TREE_DEPRECATED (record) = 1; > >>+ if (TREE_UNAVAILABLE (klass)) > >>+ TREE_UNAVAILABLE (record) = 1; > >>} > >>} > >> > >>@@ -4973,6 +4979,7 @@ objc_decl_method_attributes (tree *node, tree > >>attributes, int flags) > >>tree name = TREE_PURPOSE (attribute); > >> > >>if (is_attribute_p ("deprecated", name) > >>+ || is_attribute_p ("unavailable", name) > >>|| is_attribute_p ("sentinel", name) > >>|| is_attribute_p ("noreturn", name)) > >>{ > >>@@ -5438,9 +5445,9 @@ lookup_method_in_hash_lists (tree sel_name, int > >>is_class) > >>C++ template functions, it is called from 'build_expr_from_tree' > >>(in decl2.c) after RECEIVER and METHOD_PARAMS have been expanded. > >> > >>- If the DEPRECATED_METHOD_PROTOTYPE argument is NULL, then we warn > >>+ If the method_prototype_avail argument is NULL, then we warn > >>if the method being used is deprecated. If it is not NULL, instead > >>- of deprecating, we set *DEPRECATED_METHOD_PROTOTYPE to the method > >>+ of deprecating, we set *method_prototype_avail to the method > >>prototype that was used and is deprecated. This is useful for > >>getter calls that are always generated when compiling dot-syntax > >>expressions, even if they may not be used. In that case, we don't > >>@@ -5449,7 +5456,7 @@ lookup_method_in_hash_lists (tree sel_name, int > >>is_class) > >>used. */ > >>tree > >>objc_finish_message_expr (tree receiver, tree sel_name, tree method_params, > >>- tree *deprecated_method_prototype) > >>+ tree *method_prototype_avail) > >>{ > >>tree method_prototype = NULL_TREE, rprotos = NULL_TREE, rtype; > >>tree retval, class_tree; > >>@@ -5761,10 +5768,17 @@ objc_finish_message_expr (tree receiver, tree > >>sel_name, tree method_params, > >>In practice this makes sense since casting an object to 'id' > >>is often used precisely to turn off warnings associated with > >>the object being of a particular class. */ > >>- if (TREE_DEPRECATED (method_prototype) && rtype != NULL_TREE) > >>+ if (TREE_UNAVAILABLE (method_prototype) && rtype != NULL_TREE) > >>{ > >>- if (deprecated_method_prototype) > >>- *deprecated_method_prototype = method_prototype; > >>+ if (method_prototype_avail) > >>+ *method_prototype_avail = method_prototype; > >>+ else > >>+ error_unavailable_use (method_prototype, NULL_TREE); > >>+ } > >>+ else if (TREE_DEPRECATED (method_prototype) && rtype != NULL_TREE) > >>+ { > >>+ if (method_prototype_avail) > >>+ *method_prototype_avail = method_prototype; > >>else > >>warn_deprecated_use (method_prototype, NULL_TREE); > >>} > >>@@ -6936,7 +6950,9 @@ start_class (enum tree_code code, tree class_name, > >>tree super_name, > >>} > >>else > >>{ > >>- if (TREE_DEPRECATED (super_interface)) > >>+ if (TREE_UNAVAILABLE (super_interface)) > >>+ error ("class %qE is not available", super); > >>+ else if (TREE_DEPRECATED (super_interface)) > >>warning (OPT_Wdeprecated_declarations, "class %qE is deprecated", > >>super); > >>super_name = super; > >>@@ -7040,7 +7056,9 @@ start_class (enum tree_code code, tree class_name, > >>tree super_name, > >>/* TODO: Document what the objc_exception attribute is/does. */ > >>/* We handle the 'deprecated', 'visibility' and (undocumented) > >>'objc_exception' attributes. */ > >>- if (is_attribute_p ("deprecated", name)) > >>+ if (is_attribute_p ("unavailable", name)) > >>+ TREE_UNAVAILABLE (klass) = 1; > >>+ else if (is_attribute_p ("deprecated", name)) > >>TREE_DEPRECATED (klass) = 1; > >>else if (is_attribute_p ("objc_exception", name)) > >>CLASS_HAS_EXCEPTION_ATTR (klass) = 1; > >>@@ -7069,7 +7087,9 @@ start_class (enum tree_code code, tree class_name, > >>tree super_name, > >>} > >>else > >>{ > >>- if (TREE_DEPRECATED (class_category_is_assoc_with)) > >>+ if (TREE_UNAVAILABLE (class_category_is_assoc_with)) > >>+ error ("class %qE is unavailable", class_name); > >>+ else if (TREE_DEPRECATED (class_category_is_assoc_with)) > >>warning (OPT_Wdeprecated_declarations, "class %qE is deprecated", > >>class_name); > >> > >>@@ -8096,6 +8116,7 @@ finish_class (tree klass) > >>else > >>objc_add_method (objc_interface_context, getter_decl, false, false); > >>TREE_DEPRECATED (getter_decl) = TREE_DEPRECATED (x); > >>+ TREE_UNAVAILABLE (getter_decl) = TREE_UNAVAILABLE (x); > >>METHOD_PROPERTY_CONTEXT (getter_decl) = x; > >>} > >> > >>@@ -8140,6 +8161,7 @@ finish_class (tree klass) > >>else > >>objc_add_method (objc_interface_context, setter_decl, false, false); > >>TREE_DEPRECATED (setter_decl) = TREE_DEPRECATED (x); > >>+ TREE_UNAVAILABLE (setter_decl) = TREE_UNAVAILABLE (x); > >>METHOD_PROPERTY_CONTEXT (setter_decl) = x; > >>} > >>} > >>@@ -8193,7 +8215,9 @@ lookup_protocol (tree ident, bool warn_if_deprecated, > >>bool definition_required) > >>for (chain = protocol_chain; chain; chain = TREE_CHAIN (chain)) > >>if (ident == PROTOCOL_NAME (chain)) > >>{ > >>- if (warn_if_deprecated && TREE_DEPRECATED (chain)) > >>+ if (TREE_UNAVAILABLE (chain)) > >>+ error ("protocol %qE is unavailable", PROTOCOL_NAME (chain)); > >>+ else if (warn_if_deprecated && TREE_DEPRECATED (chain)) > >>{ > >>/* It would be nice to use warn_deprecated_use() here, but > >>we are using TREE_CHAIN (which is supposed to be the > >>@@ -8218,6 +8242,7 @@ void > >>objc_declare_protocol (tree name, tree attributes) > >>{ > >>bool deprecated = false; > >>+ bool unavailable = false; > >> > >>#ifdef OBJCPLUS > >>if (current_namespace != global_namespace) { > >>@@ -8236,6 +8261,8 @@ objc_declare_protocol (tree name, tree attributes) > >> > >>if (is_attribute_p ("deprecated", name)) > >>deprecated = true; > >>+ else if (is_attribute_p ("unavailable", name)) > >>+ unavailable = true; > >>else > >>warning (OPT_Wattributes, "%qE attribute directive ignored", name); > >>} > >>@@ -8260,6 +8287,8 @@ objc_declare_protocol (tree name, tree attributes) > >>TYPE_ATTRIBUTES (protocol) = attributes; > >>if (deprecated) > >>TREE_DEPRECATED (protocol) = 1; > >>+ if (unavailable) > >>+ TREE_UNAVAILABLE (protocol) = 1; > >>} > >>} > >>} > >>@@ -8269,6 +8298,7 @@ start_protocol (enum tree_code code, tree name, tree > >>list, tree attributes) > >>{ > >>tree protocol; > >>bool deprecated = false; > >>+ bool unavailable = false; > >> > >>#ifdef OBJCPLUS > >>if (current_namespace != global_namespace) { > >>@@ -8287,6 +8317,8 @@ start_protocol (enum tree_code code, tree name, tree > >>list, tree attributes) > >> > >>if (is_attribute_p ("deprecated", name)) > >>deprecated = true; > >>+ else if (is_attribute_p ("unavailable", name)) > >>+ unavailable = true; > >>else > >>warning (OPT_Wattributes, "%qE attribute directive ignored", name); > >>} > >>@@ -8326,6 +8358,8 @@ start_protocol (enum tree_code code, tree name, tree > >>list, tree attributes) > >>TYPE_ATTRIBUTES (protocol) = attributes; > >>if (deprecated) > >>TREE_DEPRECATED (protocol) = 1; > >>+ if (unavailable) > >>+ TREE_UNAVAILABLE (protocol) = 1; > >>} > >> > >>return protocol; > >>@@ -8855,6 +8889,8 @@ really_start_method (tree method, > >>warnings are produced), but just in case. */ > >>if (TREE_DEPRECATED (proto)) > >>TREE_DEPRECATED (method) = 1; > >>+ if (TREE_UNAVAILABLE (proto)) > >>+ TREE_UNAVAILABLE (method) = 1; > >> > >>/* If the method in the @interface was marked as > >>'noreturn', mark the function implementing the method > >>@@ -9586,12 +9622,17 @@ objc_gimplify_property_ref (tree *expr_p) > >>return; > >>} > >> > >>+ /* FIXME, this should be a label indicating availability in general. */ > >>if (PROPERTY_REF_DEPRECATED_GETTER (*expr_p)) > >>{ > >>- /* PROPERTY_REF_DEPRECATED_GETTER contains the method prototype > >>+ if (TREE_UNAVAILABLE (PROPERTY_REF_DEPRECATED_GETTER (*expr_p))) > >>+ error_unavailable_use (PROPERTY_REF_DEPRECATED_GETTER (*expr_p), > >>+ NULL_TREE); > >>+ else > >>+ /* PROPERTY_REF_DEPRECATED_GETTER contains the method prototype > >>that is deprecated. */ > >>- warn_deprecated_use (PROPERTY_REF_DEPRECATED_GETTER (*expr_p), > >>- NULL_TREE); > >>+ warn_deprecated_use (PROPERTY_REF_DEPRECATED_GETTER (*expr_p), > >>+ NULL_TREE); > >>} > >> > >>call_exp = getter; > >>diff --git a/gcc/print-tree.c b/gcc/print-tree.c > >>index 17c88f81770..1443d3f5c39 100644 > >>--- a/gcc/print-tree.c > >>+++ b/gcc/print-tree.c > >>@@ -364,6 +364,8 @@ print_node (FILE *file, const char *prefix, tree node, > >>int indent, > >>fputs (code == CALL_EXPR ? " must-tail-call" : " static", file); > >>if (TREE_DEPRECATED (node)) > >>fputs (" deprecated", file); > >>+ if (TREE_UNAVAILABLE (node)) > >>+ fputs (" unavailable", file); > >>if (TREE_VISITED (node)) > >>fputs (" visited", file); > >> > >>diff --git a/gcc/testsuite/g++.dg/ext/attr-unavailable-1.C > >>b/gcc/testsuite/g++.dg/ext/attr-unavailable-1.C > >>new file mode 100644 > >>index 00000000000..862651f6cbf > >>--- /dev/null > >>+++ b/gcc/testsuite/g++.dg/ext/attr-unavailable-1.C > >>@@ -0,0 +1,113 @@ > >>+/* Test __attribute__ ((unavailable)) */ > >>+/* { dg-do compile } */ > >>+/* { dg-options "" } */ > >>+ > >>+typedef int INT1 __attribute__((unavailable)); > >>+typedef INT1 INT2 __attribute__ ((__unavailable__)); > >>+ > >>+typedef INT1 INT1a; /* { dg-error "'INT1' is unavailable" "" } */ > >>+typedef INT1 INT1b __attribute__ ((unavailable)); > >>+ > >>+INT1 should_be_unavailable; /* { dg-error "'INT1' is unavailable" "" } */ > >>+INT1a should_not_be_unavailable; > >>+ > >>+INT1 f1(void) __attribute__ ((unavailable)); > >>+INT1 f2(void) { return 0; } /* { dg-error "'INT1' is unavailable" "" } */ > >>+ > >>+INT2 f3(void) __attribute__ ((__unavailable__)); > >>+INT2 f4(void) { return 0; } /* { dg-error "'INT2' is unavailable" "" } */ > >>+int f5(INT2 x); /* { dg-error "'INT2' is unavailable" "" } */ > >>+int f6(INT2 x) __attribute__ ((__unavailable__)); > >>+ > >>+typedef enum Color {red, green, blue} Color __attribute__((unavailable)); > >>+ > >>+int g1; > >>+int g2 __attribute__ ((unavailable)); > >>+int g3 __attribute__ ((__unavailable__)); > >>+Color k; /* { dg-error "'Color' is unavailable" "" } */ > >>+ > >>+typedef struct { > >>+ int field1; > >>+ int field2 __attribute__ ((unavailable)); > >>+ int field3; > >>+ int field4 __attribute__ ((__unavailable__)); > >>+ union { > >>+ int field5; > >>+ int field6 __attribute__ ((unavailable)); > >>+ } u1; > >>+ int field7:1; > >>+ int field8:1 __attribute__ ((unavailable)); > >>+ union { > >>+ int field9; > >>+ int field10; > >>+ } u2 __attribute__ ((unavailable)); > >>+} S1; > >>+ > >>+int func1() > >>+{ > >>+ INT1 w; /* { dg-error "'INT1' is unavailable" "" } */ > >>+ int x __attribute__ ((unavailable)); > >>+ int y __attribute__ ((__unavailable__)); > >>+ int z; > >>+ int (*pf)() = f1; /* { dg-error "'INT1 f1\\(\\)' is unavailable" "" } */ > >>+ > >>+ z = w + x + y + g1 + g2 + g3; /* { dg-error "'x' is unavailable" "" } */ > >>+ /* { dg-error "'y' is unavailable" "y" { target *-*-* } .-1 } */ > >>+ /* { dg-error "'g2' is unavailable" "g2" { target *-*-* } .-2 } */ > >>+ /* { dg-error "'g3' is unavailable" "g3" { target *-*-* } .-3 } */ > >>+ return f1(); /* { dg-error "'INT1 f1\\(\\)' is unavailable" "f1" } */ > >>+} > >>+ > >>+int func2(S1 *p) > >>+{ > >>+ S1 lp; > >>+ > >>+ if (p->field1) > >>+ return p->field2; /* { dg-error "'S1::field2' is unavailable" "" } */ > >>+ else if (lp.field4) /* { dg-error "'S1::field4' is unavailable" "" } */ > >>+ return p->field3; > >>+ > >>+ p->u1.field5 = g1 + p->field7; > >>+ p->u2.field9; /* { dg-error "'S1::u2' is unavailable" "" } */ > >>+ return p->u1.field6 + p->field8; /* { dg-error "'S1:: >>union>::field6' is unavailable" "" } */ > >>+ /* { dg-error "'S1::field8' is unavailable" "field8" { target *-*-* } .-1 > >>} */ > >>+} > >>+ > >>+struct SS1 { > >>+ int x; > >>+ INT1 y; /* { dg-error "'INT1' is unavailable" "" } */ > >>+} __attribute__ ((unavailable)); > >>+ > >>+struct SS1 *p1; /* { dg-error "'SS1' is unavailable" "" } */ > >>+ > >>+struct __attribute__ ((__unavailable__)) SS2 { > >>+ int x; > >>+ INT1 y; /* { dg-error "'INT1' is unavailable" "" } */ > >>+}; > >>+ > >>+struct SS2 *p2; /* { dg-error "'SS2' is unavailable" "" } */ > >>+ > >>+#ifdef __cplusplus > >>+class T { > >>+ public: > >>+ void member1(int) __attribute__ ((unavailable)); > >>+ void member2(INT1) __attribute__ ((__unavailable__)); > >>+ int member3(T *); > >>+ int x; > >>+} __attribute__ ((unavailable)); > >>+ > >>+T *p3; // { dg-error "'T' is unavailable" } > >>+ > >>+inline void T::member1(int) {} > >>+ > >>+int T::member3(T *p) // { dg-error "'T' is unavailable" } > >>+{ > >>+ p->member1(1); /* { dg-error "'void T::member1\\(int\\)' is unavailable" > >>"" } */ > >>+ (*p).member1(2); /* { dg-error "'void T::member1\\(int\\)' is unavailable" > >>"" } */ > >>+ p->member2(1); /* { dg-error "'void T::member2\\(INT1\\)' is unavailable" > >>"" } */ > >>+ (*p).member2(2); /* { dg-error "'void T::member2\\(INT1\\)' is > >>unavailable" "" } */ > >>+ p->member3(p); > >>+ (*p).member3(p); > >>+ return f1(); /* { dg-error "'INT1 f1\\(\\)' is unavailable" "" } */ > >>+} > >>+#endif > >>diff --git a/gcc/testsuite/g++.dg/ext/attr-unavailable-2.C > >>b/gcc/testsuite/g++.dg/ext/attr-unavailable-2.C > >>new file mode 100644 > >>index 00000000000..3de5532817e > >>--- /dev/null > >>+++ b/gcc/testsuite/g++.dg/ext/attr-unavailable-2.C > >>@@ -0,0 +1,10 @@ > >>+/* Test __attribute__ ((unavailable)) */ > >>+/* { dg-do compile } */ > >>+/* { dg-options "" } */ > >>+ > >>+void func(void); > >>+void func(void) __attribute__((unavailable)); > >>+ > >>+void f(void) { > >>+ func(); /* { dg-error "'void func\\(\\)' is unavailable" } */ > >>+} > >>diff --git a/gcc/testsuite/g++.dg/ext/attr-unavailable-3.C > >>b/gcc/testsuite/g++.dg/ext/attr-unavailable-3.C > >>new file mode 100644 > >>index 00000000000..1f267ea78c4 > >>--- /dev/null > >>+++ b/gcc/testsuite/g++.dg/ext/attr-unavailable-3.C > >>@@ -0,0 +1,14 @@ > >>+/* Check operator with __attribute__((unavailable)) */ > >>+/* { dg-do compile } */ > >>+/* { dg-options "" } */ > >>+ > >>+struct Foo > >>+{ > >>+ operator int() __attribute__((unavailable)); > >>+}; > >>+ > >>+void g(void) > >>+{ > >>+ Foo f; > >>+ (int)f; // { dg-error "'Foo::operator int\\(\\)' is unavailable" } > >>+} > >>diff --git a/gcc/testsuite/g++.dg/ext/attr-unavailable-4.C > >>b/gcc/testsuite/g++.dg/ext/attr-unavailable-4.C > >>new file mode 100644 > >>index 00000000000..b7f352ee3bd > >>--- /dev/null > >>+++ b/gcc/testsuite/g++.dg/ext/attr-unavailable-4.C > >>@@ -0,0 +1,11 @@ > >>+/* Test __attribute__ ((unavailable)) */ > >>+/* { dg-do compile } */ > >>+/* { dg-options "" } */ > >>+ > >>+struct B { > >>+ virtual int foo() __attribute__((unavailable)); > >>+}; > >>+ > >>+int main(void) { > >>+ ((B*)0)->foo(); // { dg-error "unavailable" } > >>+} > >>diff --git a/gcc/testsuite/g++.dg/ext/attr-unavailable-5.C > >>b/gcc/testsuite/g++.dg/ext/attr-unavailable-5.C > >>new file mode 100644 > >>index 00000000000..3beea5d22c5 > >>--- /dev/null > >>+++ b/gcc/testsuite/g++.dg/ext/attr-unavailable-5.C > >>@@ -0,0 +1,6 @@ > >>+/* Test __attribute__ ((unavailable)) */ > >>+/* { dg-do compile } */ > >>+/* { dg-options "" } */ > >>+ > >>+struct Foo { int i; } __attribute__ ((unavailable)); > >>+void foo() { Foo f; } // { dg-error "unavailable" } > >>diff --git a/gcc/testsuite/g++.dg/ext/attr-unavailable-6.C > >>b/gcc/testsuite/g++.dg/ext/attr-unavailable-6.C > >>new file mode 100644 > >>index 00000000000..8a57ea0d88c > >>--- /dev/null > >>+++ b/gcc/testsuite/g++.dg/ext/attr-unavailable-6.C > >>@@ -0,0 +1,110 @@ > >>+/* Test __attribute__ ((unavailable)) */ > >>+/* { dg-do compile } */ > >>+/* { dg-options "" } */ > >>+ > >>+typedef int INT1 __attribute__((unavailable("You can't use INT1"))); > >>+typedef INT1 INT2 __attribute__ ((__unavailable__("You can't use INT2"))); > >>+ > >>+typedef INT1 INT1a; /* { dg-error "'INT1' is unavailable: You can't use > >>INT1" "" } */ > >>+ > >>+INT1 should_be_unavailable; /* { dg-error "'INT1' is unavailable: You can't > >>use INT1" "" } */ > >>+INT1a should_not_be_unavailable; > >>+ > >>+INT1 f1(void) __attribute__ ((unavailable("You can't use f1"))); > >>+INT1 f2(void) { return 0; } /* { dg-error "'INT1' is unavailable: You can't > >>use INT1" "" } */ > >>+ > >>+INT2 f3(void) __attribute__ ((__unavailable__("You can't use f3"))); > >>+INT2 f4(void) { return 0; } /* { dg-error "'INT2' is unavailable: You can't > >>use INT2" "" } */ > >>+int f5(INT2 x); /* { dg-error "'INT2' is unavailable" "" } */ > >>+int f6(INT2 x) __attribute__ ((__unavailable__("You can't use f6"))); > >>+ > >>+typedef enum Color {red, green, blue} Color __attribute__((unavailable("You > >>can't use Color"))); > >>+ > >>+int g1; > >>+int g2 __attribute__ ((unavailable("You can't use g2"))); > >>+int g3 __attribute__ ((__unavailable__("You can't use g3"))); > >>+Color k; /* { dg-error "'Color' is unavailable: You can't use Color" "" } > >>*/ > >>+ > >>+typedef struct { > >>+ int field1; > >>+ int field2 __attribute__ ((unavailable("You can't use field2"))); > >>+ int field3; > >>+ int field4 __attribute__ ((__unavailable__("You can't use field4"))); > >>+ union { > >>+ int field5; > >>+ int field6 __attribute__ ((unavailable("You can't use field6"))); > >>+ } u1; > >>+ int field7:1; > >>+ int field8:1 __attribute__ ((unavailable("You can't use field8"))); > >>+ union { > >>+ int field9; > >>+ int field10; > >>+ } u2 __attribute__ ((unavailable("You can't use u2"))); > >>+} S1; > >>+ > >>+int func1() > >>+{ > >>+ INT1 w; /* { dg-error "'INT1' is unavailable: You can't use INT1" "" } */ > >>+ int x __attribute__ ((unavailable("You can't use x"))); > >>+ int y __attribute__ ((__unavailable__("You can't use y"))); > >>+ int z; > >>+ int (*pf)() = f1; /* { dg-error "'INT1 f1\\(\\)' is unavailable: You can't > >>use f1" "" } */ > >>+ > >>+ z = w + x + y + g1 + g2 + g3; /* { dg-error "'x' is unavailable: You can't > >>use x" "" } */ > >>+ /* { dg-error "'y' is unavailable: You can't use y" "y" { target *-*-* } > >>.-1 } */ > >>+ /* { dg-error "'g2' is unavailable: You can't use g2" "g2" { target *-*-* > >>} .-2 } */ > >>+ /* { dg-error "'g3' is unavailable: You can't use g3" "g3" { target *-*-* > >>} .-3 } */ > >>+ return f1(); /* { dg-error "'INT1 f1\\(\\)' is unavailable: You can't use > >>f1" "f1" } */ > >>+} > >>+ > >>+int func2(S1 *p) > >>+{ > >>+ S1 lp; > >>+ > >>+ if (p->field1) > >>+ return p->field2; /* { dg-error "'S1::field2' is unavailable: You can't > >>use field2" "" } */ > >>+ else if (lp.field4) /* { dg-error "'S1::field4' is unavailable: You can't > >>use field4" "" } */ > >>+ return p->field3; > >>+ > >>+ p->u1.field5 = g1 + p->field7; > >>+ p->u2.field9; /* { dg-error "'S1::u2' is unavailable: You can't use u2" "" > >>} */ > >>+ return p->u1.field6 + p->field8; /* { dg-error "'S1:: >>union>::field6' is unavailable: You can't use field6" "" } */ > >>+ /* { dg-error "'S1::field8' is unavailable: You can't use field8" "field8" > >>{ target *-*-* } .-1 } */ > >>+} > >>+ > >>+struct SS1 { > >>+ int x; > >>+ INT1 y; /* { dg-error "'INT1' is unavailable: You can't use INT1" "" } */ > >>+} __attribute__ ((unavailable("You can't use SS1"))); > >>+ > >>+struct SS1 *p1; /* { dg-error "'SS1' is unavailable: You can't use SS1" "" > >>} */ > >>+ > >>+struct __attribute__ ((__unavailable__("You can't use SS2"))) SS2 { > >>+ int x; > >>+ INT1 y; /* { dg-error "'INT1' is unavailable: You can't use INT1" "" } */ > >>+}; > >>+ > >>+struct SS2 *p2; /* { dg-error "'SS2' is unavailable: You can't use SS2" "" > >>} */ > >>+ > >>+class T { > >>+ public: > >>+ void member1(int) __attribute__ ((unavailable("You can't use member1"))); > >>+ void member2(INT1) __attribute__ ((__unavailable__("You can't use > >>member2"))); > >>+ int member3(T *); > >>+ int x; > >>+} __attribute__ ((unavailable("You can't use T"))); > >>+ > >>+T *p3; // { dg-error "'T' is unavailable: You can't use T" } > >>+ > >>+inline void T::member1(int) {} > >>+ > >>+int T::member3(T *p) // { dg-error "'T' is unavailable: You can't use T" } > >>+{ > >>+ p->member1(1); /* { dg-error "'void T::member1\\(int\\)' is unavailable: > >>You can't use member1" "" } */ > >>+ (*p).member1(2); /* { dg-error "'void T::member1\\(int\\)' is unavailable: > >>You can't use member1" "" } */ > >>+ p->member2(1); /* { dg-error "'void T::member2\\(INT1\\)' is unavailable: > >>You can't use member2" "" } */ > >>+ (*p).member2(2); /* { dg-error "'void T::member2\\(INT1\\)' is > >>unavailable: You can't use member2" "" } */ > >>+ p->member3(p); > >>+ (*p).member3(p); > >>+ return f1(); /* { dg-error "'INT1 f1\\(\\)' is unavailable: You can't use > >>f1" "" } */ > >>+} > >>diff --git a/gcc/testsuite/g++.dg/ext/attr-unavailable-7.C > >>b/gcc/testsuite/g++.dg/ext/attr-unavailable-7.C > >>new file mode 100644 > >>index 00000000000..c061aa3b6a2 > >>--- /dev/null > >>+++ b/gcc/testsuite/g++.dg/ext/attr-unavailable-7.C > >>@@ -0,0 +1,19 @@ > >>+/* Test __attribute__ ((unavailable)) */ > >>+/* { dg-do compile } */ > >>+/* { dg-options "" } */ > >>+ > >>+int g_nn; > >>+int& g_n __attribute__((unavailable)) = g_nn; > >>+ > >>+void f() > >>+{ > >>+ int f_nn; > >>+ int& f_n __attribute__((unavailable)) = f_nn; > >>+ f_n = 1; // { dg-error "'f_n' is unavailable" } > >>+} > >>+ > >>+int main() > >>+{ > >>+ g_n = 1; // { dg-error "'g_n' is unavailable" } > >>+ f(); > >>+} > >>diff --git a/gcc/testsuite/g++.dg/ext/attr-unavailable-8.C > >>b/gcc/testsuite/g++.dg/ext/attr-unavailable-8.C > >>new file mode 100644 > >>index 00000000000..334a2cf7286 > >>--- /dev/null > >>+++ b/gcc/testsuite/g++.dg/ext/attr-unavailable-8.C > >>@@ -0,0 +1,17 @@ > >>+/* Test __attribute__ ((unavailable)) */ > >>+/* { dg-do compile } */ > >>+/* { dg-options "" } */ > >>+ > >>+class ToBeunavailable { > >>+} __attribute__ ((unavailable ("unavailable!"))); > >>+ > >>+typedef ToBeunavailable NotToBeunavailable; // { dg-error > >>"'ToBeunavailable' is unavailable" } > >>+ > >>+int main() { > >>+ > >>+ ToBeunavailable(); // { dg-error "'ToBeunavailable' is unavailable" } > >>+ ToBeunavailable x; // { dg-error "'ToBeunavailable' is unavailable" } > >>+ > >>+ NotToBeunavailable(); > >>+ NotToBeunavailable y; > >>+} > >>diff --git a/gcc/testsuite/g++.dg/ext/attr-unavailable-9.C > >>b/gcc/testsuite/g++.dg/ext/attr-unavailable-9.C > >>new file mode 100644 > >>index 00000000000..44161336e78 > >>--- /dev/null > >>+++ b/gcc/testsuite/g++.dg/ext/attr-unavailable-9.C > >>@@ -0,0 +1,17 @@ > >>+/* Test __attribute__ ((unavailable)) */ > >>+/* { dg-do compile } */ > >>+/* { dg-options "" } */ > >>+ > >>+template struct __attribute__ ((unavailable)) S {}; > >>+S s; > >>+ > >>+template