This is just for the parser, the semantic analysis of virt-specifiers will be done later. Also, these changes don't yet support a final specifier on class.
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index e538825..08d939f 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -4420,6 +4420,11 @@ extern GTY(()) operator_name_info_t assignment_operator_name_info typedef int cp_cv_quals; +/* A type-qualifier, or bitmask therefore, using the VIRT_SPEC + constants. */ + +typedef int cp_virt_specifiers; + /* A storage class. */ typedef enum cp_storage_class { @@ -4562,6 +4567,8 @@ struct cp_declarator { tree parameters; /* The cv-qualifiers for the function. */ cp_cv_quals qualifiers; + /* The virt-specifiers for the function. */ + cp_virt_specifiers virt_specifiers; /* The exception-specification for the function. */ tree exception_specification; /* The late-specified return type, if any. */ diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 7d3121c..bf28172 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -936,7 +936,7 @@ clear_decl_specs (cp_decl_specifier_seq *decl_specs) VAR_DECLs or FUNCTION_DECLs) should do that directly. */ static cp_declarator *make_call_declarator - (cp_declarator *, tree, cp_cv_quals, tree, tree); + (cp_declarator *, tree, cp_cv_quals, cp_virt_specifiers, tree, tree); static cp_declarator *make_array_declarator (cp_declarator *, tree); static cp_declarator *make_pointer_declarator @@ -1101,6 +1101,7 @@ cp_declarator * make_call_declarator (cp_declarator *target, tree parms, cp_cv_quals cv_qualifiers, + cp_virt_specifiers virt_specifiers, tree exception_specification, tree late_return_type) { @@ -1110,6 +1111,7 @@ make_call_declarator (cp_declarator *target, declarator->declarator = target; declarator->u.function.parameters = parms; declarator->u.function.qualifiers = cv_qualifiers; + declarator->u.function.virt_specifiers = virt_specifiers; declarator->u.function.exception_specification = exception_specification; declarator->u.function.late_return_type = late_return_type; if (target) @@ -1689,6 +1691,8 @@ static enum tree_code cp_parser_ptr_operator (cp_parser *, tree *, cp_cv_quals *); static cp_cv_quals cp_parser_cv_qualifier_seq_opt (cp_parser *); +static cp_virt_specifiers cp_parser_virt_specifier_seq_opt + (cp_parser *); static tree cp_parser_late_return_type_opt (cp_parser *); static tree cp_parser_declarator_id @@ -7648,6 +7652,7 @@ cp_parser_lambda_declarator_opt (cp_parser* parser, tree lambda_expr) quals = (LAMBDA_EXPR_MUTABLE_P (lambda_expr) ? TYPE_UNQUALIFIED : TYPE_QUAL_CONST); declarator = make_call_declarator (declarator, param_list, quals, + VIRT_SPEC_UNSPECIFIED, exception_spec, /*late_return_type=*/NULL_TREE); declarator->id_loc = LAMBDA_EXPR_LOCATION (lambda_expr); @@ -14860,6 +14865,7 @@ cp_parser_direct_declarator (cp_parser* parser, if (member_p || cp_parser_parse_definitely (parser)) { cp_cv_quals cv_quals; + cp_virt_specifiers virt_specifiers; tree exception_specification; tree late_return; @@ -14876,6 +14882,8 @@ cp_parser_direct_declarator (cp_parser* parser, /* And the exception-specification. */ exception_specification = cp_parser_exception_specification_opt (parser); + /* Parse the virt-specifier-seq. */ + virt_specifiers = cp_parser_virt_specifier_seq_opt (parser); late_return = cp_parser_late_return_type_opt (parser); @@ -14884,6 +14892,7 @@ cp_parser_direct_declarator (cp_parser* parser, declarator = make_call_declarator (declarator, params, cv_quals, + virt_specifiers, exception_specification, late_return); /* Any subsequent parameter lists are to do with @@ -15391,6 +15400,62 @@ cp_parser_cv_qualifier_seq_opt (cp_parser* parser) return cv_quals; } +/* Parse an (optional) virt-specifier-seq. + + virt-specifier-seq: + virt-specifier virt-specifier-seq [opt] + + virt-specifier: + override + final + + Returns a bitmask representing the virt-specifiers. */ + +static cp_virt_specifiers cp_parser_virt_specifier_seq_opt + (cp_parser* parser) +{ + cp_virt_specifiers virt_specifiers = VIRT_SPEC_UNSPECIFIED; + + while (true) + { + cp_token *token; + cp_virt_specifiers virt_specifier; + + /* Peek at the next token. */ + token = cp_lexer_peek_token (parser->lexer); + /* See if it's a virt-specifier-qualifier. */ + if (token->type != CPP_NAME) + break; + if (!strcmp(IDENTIFIER_POINTER(token->u.value), "override")) + { + virt_specifier = VIRT_SPEC_OVERRIDE; + } + else if (!strcmp(IDENTIFIER_POINTER(token->u.value), "final")) + { + virt_specifier = VIRT_SPEC_FINAL; + } + else + { + virt_specifier = VIRT_SPEC_UNSPECIFIED; + } + + if (!virt_specifier) + break; + + if (virt_specifiers & virt_specifier) + { + error_at (token->location, "duplicate virt-specifier"); + cp_lexer_purge_token (parser->lexer); + } + else + { + cp_lexer_consume_token (parser->lexer); + virt_specifiers |= virt_specifier; + } + } + return virt_specifiers; +} + /* Parse a late-specified return type, if any. This is not a separate non-terminal, but part of a function declarator, which looks like diff --git a/gcc/tree.h b/gcc/tree.h index 0bc98cd..e6a66fa 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -2259,6 +2259,15 @@ extern enum machine_mode vector_type_mode (const_tree); #define TYPE_QUAL_VOLATILE 0x2 #define TYPE_QUAL_RESTRICT 0x4 +/* Non-static member functions have an optional virt-specifier-seq. + There is a VIRT_SPEC value for each virt-specifier. + They can be combined by bitwise-or to form the complete set of + virt-specifiers for a member function. */ + +#define VIRT_SPEC_UNSPECIFIED 0x0 +#define VIRT_SPEC_FINAL 0x1 +#define VIRT_SPEC_OVERRIDE 0x2 + /* Encode/decode the named memory support as part of the qualifier. If more than 8 qualifiers are added, these macros need to be adjusted. */ #define ENCODE_QUAL_ADDR_SPACE(NUM) ((NUM & 0xFF) << 8)