From b642fca1c31b2e2175e0860daf32b4ee0d918085 Mon Sep 17 00:00:00 2001 From: Iain Sandoe Date: Wed, 4 Nov 2020 23:52:12 +0000 Subject: [PATCH] Objective-C/C++ : Handle parsing @property 'class' attribute. This attribute states that a property is one manipulated by class methods (it requires a static variable and the setter and getter must be provided explicitly, they cannot be @synthesized). gcc/c-family/ChangeLog: * c-common.h (OBJC_IS_PATTR_KEYWORD): Add class to the list of keywords accepted in @property attribute contexts. * c-objc.h (enum objc_property_attribute_group): Add OBJC_PROPATTR_GROUP_CLASS. (enum objc_property_attribute_kind): Add OBJC_PROPERTY_ATTR_CLASS. gcc/cp/ChangeLog: * parser.c (cp_parser_objc_at_property_declaration): Handle class keywords in @property attribute context. gcc/objc/ChangeLog: * objc-act.c (objc_prop_attr_kind_for_rid): Handle class attribute. (objc_add_property_declaration): Likewise. * objc-act.h (PROPERTY_CLASS): Record class attribute state. gcc/testsuite/ChangeLog: * obj-c++.dg/property/at-property-4.mm: Test handling class attributes. * objc.dg/property/at-property-4.m: Likewise. --- gcc/c-family/c-common.h | 6 +++-- gcc/c-family/c-objc.h | 2 ++ gcc/cp/parser.c | 4 +++ gcc/objc/objc-act.c | 10 +++++++ gcc/objc/objc-act.h | 4 +++ .../obj-c++.dg/property/at-property-4.mm | 27 +++++++++++-------- .../objc.dg/property/at-property-4.m | 21 +++++++++------ 7 files changed, 53 insertions(+), 21 deletions(-) diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h index 7e2cd5342aa..bfcc279609c 100644 --- a/gcc/c-family/c-common.h +++ b/gcc/c-family/c-common.h @@ -275,9 +275,11 @@ enum rid ((unsigned int) (rid) >= (unsigned int) RID_FIRST_PQ && \ (unsigned int) (rid) <= (unsigned int) RID_LAST_PQ) +/* Keywords permitted in an @property attribute context. */ #define OBJC_IS_PATTR_KEYWORD(rid) \ - ((unsigned int) (rid) >= (unsigned int) RID_FIRST_PATTR && \ - (unsigned int) (rid) <= (unsigned int) RID_LAST_PATTR) + ((((unsigned int) (rid) >= (unsigned int) RID_FIRST_PATTR && \ + (unsigned int) (rid) <= (unsigned int) RID_LAST_PATTR)) \ + || rid == RID_CLASS) /* OBJC_IS_CXX_KEYWORD recognizes the 'CXX_OBJC' keywords (such as 'class') which are shared in a subtle way between Objective-C and diff --git a/gcc/c-family/c-objc.h b/gcc/c-family/c-objc.h index a2ca112dcc6..6e96731882b 100644 --- a/gcc/c-family/c-objc.h +++ b/gcc/c-family/c-objc.h @@ -44,6 +44,7 @@ enum objc_property_attribute_group OBJC_PROPATTR_GROUP_READWRITE, OBJC_PROPATTR_GROUP_ASSIGN, OBJC_PROPATTR_GROUP_ATOMIC, + OBJC_PROPATTR_GROUP_CLASS, OBJC_PROPATTR_GROUP_MAX }; @@ -59,6 +60,7 @@ enum objc_property_attribute_kind OBJC_PROPERTY_ATTR_COPY = ( 7 << 8)|OBJC_PROPATTR_GROUP_ASSIGN, OBJC_PROPERTY_ATTR_ATOMIC = ( 8 << 8)|OBJC_PROPATTR_GROUP_ATOMIC, OBJC_PROPERTY_ATTR_NONATOMIC = ( 9 << 8)|OBJC_PROPATTR_GROUP_ATOMIC, + OBJC_PROPERTY_ATTR_CLASS = (16 << 8)|OBJC_PROPATTR_GROUP_CLASS, OBJC_PROPERTY_ATTR_MAX = (255 << 8|OBJC_PROPATTR_GROUP_MAX) }; diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index c4c672efa09..323d7424a83 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -34052,6 +34052,10 @@ cp_parser_objc_at_property_declaration (cp_parser *parser) enum rid keyword; if (token->type == CPP_NAME) keyword = C_RID_CODE (token->u.value); + else if (token->type == CPP_KEYWORD + && token->keyword == RID_CLASS) + /* Account for accepting the 'class' keyword in this context. */ + keyword = RID_CLASS; else keyword = RID_MAX; /* By definition, an unknown property. */ cp_lexer_consume_token (parser->lexer); diff --git a/gcc/objc/objc-act.c b/gcc/objc/objc-act.c index 2dad46aa77e..b9ed32d51d0 100644 --- a/gcc/objc/objc-act.c +++ b/gcc/objc/objc-act.c @@ -825,6 +825,7 @@ objc_prop_attr_kind_for_rid (enum rid prop_rid) case RID_PROPATOMIC: return OBJC_PROPERTY_ATTR_ATOMIC; case RID_NONATOMIC: return OBJC_PROPERTY_ATTR_NONATOMIC; + case RID_CLASS: return OBJC_PROPERTY_ATTR_CLASS; } } @@ -986,6 +987,14 @@ objc_add_property_declaration (location_t location, tree decl, gcc_unreachable (); } + /* An attribute that indicates this property manipulates a class variable. + In this case, both the variable and the getter/setter must be provided + by the user. */ + bool property_class = false; + if (attrs[OBJC_PROPATTR_GROUP_CLASS]) + property_nonatomic = attrs[OBJC_PROPATTR_GROUP_CLASS]->prop_kind + == OBJC_PROPERTY_ATTR_CLASS; + /* TODO: Check that the property type is an Objective-C object or a "POD". */ @@ -1273,6 +1282,7 @@ objc_add_property_declaration (location_t location, tree decl, PROPERTY_SETTER_NAME (property_decl) = property_setter_ident; PROPERTY_READONLY (property_decl) = property_readonly; PROPERTY_NONATOMIC (property_decl) = property_nonatomic; + PROPERTY_CLASS (property_decl) = property_class; PROPERTY_ASSIGN_SEMANTICS (property_decl) = property_assign_semantics; PROPERTY_IVAR_NAME (property_decl) = NULL_TREE; PROPERTY_DYNAMIC (property_decl) = 0; diff --git a/gcc/objc/objc-act.h b/gcc/objc/objc-act.h index db71b6a265e..5b0433ff0ee 100644 --- a/gcc/objc/objc-act.h +++ b/gcc/objc/objc-act.h @@ -137,6 +137,10 @@ enum objc_property_assign_semantics { #define PROPERTY_OPTIONAL(DECL) \ DECL_LANG_FLAG_5 (PROPERTY_DECL_CHECK (DECL)) +/* PROPERTY_CLASS can be 0 or 1. */ +#define PROPERTY_CLASS(DECL) \ + DECL_LANG_FLAG_6 (PROPERTY_DECL_CHECK (DECL)) + /* PROPERTY_REF. A PROPERTY_REF represents an 'object.property' expression. It is normally used for property access, but when the Objective-C 2.0 "dot-syntax" (object.component) is used diff --git a/gcc/testsuite/obj-c++.dg/property/at-property-4.mm b/gcc/testsuite/obj-c++.dg/property/at-property-4.mm index 31f2eb4336a..f73d70639b6 100644 --- a/gcc/testsuite/obj-c++.dg/property/at-property-4.mm +++ b/gcc/testsuite/obj-c++.dg/property/at-property-4.mm @@ -14,17 +14,22 @@ - (void) mySetter2: (int)property; /* Test that all the new property attributes can be parsed. */ -@property (assign) id property_a; -@property (copy) id property_b; -@property (atomic) int property_ca; -@property (nonatomic) int property_c; -@property (readonly) int property_d; -@property (readwrite) int property_e; -@property (retain) id property_f; -@property (release) int property_g; /* { dg-error "unknown property attribute" } */ - -@property (getter=myGetter) int property_h; -@property (setter=mySetter:) int property_i; +@property (assign) id property_as_1; +@property (copy) id property_as_2; +@property (retain) id property_as_3; + +@property (atomic) int property_at_1; +@property (nonatomic) int property_at_2; + +@property (readonly) int property_rw_1; +@property (readwrite) int property_rw_2; + +@property (class) int property_cl_1; + +@property (release) int property_err_1; /* { dg-error "unknown property attribute" } */ + +@property (getter=myGetter) int property_g0; +@property (setter=mySetter:) int property_s0; /* Now test various problems. */ diff --git a/gcc/testsuite/objc.dg/property/at-property-4.m b/gcc/testsuite/objc.dg/property/at-property-4.m index 31f2eb4336a..0e905db0eb4 100644 --- a/gcc/testsuite/objc.dg/property/at-property-4.m +++ b/gcc/testsuite/objc.dg/property/at-property-4.m @@ -14,14 +14,19 @@ - (void) mySetter2: (int)property; /* Test that all the new property attributes can be parsed. */ -@property (assign) id property_a; -@property (copy) id property_b; -@property (atomic) int property_ca; -@property (nonatomic) int property_c; -@property (readonly) int property_d; -@property (readwrite) int property_e; -@property (retain) id property_f; -@property (release) int property_g; /* { dg-error "unknown property attribute" } */ +@property (assign) id property_as_1; +@property (copy) id property_as_2; +@property (retain) id property_as_3; + +@property (atomic) int property_at_1; +@property (nonatomic) int property_at_2; + +@property (readonly) int property_rw_1; +@property (readwrite) int property_rw_2; + +@property (class) int property_cl_1; + +@property (release) int property_err_1; /* { dg-error "unknown property attribute" } */ @property (getter=myGetter) int property_h; @property (setter=mySetter:) int property_i; -- 2.30.2