diff options
author | Douglas Gregor <doug.gregor@gmail.com> | 2007-07-27 17:43:05 +0000 |
---|---|---|
committer | Doug Gregor <dgregor@gcc.gnu.org> | 2007-07-27 17:43:05 +0000 |
commit | 3ad6a8e12ca4ac15b759f6a407d2ca2ea32e17a2 (patch) | |
tree | 1fd8c965b4122258e1d88e04db3ecb09a3757908 /gcc/cp/parser.c | |
parent | 8a67955f0815ecf2892c635ca4128a5f414eb507 (diff) | |
download | gcc-3ad6a8e12ca4ac15b759f6a407d2ca2ea32e17a2.zip gcc-3ad6a8e12ca4ac15b759f6a407d2ca2ea32e17a2.tar.gz gcc-3ad6a8e12ca4ac15b759f6a407d2ca2ea32e17a2.tar.bz2 |
typeck.c (structural_comptypes): Compare DECLTYPE_TYPE nodes.
2007-07-27 Douglas Gregor <doug.gregor@gmail.com>
* typeck.c (structural_comptypes): Compare DECLTYPE_TYPE nodes.
* cp-tree.def (DECLTYPE_TYPE): New.
* error.c (dump_type): Dump DECLTYPE_TYPE nodes.
(dump_type_prefix): Ditto.
(dump_type_suffix): Ditto.
* tree.c (DECLTYPE_TYPE): Walk DECLTYPE_TYPE nodes.
* mangle.c (write_type): Handle DECLTYPE_TYPE.
* cp-tree.h (IS_AGGR_TYPE): DECLTYPE_TYPE nodes can be aggregate
types.
(DECLTYPE_TYPE_EXPR): New.
(DECLTYPE_TYPE_ID_EXPR_OR_MEMBER_ACCESS_P): New.
(finish_declared_type): Declare.
* cxx-pretty-print.c (pp_cxx_type_specifier_seq): Print
DECLTYPE_TYPE nodes.
(pp_cxx_type_id): Ditto.
* pt.c (for_each_template_parm_r): Walk DECLTYPE_TYPE children.
(tsubst): Substitute into a DECLTYPE_TYPE node.
(tsubst_copy): Ditto.
(unify): Cannot deduce anything from TYPEOF_TYPE or DECLTYPE_TYPE
nodes.
(dependent_type_p_r): DECLTYPE_TYPE types are always dependent.
* semantics.c (finish_typeof): TYPEOF_TYPE types need to use
structural equality (because we can't hash the expressions).
(finish_declared_type): New.
* lex.c (reswords): Add "decltype" keyword.
* parser.c cp_lexer_next_token_is_decl_specifier_keyword
(cp_parser_postfix_expression): Add member_access_only_p to
restrict postfix expression to member access expressions.
(cp_parser_unary_expression): Update call to
cp_parser_postfix_expression to reflect new parameter.
(cp_parser_declared_type): New.
(cp_parser_simple_type_specifier): Parse decltype types.
2007-07-27 Douglas Gregor <doug.gregor@gmail.com>
* c-common.h (enum rid): Add RID_DECLTYPE, update RID_LAST_CXX0X.
2007-07-27 Douglas Gregor <doug.gregor@gmail.com>
* g++.dg/cpp0x/decltype1.C: New.
* g++.dg/cpp0x/decltype2.C: New.
* g++.dg/cpp0x/decltype3.C: New.
* g++.dg/cpp0x/decltype4.C: New.
* g++.dg/cpp0x/decltype5.C: New.
* g++.dg/cpp0x/decltype6.C: New.
From-SVN: r126991
Diffstat (limited to 'gcc/cp/parser.c')
-rw-r--r-- | gcc/cp/parser.c | 201 |
1 files changed, 197 insertions, 4 deletions
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index b8d2b15..a7190cb 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -577,6 +577,8 @@ cp_lexer_next_token_is_decl_specifier_keyword (cp_lexer *lexer) /* GNU extensions. */ case RID_ATTRIBUTE: case RID_TYPEOF: + /* C++0x extensions. */ + case RID_DECLTYPE: return true; default: @@ -1582,7 +1584,7 @@ static tree cp_parser_nested_name_specifier static tree cp_parser_class_or_namespace_name (cp_parser *, bool, bool, bool, bool, bool); static tree cp_parser_postfix_expression - (cp_parser *, bool, bool); + (cp_parser *, bool, bool, bool); static tree cp_parser_postfix_open_square_expression (cp_parser *, tree, bool); static tree cp_parser_postfix_dot_deref_expression @@ -1707,6 +1709,8 @@ static void cp_parser_linkage_specification (cp_parser *); static void cp_parser_static_assert (cp_parser *, bool); +static tree cp_parser_decltype + (cp_parser *); /* Declarators [gram.dcl.decl] */ @@ -4254,15 +4258,20 @@ cp_parser_class_or_namespace_name (cp_parser *parser, `&' operator. CAST_P is true if this expression is the target of a cast. + If MEMBER_ACCESS_ONLY_P, we only allow postfix expressions that are + class member access expressions [expr.ref]. + Returns a representation of the expression. */ static tree -cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p) +cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p, + bool member_access_only_p) { cp_token *token; enum rid keyword; cp_id_kind idk = CP_ID_KIND_NONE; tree postfix_expression = NULL_TREE; + bool is_member_access = false; /* Peek at the next token. */ token = cp_lexer_peek_token (parser->lexer); @@ -4513,6 +4522,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p) postfix_expression, false); idk = CP_ID_KIND_NONE; + is_member_access = false; break; case CPP_OPEN_PAREN: @@ -4524,6 +4534,8 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p) bool saved_non_integral_constant_expression_p = false; tree args; + is_member_access = false; + is_builtin_constant_p = DECL_IS_BUILTIN_CONSTANT_P (postfix_expression); if (is_builtin_constant_p) @@ -4669,6 +4681,8 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p) = cp_parser_postfix_dot_deref_expression (parser, token->type, postfix_expression, false, &idk); + + is_member_access = true; break; case CPP_PLUS_PLUS: @@ -4684,6 +4698,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p) "an increment")) postfix_expression = error_mark_node; idk = CP_ID_KIND_NONE; + is_member_access = false; break; case CPP_MINUS_MINUS: @@ -4699,10 +4714,14 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p) "a decrement")) postfix_expression = error_mark_node; idk = CP_ID_KIND_NONE; + is_member_access = false; break; default: - return postfix_expression; + if (member_access_only_p) + return is_member_access? postfix_expression : error_mark_node; + else + return postfix_expression; } } @@ -5341,7 +5360,8 @@ cp_parser_unary_expression (cp_parser *parser, bool address_p, bool cast_p) return expression; } - return cp_parser_postfix_expression (parser, address_p, cast_p); + return cp_parser_postfix_expression (parser, address_p, cast_p, + /*member_access_only_p=*/false); } /* Returns ERROR_MARK if TOKEN is not a unary-operator. If TOKEN is a @@ -8371,6 +8391,164 @@ cp_parser_static_assert(cp_parser *parser, bool member_p) finish_static_assert (condition, message, saved_loc, member_p); } +/* Parse a `decltype' type. Returns the type. + + simple-type-specifier: + decltype ( expression ) */ + +static tree +cp_parser_decltype (cp_parser *parser) +{ + tree expr; + bool id_expression_or_member_access_p = false; + const char *saved_message; + bool saved_integral_constant_expression_p; + bool saved_non_integral_constant_expression_p; + + /* Look for the `decltype' token. */ + if (!cp_parser_require_keyword (parser, RID_DECLTYPE, "`decltype'")) + return error_mark_node; + + /* Types cannot be defined in a `decltype' expression. Save away the + old message. */ + saved_message = parser->type_definition_forbidden_message; + + /* And create the new one. */ + parser->type_definition_forbidden_message + = "types may not be defined in `decltype' expressions"; + + /* The restrictions on constant-expressions do not apply inside + decltype expressions. */ + saved_integral_constant_expression_p + = parser->integral_constant_expression_p; + saved_non_integral_constant_expression_p + = parser->non_integral_constant_expression_p; + parser->integral_constant_expression_p = false; + + /* Do not actually evaluate the expression. */ + ++skip_evaluation; + + /* Parse the opening `('. */ + cp_parser_require (parser, CPP_OPEN_PAREN, "`('"); + + /* First, try parsing an id-expression. */ + cp_parser_parse_tentatively (parser); + expr = cp_parser_id_expression (parser, + /*template_keyword_p=*/false, + /*check_dependency_p=*/true, + /*template_p=*/NULL, + /*declarator_p=*/false, + /*optional_p=*/false); + + if (!cp_parser_error_occurred (parser) && expr != error_mark_node) + { + bool non_integral_constant_expression_p = false; + tree id_expression = expr; + cp_id_kind idk; + const char *error_msg; + + /* Lookup the name we got back from the id-expression. */ + expr = cp_parser_lookup_name (parser, expr, + none_type, + /*is_template=*/false, + /*is_namespace=*/false, + /*check_dependency=*/true, + /*ambiguous_decls=*/NULL); + + if (expr + && expr != error_mark_node + && TREE_CODE (expr) != TEMPLATE_ID_EXPR + && TREE_CODE (expr) != TYPE_DECL + && cp_lexer_peek_token (parser->lexer)->type == CPP_CLOSE_PAREN) + { + /* Complete lookup of the id-expression. */ + expr = (finish_id_expression + (id_expression, expr, parser->scope, &idk, + /*integral_constant_expression_p=*/false, + /*allow_non_integral_constant_expression_p=*/true, + &non_integral_constant_expression_p, + /*template_p=*/false, + /*done=*/true, + /*address_p=*/false, + /*template_arg_p=*/false, + &error_msg)); + + if (expr == error_mark_node) + /* We found an id-expression, but it was something that we + should not have found. This is an error, not something + we can recover from, so note that we found an + id-expression and we'll recover as gracefully as + possible. */ + id_expression_or_member_access_p = true; + } + + if (expr + && expr != error_mark_node + && cp_lexer_peek_token (parser->lexer)->type == CPP_CLOSE_PAREN) + /* We have an id-expression. */ + id_expression_or_member_access_p = true; + } + + if (!id_expression_or_member_access_p) + { + /* Abort the id-expression parse. */ + cp_parser_abort_tentative_parse (parser); + + /* Parsing tentatively, again. */ + cp_parser_parse_tentatively (parser); + + /* Parse a class member access. */ + expr = cp_parser_postfix_expression (parser, /*address_p=*/false, + /*cast_p=*/false, + /*member_access_only_p=*/true); + + if (expr + && expr != error_mark_node + && cp_lexer_peek_token (parser->lexer)->type == CPP_CLOSE_PAREN) + /* We have an id-expression. */ + id_expression_or_member_access_p = true; + } + + if (id_expression_or_member_access_p) + /* We have parsed the complete id-expression or member access. */ + cp_parser_parse_definitely (parser); + else + { + /* Abort our attempt to parse an id-expression or member access + expression. */ + cp_parser_abort_tentative_parse (parser); + + /* Parse a full expression. */ + expr = cp_parser_expression (parser, /*cast_p=*/false); + } + + /* Go back to evaluating expressions. */ + --skip_evaluation; + + /* Restore the old message and the integral constant expression + flags. */ + parser->type_definition_forbidden_message = saved_message; + parser->integral_constant_expression_p + = saved_integral_constant_expression_p; + parser->non_integral_constant_expression_p + = saved_non_integral_constant_expression_p; + + if (expr == error_mark_node) + { + /* Skip everything up to the closing `)'. */ + cp_parser_skip_to_closing_parenthesis (parser, true, false, + /*consume_paren=*/true); + return error_mark_node; + } + + /* Parse to the closing `)'. */ + if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'")) + cp_parser_skip_to_closing_parenthesis (parser, true, false, + /*consume_paren=*/true); + + return finish_decltype_type (expr, id_expression_or_member_access_p); +} + /* Special member functions [gram.special] */ /* Parse a conversion-function-id. @@ -10438,6 +10616,11 @@ cp_parser_type_specifier (cp_parser* parser, double void + C++0x Extension: + + simple-type-specifier: + decltype ( expression ) + GNU Extension: simple-type-specifier: @@ -10507,6 +10690,16 @@ cp_parser_simple_type_specifier (cp_parser* parser, type = void_type_node; break; + case RID_DECLTYPE: + /* Parse the `decltype' type. */ + type = cp_parser_decltype (parser); + + if (decl_specs) + cp_parser_set_decl_spec_type (decl_specs, type, + /*user_defined_p=*/true); + + return type; + case RID_TYPEOF: /* Consume the `typeof' token. */ cp_lexer_consume_token (parser->lexer); |