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/testsuite/gcc.dg | |
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/testsuite/gcc.dg')
-rw-r--r-- | gcc/testsuite/gcc.dg/attr-unavailable-1.c | 88 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/attr-unavailable-2.c | 6 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/attr-unavailable-3.c | 10 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/attr-unavailable-4.c | 88 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/attr-unavailable-5.c | 6 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/attr-unavailable-6.c | 11 |
6 files changed, 209 insertions, 0 deletions
diff --git a/gcc/testsuite/gcc.dg/attr-unavailable-1.c b/gcc/testsuite/gcc.dg/attr-unavailable-1.c new file mode 100644 index 0000000..768214f --- /dev/null +++ b/gcc/testsuite/gcc.dg/attr-unavailable-1.c @@ -0,0 +1,88 @@ +/* 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__)); /* { dg-error "'INT2' is unavailable" "" } */ + +typedef enum {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 "'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 "'f1' is unavailable" "f1" } */ +} + +int func2(S1 *p) +{ + S1 lp; + + if (p->field1) + return p->field2; /* { dg-error "'field2' is unavailable" "" } */ + else if (lp.field4) /* { dg-error "'field4' is unavailable" "" } */ + return p->field3; + + p->u1.field5 = g1 + p->field7; + p->u2.field9; /* { dg-error "'u2' is unavailable" "" } */ + return p->u1.field6 + p->field8; /* { dg-error "'field6' is unavailable" "" } */ + /* { dg-error "'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" "" } */ diff --git a/gcc/testsuite/gcc.dg/attr-unavailable-2.c b/gcc/testsuite/gcc.dg/attr-unavailable-2.c new file mode 100644 index 0000000..303f973 --- /dev/null +++ b/gcc/testsuite/gcc.dg/attr-unavailable-2.c @@ -0,0 +1,6 @@ +/* Test __attribute__((unavailable)). Test types without names. */ +/* { dg-do compile } */ +/* { dg-options "" } */ + +struct { int a; } __attribute__((unavailable)) x; /* { dg-error "type is unavailable" } */ +typeof(x) y; /* { dg-error "type is unavailable" } */ diff --git a/gcc/testsuite/gcc.dg/attr-unavailable-3.c b/gcc/testsuite/gcc.dg/attr-unavailable-3.c new file mode 100644 index 0000000..7274c19 --- /dev/null +++ b/gcc/testsuite/gcc.dg/attr-unavailable-3.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 "'func' is unavailable" } */ +} diff --git a/gcc/testsuite/gcc.dg/attr-unavailable-4.c b/gcc/testsuite/gcc.dg/attr-unavailable-4.c new file mode 100644 index 0000000..9e39c50 --- /dev/null +++ b/gcc/testsuite/gcc.dg/attr-unavailable-4.c @@ -0,0 +1,88 @@ +/* Test __attribute__ ((unavailable("message"))) */ +/* { 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" "" } */ +typedef INT1 INT1b __attribute__ ((unavailable("You can't use INT1b"))); + +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: You can't use INT2" "" } */ +int f6(INT2 x) __attribute__ ((__unavailable__("You can't use f6"))); /* { dg-error "'INT2' is unavailable: You can't use INT2" "" } */ + +typedef enum {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("Avoid x"))); + int y __attribute__ ((__unavailable__("Bad y"))); + int z; + int (*pf)() = f1; /* { dg-error "'f1' is unavailable: You can't use f1" "" } */ + + z = w + x + y + g1 + g2 + g3; /* { dg-error "'x' is unavailable: Avoid x" "" } */ + /* { dg-error "'y' is unavailable: Bad 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 "'f1' is unavailable: You can't use f1" "" } */ +} + +int func2(S1 *p) +{ + S1 lp; + + if (p->field1) + return p->field2; /* { dg-error "'field2' is unavailable: You can't use field2" "" } */ + else if (lp.field4) /* { dg-error "'field4' is unavailable: You can't use field4" "" } */ + return p->field3; + + p->u1.field5 = g1 + p->field7; + p->u2.field9; /* { dg-error "'u2' is unavailable: You can't use u2" "" } */ + return p->u1.field6 + p->field8; /* { dg-error "'field6' is unavailable: You can't use field6" "" } */ + /* { dg-error "'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" "" } */ diff --git a/gcc/testsuite/gcc.dg/attr-unavailable-5.c b/gcc/testsuite/gcc.dg/attr-unavailable-5.c new file mode 100644 index 0000000..051f960 --- /dev/null +++ b/gcc/testsuite/gcc.dg/attr-unavailable-5.c @@ -0,0 +1,6 @@ +/* Test __attribute__((unavailable)). Test types without names. */ +/* { dg-do compile } */ +/* { dg-options "" } */ + +struct { int a; } __attribute__((unavailable ("Do not use"))) x; /* { dg-error "type is unavailable" } */ +typeof(x) y; /* { dg-error "type is unavailable: Do not use" } */ diff --git a/gcc/testsuite/gcc.dg/attr-unavailable-6.c b/gcc/testsuite/gcc.dg/attr-unavailable-6.c new file mode 100644 index 0000000..f5f4560 --- /dev/null +++ b/gcc/testsuite/gcc.dg/attr-unavailable-6.c @@ -0,0 +1,11 @@ +/* Test __attribute__((unavailable)). Test merging with multiple + declarations. */ +/* { dg-do compile } */ +/* { dg-options "" } */ + +void func(void); +void func(void) __attribute__((unavailable ("Do not use"))); + +void f(void) { + func(); /* { dg-error "'func' is unavailable: Do not use" } */ +} |