diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 6812f8b86a3..77aeeb08070 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,29 @@ +2004-06-26 Mark Mitchell + + * cp-tree.h (cp_cv_quals): New type. + (cp_declarator): Use it instead of "tree" as appropriate. + (grok_method_quals): Adjust prototype. + (grokclassfn): Likewise. + (do_friend): Likewise. + * decl.c (grokfndecl): Use cp_cv_quals, not tree. + (grokdeclarator): Likewise. + * decl2.c (grok_method_quals): Likewise. + (grokclassfn): Likewise. + * friend.c (do_friend): Likewise. + * method.c (implicitly_declare_fn): Adjust call to grokclassfn. + * parser.c (make_call_declarator): Use cp_cv_quals, not tree. + (make_pointer_declarator): Likewise. + (make_reference_declarator): Likewise. + (make_ptrmem_declarator): Likewise. + (cp_parser_ptr_operator): Likewise. + (cp_parser_cv_qualifier_seq_opt): Likewise. + (cp_parser_cv_qualifier_opt): Remove. + (cp_parser_new_declarator_opt): Adjust call to + cp_parser_ptr_operator. + (cp_parser_conversion_declaration_opt): Likewise. + (cp_parser_declarator): Use cp_cv_quals, not tree. + (cp_parser_direct_declarator): Likewise. + 2004-06-26 Richard Kenner * call.c, cp-tree.h, cxx-pretty-print.c, decl.c, decl2.c: diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index f2ebb649988..54bb0e3bb20 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -3503,6 +3503,11 @@ extern GTY(()) operator_name_info_t operator_name_info extern GTY(()) operator_name_info_t assignment_operator_name_info [(int) LAST_CPLUS_TREE_CODE]; +/* A type-qualifier, or bitmask therefore, using the TYPE_QUAL + constants. */ + +typedef int cp_cv_quals; + /* A storage class. */ typedef enum cp_storage_class { @@ -3628,7 +3633,7 @@ struct cp_declarator { /* The parameters to the function. */ cp_parameter_declarator *parameters; /* The cv-qualifiers for the function. */ - tree qualifiers; + cp_cv_quals qualifiers; /* The exception-specification for the function. */ tree exception_specification; } function; @@ -3640,7 +3645,7 @@ struct cp_declarator { /* For cdk_pointer, cdk_reference, and cdk_ptrmem. */ struct { /* The cv-qualifiers for the pointer. */ - tree qualifiers; + cp_cv_quals qualifiers; /* For cdk_ptrmem, the class type containing the member. */ tree class_type; } pointer; @@ -3866,10 +3871,10 @@ extern bool have_extern_spec; /* in decl2.c */ extern bool check_java_method (tree); -extern int grok_method_quals (tree, tree, tree); +extern cp_cv_quals grok_method_quals (tree, tree, cp_cv_quals); extern void maybe_retrofit_in_chrg (tree); extern void maybe_make_one_only (tree); -extern void grokclassfn (tree, tree, enum overload_flags, tree); +extern void grokclassfn (tree, tree, enum overload_flags, cp_cv_quals); extern tree grok_array_decl (tree, tree); extern tree delete_sanity (tree, tree, bool, int); extern tree check_classfn (tree, tree, tree); @@ -3941,7 +3946,7 @@ extern tree cplus_expand_constant (tree); extern int is_friend (tree, tree); extern void make_friend_class (tree, tree, bool); extern void add_friend (tree, tree, bool); -extern tree do_friend (tree, tree, tree, tree, enum overload_flags, tree, int); +extern tree do_friend (tree, tree, tree, tree, enum overload_flags, cp_cv_quals, int); /* in init.c */ extern tree expand_member_init (tree); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 9d2aedb8123..838f22bd55a 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -62,7 +62,7 @@ static int unary_op_p (enum tree_code); static void push_local_name (tree); static tree grok_reference_init (tree, tree, tree, tree *); static tree grokfndecl (tree, tree, tree, tree, tree, int, - enum overload_flags, tree, + enum overload_flags, cp_cv_quals, tree, int, int, int, int, int, int, tree); static tree grokvardecl (tree, tree, cp_decl_specifier_seq *, int, int, tree); static void record_unknown_type (tree, const char *); @@ -5424,7 +5424,7 @@ grokfndecl (tree ctype, tree orig_declarator, int virtualp, enum overload_flags flags, - tree quals, + cp_cv_quals quals, tree raises, int check, int friendp, @@ -5544,11 +5544,11 @@ grokfndecl (tree ctype, DECL_INLINE (decl) = 1; DECL_EXTERNAL (decl) = 1; - if (quals != NULL_TREE && TREE_CODE (type) == FUNCTION_TYPE) + if (quals && TREE_CODE (type) == FUNCTION_TYPE) { - error ("%smember function `%D' cannot have `%T' method qualifier", - (ctype ? "static " : "non-"), decl, TREE_VALUE (quals)); - quals = NULL_TREE; + error ("%smember function `%D' cannot have cv-qualifier", + (ctype ? "static " : "non-"), decl); + quals = TYPE_UNQUALIFIED; } if (IDENTIFIER_OPNAME_P (DECL_NAME (decl))) @@ -6287,7 +6287,7 @@ grokdeclarator (const cp_declarator *declarator, tree dname = NULL_TREE; tree ctor_return_type = NULL_TREE; enum overload_flags flags = NO_SPECIAL; - tree quals = NULL_TREE; + cp_cv_quals quals = TYPE_UNQUALIFIED; tree raises = NULL_TREE; int template_count = 0; tree returned_attrs = NULL_TREE; @@ -6546,7 +6546,7 @@ grokdeclarator (const cp_declarator *declarator, } else if (declspecs->specs[(int)ds] > 1) { - static const char *decl_spec_names[] = { + static const char *const decl_spec_names[] = { "signed", "unsigned", "short", @@ -7049,9 +7049,8 @@ grokdeclarator (const cp_declarator *declarator, error ("destructor cannot be static member function"); if (quals) { - error ("destructors may not be `%E'", - TREE_VALUE (quals)); - quals = NULL_TREE; + error ("destructors may not be cv-qualified"); + quals = TYPE_UNQUALIFIED; } if (decl_context == FIELD) { @@ -7078,9 +7077,8 @@ grokdeclarator (const cp_declarator *declarator, } if (quals) { - error ("constructors may not be `%E'", - TREE_VALUE (quals)); - quals = NULL_TREE; + error ("constructors may not be cv-qualified"); + quals = TYPE_UNQUALIFIED; } if (decl_context == FIELD) { @@ -7163,7 +7161,7 @@ grokdeclarator (const cp_declarator *declarator, grok_method_quals (declarator->u.pointer.class_type, dummy, quals); type = TREE_TYPE (dummy); - quals = NULL_TREE; + quals = TYPE_UNQUALIFIED; } if (declarator->kind == cdk_reference) @@ -7184,45 +7182,9 @@ grokdeclarator (const cp_declarator *declarator, if (declarator->u.pointer.qualifiers) { - tree typemodlist; - int erred = 0; - int constp = 0; - int volatilep = 0; - int restrictp = 0; - - for (typemodlist = declarator->u.pointer.qualifiers; typemodlist; - typemodlist = TREE_CHAIN (typemodlist)) - { - tree qualifier = TREE_VALUE (typemodlist); - - if (qualifier == ridpointers[(int) RID_CONST]) - { - constp++; - type_quals |= TYPE_QUAL_CONST; - } - else if (qualifier == ridpointers[(int) RID_VOLATILE]) - { - volatilep++; - type_quals |= TYPE_QUAL_VOLATILE; - } - else if (qualifier == ridpointers[(int) RID_RESTRICT]) - { - restrictp++; - type_quals |= TYPE_QUAL_RESTRICT; - } - else if (!erred) - { - erred = 1; - error ("invalid type modifier within pointer declarator"); - } - } - if (constp > 1) - pedwarn ("duplicate `const'"); - if (volatilep > 1) - pedwarn ("duplicate `volatile'"); - if (restrictp > 1) - pedwarn ("duplicate `restrict'"); - type = cp_build_qualified_type (type, type_quals); + type + = cp_build_qualified_type (type, + declarator->u.pointer.qualifiers); type_quals = cp_type_quals (type); } ctype = NULL_TREE; @@ -7488,7 +7450,7 @@ grokdeclarator (const cp_declarator *declarator, || (typedef_decl && C_TYPEDEF_EXPLICITLY_SIGNED (typedef_decl))) C_TYPEDEF_EXPLICITLY_SIGNED (decl) = 1; - bad_specifiers (decl, "type", virtualp, quals != NULL_TREE, + bad_specifiers (decl, "type", virtualp, quals != TYPE_UNQUALIFIED, inlinep, friendp, raises != NULL_TREE); return decl; @@ -7654,7 +7616,7 @@ grokdeclarator (const cp_declarator *declarator, { decl = cp_build_parm_decl (unqualified_id, type); - bad_specifiers (decl, "parameter", virtualp, quals != NULL_TREE, + bad_specifiers (decl, "parameter", virtualp, quals != TYPE_UNQUALIFIED, inlinep, friendp, raises != NULL_TREE); } else if (decl_context == FIELD) @@ -7908,7 +7870,7 @@ grokdeclarator (const cp_declarator *declarator, } } - bad_specifiers (decl, "field", virtualp, quals != NULL_TREE, + bad_specifiers (decl, "field", virtualp, quals != TYPE_UNQUALIFIED, inlinep, friendp, raises != NULL_TREE); } } @@ -8009,7 +7971,7 @@ grokdeclarator (const cp_declarator *declarator, initialized, (type_quals & TYPE_QUAL_CONST) != 0, ctype ? ctype : in_namespace); - bad_specifiers (decl, "variable", virtualp, quals != NULL_TREE, + bad_specifiers (decl, "variable", virtualp, quals != TYPE_UNQUALIFIED, inlinep, friendp, raises != NULL_TREE); if (ctype) diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index 142bd4b7f87..2214e8d3656 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -118,31 +118,15 @@ tree static_dtors; TYPE_UNQUALIFIED will be an extension. */ int -grok_method_quals (tree ctype, tree function, tree quals) +grok_method_quals (tree ctype, tree function, cp_cv_quals quals) { tree fntype = TREE_TYPE (function); tree raises = TYPE_RAISES_EXCEPTIONS (fntype); int type_quals = TYPE_UNQUALIFIED; - int dup_quals = TYPE_UNQUALIFIED; int this_quals = TYPE_UNQUALIFIED; - while (quals) - { - int tq = cp_type_qual_from_rid (TREE_VALUE (quals)); - - if ((type_quals | this_quals) & tq) - dup_quals |= tq; - else if (tq & TYPE_QUAL_RESTRICT) - this_quals |= tq; - else - type_quals |= tq; - quals = TREE_CHAIN (quals); - } - - if (dup_quals != TYPE_UNQUALIFIED) - error ("duplicate type qualifiers in %s declaration", - TREE_CODE (function) == FUNCTION_DECL - ? "member function" : "type"); + type_quals = quals & ~TYPE_QUAL_RESTRICT; + this_quals = quals & TYPE_QUAL_RESTRICT; ctype = cp_build_qualified_type (ctype, type_quals); fntype = build_method_type_directly (ctype, TREE_TYPE (fntype), @@ -281,10 +265,11 @@ maybe_retrofit_in_chrg (tree fn) QUALS are the qualifiers for the this pointer. */ void -grokclassfn (tree ctype, tree function, enum overload_flags flags, tree quals) +grokclassfn (tree ctype, tree function, enum overload_flags flags, + cp_cv_quals quals) { tree fn_name = DECL_NAME (function); - int this_quals = TYPE_UNQUALIFIED; + cp_cv_quals this_quals = TYPE_UNQUALIFIED; /* Even within an `extern "C"' block, members get C++ linkage. See [dcl.link] for details. */ diff --git a/gcc/cp/friend.c b/gcc/cp/friend.c index f815b99f0b9..faf558c4245 100644 --- a/gcc/cp/friend.c +++ b/gcc/cp/friend.c @@ -325,7 +325,8 @@ make_friend_class (tree type, tree friend_type, bool complain) tree do_friend (tree ctype, tree declarator, tree decl, - tree attrlist, enum overload_flags flags, tree quals, + tree attrlist, enum overload_flags flags, + cp_cv_quals quals, int funcdef_flag) { /* Every decl that gets here is a friend of something. */ diff --git a/gcc/cp/method.c b/gcc/cp/method.c index cc06725c3c3..adda8da26bc 100644 --- a/gcc/cp/method.c +++ b/gcc/cp/method.c @@ -1020,7 +1020,7 @@ implicitly_declare_fn (special_function_kind kind, tree type, bool const_p) } grokclassfn (type, fn, kind == sfk_destructor ? DTOR_FLAG : NO_SPECIAL, - /*quals=*/NULL_TREE); + TYPE_UNQUALIFIED); grok_special_member_properties (fn); cp_finish_decl (fn, /*init=*/NULL_TREE, /*asmspec_tree=*/NULL_TREE, /*flags=*/LOOKUP_ONLYCONVERTING); diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index e6b1f920815..1b989dbe283 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -1019,17 +1019,17 @@ clear_decl_specs (cp_decl_specifier_seq *decl_specs) static cp_declarator *make_id_declarator (tree); static cp_declarator *make_call_declarator - (cp_declarator *, cp_parameter_declarator *, tree, tree); + (cp_declarator *, cp_parameter_declarator *, cp_cv_quals, tree); static cp_declarator *make_array_declarator (cp_declarator *, tree); static cp_declarator *make_pointer_declarator - (tree, cp_declarator *); + (cp_cv_quals, cp_declarator *); static cp_declarator *make_reference_declarator - (tree, cp_declarator *); + (cp_cv_quals, cp_declarator *); static cp_parameter_declarator *make_parameter_declarator (cp_decl_specifier_seq *, cp_declarator *, tree); static cp_declarator *make_ptrmem_declarator - (tree, tree, cp_declarator *); + (cp_cv_quals, tree, cp_declarator *); cp_declarator *cp_error_declarator; @@ -1080,7 +1080,7 @@ make_id_declarator (tree id) type, represented as identifiers. */ cp_declarator * -make_pointer_declarator (tree cv_qualifiers, cp_declarator *target) +make_pointer_declarator (cp_cv_quals cv_qualifiers, cp_declarator *target) { cp_declarator *declarator; @@ -1095,7 +1095,7 @@ make_pointer_declarator (tree cv_qualifiers, cp_declarator *target) /* Like make_pointer_declarator -- but for references. */ cp_declarator * -make_reference_declarator (tree cv_qualifiers, cp_declarator *target) +make_reference_declarator (cp_cv_quals cv_qualifiers, cp_declarator *target) { cp_declarator *declarator; @@ -1111,7 +1111,7 @@ make_reference_declarator (tree cv_qualifiers, cp_declarator *target) member of CLASS_TYPE. */ cp_declarator * -make_ptrmem_declarator (tree cv_qualifiers, tree class_type, +make_ptrmem_declarator (cp_cv_quals cv_qualifiers, tree class_type, cp_declarator *pointee) { cp_declarator *declarator; @@ -1132,7 +1132,7 @@ make_ptrmem_declarator (tree cv_qualifiers, tree class_type, cp_declarator * make_call_declarator (cp_declarator *target, cp_parameter_declarator *parms, - tree cv_qualifiers, + cp_cv_quals cv_qualifiers, tree exception_specification) { cp_declarator *declarator; @@ -1693,10 +1693,8 @@ static cp_declarator *cp_parser_declarator static cp_declarator *cp_parser_direct_declarator (cp_parser *, cp_parser_declarator_kind, int *); static enum tree_code cp_parser_ptr_operator - (cp_parser *, tree *, tree *); -static tree cp_parser_cv_qualifier_seq_opt - (cp_parser *); -static tree cp_parser_cv_qualifier_opt + (cp_parser *, tree *, cp_cv_quals *); +static cp_cv_quals cp_parser_cv_qualifier_seq_opt (cp_parser *); static tree cp_parser_declarator_id (cp_parser *); @@ -4956,12 +4954,12 @@ cp_parser_new_declarator_opt (cp_parser* parser) { enum tree_code code; tree type; - tree cv_qualifier_seq; + cp_cv_quals cv_quals; /* We don't know if there's a ptr-operator next, or not. */ cp_parser_parse_tentatively (parser); /* Look for a ptr-operator. */ - code = cp_parser_ptr_operator (parser, &type, &cv_qualifier_seq); + code = cp_parser_ptr_operator (parser, &type, &cv_quals); /* If that worked, look for more new-declarators. */ if (cp_parser_parse_definitely (parser)) { @@ -4972,15 +4970,11 @@ cp_parser_new_declarator_opt (cp_parser* parser) /* Create the representation of the declarator. */ if (type) - declarator = make_ptrmem_declarator (cv_qualifier_seq, - type, - declarator); + declarator = make_ptrmem_declarator (cv_quals, type, declarator); else if (code == INDIRECT_REF) - declarator = make_pointer_declarator (cv_qualifier_seq, - declarator); + declarator = make_pointer_declarator (cv_quals, declarator); else - declarator = make_reference_declarator (cv_qualifier_seq, - declarator); + declarator = make_reference_declarator (cv_quals, declarator); return declarator; } @@ -7570,13 +7564,12 @@ cp_parser_conversion_declarator_opt (cp_parser* parser) { enum tree_code code; tree class_type; - tree cv_qualifier_seq; + cp_cv_quals cv_quals; /* We don't know if there's a ptr-operator next, or not. */ cp_parser_parse_tentatively (parser); /* Try the ptr-operator. */ - code = cp_parser_ptr_operator (parser, &class_type, - &cv_qualifier_seq); + code = cp_parser_ptr_operator (parser, &class_type, &cv_quals); /* If it worked, look for more conversion-declarators. */ if (cp_parser_parse_definitely (parser)) { @@ -7587,15 +7580,12 @@ cp_parser_conversion_declarator_opt (cp_parser* parser) /* Create the representation of the declarator. */ if (class_type) - declarator = make_ptrmem_declarator (cv_qualifier_seq, - class_type, + declarator = make_ptrmem_declarator (cv_quals, class_type, declarator); else if (code == INDIRECT_REF) - declarator = make_pointer_declarator (cv_qualifier_seq, - declarator); + declarator = make_pointer_declarator (cv_quals, declarator); else - declarator = make_reference_declarator (cv_qualifier_seq, - declarator); + declarator = make_reference_declarator (cv_quals, declarator); return declarator; } @@ -10779,7 +10769,7 @@ cp_parser_declarator (cp_parser* parser, cp_token *token; cp_declarator *declarator; enum tree_code code; - tree cv_qualifier_seq; + cp_cv_quals cv_quals; tree class_type; tree attributes = NULL_TREE; @@ -10799,7 +10789,7 @@ cp_parser_declarator (cp_parser* parser, /* Parse the ptr-operator. */ code = cp_parser_ptr_operator (parser, &class_type, - &cv_qualifier_seq); + &cv_quals); /* If that worked, then we have a ptr-operator. */ if (cp_parser_parse_definitely (parser)) { @@ -10825,15 +10815,13 @@ cp_parser_declarator (cp_parser* parser, /* Build the representation of the ptr-operator. */ if (class_type) - declarator = make_ptrmem_declarator (cv_qualifier_seq, + declarator = make_ptrmem_declarator (cv_quals, class_type, declarator); else if (code == INDIRECT_REF) - declarator = make_pointer_declarator (cv_qualifier_seq, - declarator); + declarator = make_pointer_declarator (cv_quals, declarator); else - declarator = make_reference_declarator (cv_qualifier_seq, - declarator); + declarator = make_reference_declarator (cv_quals, declarator); } /* Everything else is a direct-declarator. */ else @@ -10968,7 +10956,7 @@ cp_parser_direct_declarator (cp_parser* parser, exception-specification. */ if (cp_parser_parse_definitely (parser)) { - tree cv_qualifiers; + cp_cv_quals cv_quals; tree exception_specification; if (ctor_dtor_or_conv_p) @@ -10978,7 +10966,7 @@ cp_parser_direct_declarator (cp_parser* parser, cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'"); /* Parse the cv-qualifier-seq. */ - cv_qualifiers = cp_parser_cv_qualifier_seq_opt (parser); + cv_quals = cp_parser_cv_qualifier_seq_opt (parser); /* And the exception-specification. */ exception_specification = cp_parser_exception_specification_opt (parser); @@ -10986,7 +10974,7 @@ cp_parser_direct_declarator (cp_parser* parser, /* Create the function-declarator. */ declarator = make_call_declarator (declarator, params, - cv_qualifiers, + cv_quals, exception_specification); /* Any subsequent parameter lists are to do with return type, so are not those of the declared @@ -11226,17 +11214,17 @@ cp_parser_direct_declarator (cp_parser* parser, ptr-operator: & cv-qualifier-seq [opt] - Returns INDIRECT_REF if a pointer, or pointer-to-member, was - used. Returns ADDR_EXPR if a reference was used. In the - case of a pointer-to-member, *TYPE is filled in with the - TYPE containing the member. *CV_QUALIFIER_SEQ is filled in - with the cv-qualifier-seq, or NULL_TREE, if there are no - cv-qualifiers. Returns ERROR_MARK if an error occurred. */ + Returns INDIRECT_REF if a pointer, or pointer-to-member, was used. + Returns ADDR_EXPR if a reference was used. In the case of a + pointer-to-member, *TYPE is filled in with the TYPE containing the + member. *CV_QUALS is filled in with the cv-qualifier-seq, or + TYPE_UNQUALIFIED, if there are no cv-qualifiers. Returns + ERROR_MARK if an error occurred. */ static enum tree_code cp_parser_ptr_operator (cp_parser* parser, tree* type, - tree* cv_qualifier_seq) + cp_cv_quals *cv_quals) { enum tree_code code = ERROR_MARK; cp_token *token; @@ -11244,7 +11232,7 @@ cp_parser_ptr_operator (cp_parser* parser, /* Assume that it's not a pointer-to-member. */ *type = NULL_TREE; /* And that there are no cv-qualifiers. */ - *cv_qualifier_seq = NULL_TREE; + *cv_quals = TYPE_UNQUALIFIED; /* Peek at the next token. */ token = cp_lexer_peek_token (parser->lexer); @@ -11263,7 +11251,7 @@ cp_parser_ptr_operator (cp_parser* parser, enforced during semantic analysis. */ if (code == INDIRECT_REF || cp_parser_allow_gnu_extensions_p (parser)) - *cv_qualifier_seq = cp_parser_cv_qualifier_seq_opt (parser); + *cv_quals = cp_parser_cv_qualifier_seq_opt (parser); } else { @@ -11293,7 +11281,7 @@ cp_parser_ptr_operator (cp_parser* parser, /* Indicate that the `*' operator was used. */ code = INDIRECT_REF; /* Look for the optional cv-qualifier-seq. */ - *cv_qualifier_seq = cp_parser_cv_qualifier_seq_opt (parser); + *cv_quals = cp_parser_cv_qualifier_seq_opt (parser); } /* If that didn't work we don't have a ptr-operator. */ if (!cp_parser_parse_definitely (parser)) @@ -11308,35 +11296,6 @@ cp_parser_ptr_operator (cp_parser* parser, cv-qualifier-seq: cv-qualifier cv-qualifier-seq [opt] - Returns a TREE_LIST. The TREE_VALUE of each node is the - representation of a cv-qualifier. */ - -static tree -cp_parser_cv_qualifier_seq_opt (cp_parser* parser) -{ - tree cv_qualifiers = NULL_TREE; - - while (true) - { - tree cv_qualifier; - - /* Look for the next cv-qualifier. */ - cv_qualifier = cp_parser_cv_qualifier_opt (parser); - /* If we didn't find one, we're done. */ - if (!cv_qualifier) - break; - - /* Add this cv-qualifier to the list. */ - cv_qualifiers - = tree_cons (NULL_TREE, cv_qualifier, cv_qualifiers); - } - - /* We built up the list in reverse order. */ - return nreverse (cv_qualifiers); -} - -/* Parse an (optional) cv-qualifier. - cv-qualifier: const volatile @@ -11344,33 +11303,58 @@ cp_parser_cv_qualifier_seq_opt (cp_parser* parser) GNU Extension: cv-qualifier: - __restrict__ */ + __restrict__ -static tree -cp_parser_cv_qualifier_opt (cp_parser* parser) + Returns a bitmask representing the cv-qualifiers. */ + +static cp_cv_quals +cp_parser_cv_qualifier_seq_opt (cp_parser* parser) { - cp_token *token; - tree cv_qualifier = NULL_TREE; + cp_cv_quals cv_quals = TYPE_UNQUALIFIED; - /* Peek at the next token. */ - token = cp_lexer_peek_token (parser->lexer); - /* See if it's a cv-qualifier. */ - switch (token->keyword) + while (true) { - case RID_CONST: - case RID_VOLATILE: - case RID_RESTRICT: - /* Save the value of the token. */ - cv_qualifier = token->value; - /* Consume the token. */ - cp_lexer_consume_token (parser->lexer); - break; + cp_token *token; + cp_cv_quals cv_qualifier; + + /* Peek at the next token. */ + token = cp_lexer_peek_token (parser->lexer); + /* See if it's a cv-qualifier. */ + switch (token->keyword) + { + case RID_CONST: + cv_qualifier = TYPE_QUAL_CONST; + break; + + case RID_VOLATILE: + cv_qualifier = TYPE_QUAL_VOLATILE; + break; + + case RID_RESTRICT: + cv_qualifier = TYPE_QUAL_RESTRICT; + break; + + default: + cv_qualifier = TYPE_UNQUALIFIED; + break; + } + + if (!cv_qualifier) + break; - default: - break; + if (cv_quals & cv_qualifier) + { + error ("duplicate cv-qualifier"); + cp_lexer_purge_token (parser->lexer); + } + else + { + cp_lexer_consume_token (parser->lexer); + cv_quals |= cv_qualifier; + } } - return cv_qualifier; + return cv_quals; } /* Parse a declarator-id.