Commit 34429675 by Jason Merrill Committed by Jason Merrill

PR c++/6709 (DR 743)

	PR c++/6709 (DR 743)
	PR c++/42603 (DR 950)
gcc/cp/
	* parser.c (token_is_decltype, cp_lexer_next_token_is_decltype): New.
	(cp_parser_nested_name_specifier_opt): Allow decltype.
	(cp_parser_qualifying_entity): Likewise.
	(cp_parser_decltype): Replace source tokens with CPP_DECLTYPE.
	(cp_parser_simple_type_specifier): Handle decltype as scope.
	(cp_parser_base_specifier): Allow decltype.
	(cp_parser_base_clause): Don't crash on null base.
	* parser.h (CPP_KEYWORD, CPP_TEMPLATE_ID): Move to c-common.h.
	(CPP_NESTED_NAME_SPECIFIER, N_CP_TTYPES): Likewise.
gcc/c-family/
	* c-common.h (CPP_KEYWORD, CPP_TEMPLATE_ID): Move from cp/parser.h.
	(CPP_NESTED_NAME_SPECIFIER, N_CP_TTYPES): Likewise.
	(CPP_DECLTYPE): New.
	* c-common.c (c_parse_error): Handle CPP_DECLTYPE.

From-SVN: r176513
parent ff3ac0f4
2011-07-20 Jason Merrill <jason@redhat.com>
PR c++/6709 (DR 743)
PR c++/42603 (DR 950)
* c-common.h (CPP_KEYWORD, CPP_TEMPLATE_ID): Move from cp/parser.h.
(CPP_NESTED_NAME_SPECIFIER, N_CP_TTYPES): Likewise.
(CPP_DECLTYPE): New.
* c-common.c (c_parse_error): Handle CPP_DECLTYPE.
2011-07-19 Richard Guenther <rguenther@suse.de> 2011-07-19 Richard Guenther <rguenther@suse.de>
* c-common.c (pointer_int_sum): Use fold_build_pointer_plus. * c-common.c (pointer_int_sum): Use fold_build_pointer_plus.
......
...@@ -8329,6 +8329,8 @@ c_parse_error (const char *gmsgid, enum cpp_ttype token_type, ...@@ -8329,6 +8329,8 @@ c_parse_error (const char *gmsgid, enum cpp_ttype token_type,
message = catenate_messages (gmsgid, " before %<#pragma%>"); message = catenate_messages (gmsgid, " before %<#pragma%>");
else if (token_type == CPP_PRAGMA_EOL) else if (token_type == CPP_PRAGMA_EOL)
message = catenate_messages (gmsgid, " before end of line"); message = catenate_messages (gmsgid, " before end of line");
else if (token_type == CPP_DECLTYPE)
message = catenate_messages (gmsgid, " before %<decltype%>");
else if (token_type < N_TTYPES) else if (token_type < N_TTYPES)
{ {
message = catenate_messages (gmsgid, " before %qs token"); message = catenate_messages (gmsgid, " before %qs token");
......
...@@ -320,6 +320,30 @@ struct c_common_resword ...@@ -320,6 +320,30 @@ struct c_common_resword
const unsigned int disable : 16; const unsigned int disable : 16;
}; };
/* Extra cpp_ttype values for C++. */
/* A token type for keywords, as opposed to ordinary identifiers. */
#define CPP_KEYWORD ((enum cpp_ttype) (N_TTYPES + 1))
/* A token type for template-ids. If a template-id is processed while
parsing tentatively, it is replaced with a CPP_TEMPLATE_ID token;
the value of the CPP_TEMPLATE_ID is whatever was returned by
cp_parser_template_id. */
#define CPP_TEMPLATE_ID ((enum cpp_ttype) (CPP_KEYWORD + 1))
/* A token type for nested-name-specifiers. If a
nested-name-specifier is processed while parsing tentatively, it is
replaced with a CPP_NESTED_NAME_SPECIFIER token; the value of the
CPP_NESTED_NAME_SPECIFIER is whatever was returned by
cp_parser_nested_name_specifier_opt. */
#define CPP_NESTED_NAME_SPECIFIER ((enum cpp_ttype) (CPP_TEMPLATE_ID + 1))
/* A token type for pre-parsed C++0x decltype. */
#define CPP_DECLTYPE ((enum cpp_ttype) (CPP_NESTED_NAME_SPECIFIER + 1))
/* The number of token types, including C++-specific ones. */
#define N_CP_TTYPES ((int) (CPP_DECLTYPE + 1))
/* Disable mask. Keywords are disabled if (reswords[i].disable & /* Disable mask. Keywords are disabled if (reswords[i].disable &
mask) is _true_. Thus for keywords which are present in all mask) is _true_. Thus for keywords which are present in all
languages the disable field is zero. */ languages the disable field is zero. */
......
2011-07-19 Jason Merrill <jason@redhat.com> 2011-07-20 Jason Merrill <jason@redhat.com>
PR c++/6709 (DR 743)
PR c++/42603 (DR 950)
* parser.c (token_is_decltype, cp_lexer_next_token_is_decltype): New.
(cp_parser_nested_name_specifier_opt): Allow decltype.
(cp_parser_qualifying_entity): Likewise.
(cp_parser_decltype): Replace source tokens with CPP_DECLTYPE.
(cp_parser_simple_type_specifier): Handle decltype as scope.
(cp_parser_base_specifier): Allow decltype.
(cp_parser_base_clause): Don't crash on null base.
* parser.h (CPP_KEYWORD, CPP_TEMPLATE_ID): Move to c-common.h.
(CPP_NESTED_NAME_SPECIFIER, N_CP_TTYPES): Likewise.
PR c++/49785 PR c++/49785
* pt.c (coerce_template_parms): Handle non-pack after pack. * pt.c (coerce_template_parms): Handle non-pack after pack.
......
...@@ -663,6 +663,24 @@ cp_lexer_next_token_is_decl_specifier_keyword (cp_lexer *lexer) ...@@ -663,6 +663,24 @@ cp_lexer_next_token_is_decl_specifier_keyword (cp_lexer *lexer)
} }
} }
/* Returns TRUE iff the token T begins a decltype type. */
static bool
token_is_decltype (cp_token *t)
{
return (t->keyword == RID_DECLTYPE
|| t->type == CPP_DECLTYPE);
}
/* Returns TRUE iff the next token begins a decltype type. */
static bool
cp_lexer_next_token_is_decltype (cp_lexer *lexer)
{
cp_token *t = cp_lexer_peek_token (lexer);
return token_is_decltype (t);
}
/* Return a pointer to the Nth token in the token stream. If N is 1, /* Return a pointer to the Nth token in the token stream. If N is 1,
then this is precisely equivalent to cp_lexer_peek_token (except then this is precisely equivalent to cp_lexer_peek_token (except
that it is not inline). One would like to disallow that case, but that it is not inline). One would like to disallow that case, but
...@@ -4313,6 +4331,9 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser, ...@@ -4313,6 +4331,9 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser,
/* A template-id can start a nested-name-specifier. */ /* A template-id can start a nested-name-specifier. */
else if (token->type == CPP_TEMPLATE_ID) else if (token->type == CPP_TEMPLATE_ID)
; ;
/* DR 743: decltype can be used in a nested-name-specifier. */
else if (token_is_decltype (token))
;
else else
{ {
/* If the next token is not an identifier, then it is /* If the next token is not an identifier, then it is
...@@ -4386,6 +4407,28 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser, ...@@ -4386,6 +4407,28 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser,
class-or-namespace-name. */ class-or-namespace-name. */
parser->scope = old_scope; parser->scope = old_scope;
parser->qualifying_scope = saved_qualifying_scope; parser->qualifying_scope = saved_qualifying_scope;
/* If the next token is a decltype, and the one after that is a
`::', then the decltype has failed to resolve to a class or
enumeration type. Give this error even when parsing
tentatively since it can't possibly be valid--and we're going
to replace it with a CPP_NESTED_NAME_SPECIFIER below, so we
won't get another chance.*/
if (cp_lexer_next_token_is (parser->lexer, CPP_DECLTYPE)
&& (cp_lexer_peek_nth_token (parser->lexer, 2)->type
== CPP_SCOPE))
{
token = cp_lexer_consume_token (parser->lexer);
error_at (token->location, "decltype evaluates to %qT, "
"which is not a class or enumeration type",
token->u.value);
parser->scope = error_mark_node;
error_p = true;
/* As below. */
success = true;
cp_lexer_consume_token (parser->lexer);
}
if (cp_parser_uncommitted_to_tentative_parse_p (parser)) if (cp_parser_uncommitted_to_tentative_parse_p (parser))
break; break;
/* If the next token is an identifier, and the one after /* If the next token is an identifier, and the one after
...@@ -4585,6 +4628,19 @@ cp_parser_qualifying_entity (cp_parser *parser, ...@@ -4585,6 +4628,19 @@ cp_parser_qualifying_entity (cp_parser *parser,
bool only_class_p; bool only_class_p;
bool successful_parse_p; bool successful_parse_p;
/* DR 743: decltype can appear in a nested-name-specifier. */
if (cp_lexer_next_token_is_decltype (parser->lexer))
{
scope = cp_parser_decltype (parser);
if (TREE_CODE (scope) != ENUMERAL_TYPE
&& !MAYBE_CLASS_TYPE_P (scope))
{
cp_parser_simulate_error (parser);
return error_mark_node;
}
return TYPE_NAME (scope);
}
/* Before we try to parse the class-name, we must save away the /* Before we try to parse the class-name, we must save away the
current PARSER->SCOPE since cp_parser_class_name will destroy current PARSER->SCOPE since cp_parser_class_name will destroy
it. */ it. */
...@@ -10197,6 +10253,14 @@ cp_parser_decltype (cp_parser *parser) ...@@ -10197,6 +10253,14 @@ cp_parser_decltype (cp_parser *parser)
bool saved_integral_constant_expression_p; bool saved_integral_constant_expression_p;
bool saved_non_integral_constant_expression_p; bool saved_non_integral_constant_expression_p;
cp_token *id_expr_start_token; cp_token *id_expr_start_token;
cp_token *start_token = cp_lexer_peek_token (parser->lexer);
if (start_token->type == CPP_DECLTYPE)
{
/* Already parsed. */
cp_lexer_consume_token (parser->lexer);
return start_token->u.value;
}
/* Look for the `decltype' token. */ /* Look for the `decltype' token. */
if (!cp_parser_require_keyword (parser, RID_DECLTYPE, RT_DECLTYPE)) if (!cp_parser_require_keyword (parser, RID_DECLTYPE, RT_DECLTYPE))
...@@ -10350,14 +10414,6 @@ cp_parser_decltype (cp_parser *parser) ...@@ -10350,14 +10414,6 @@ cp_parser_decltype (cp_parser *parser)
parser->non_integral_constant_expression_p parser->non_integral_constant_expression_p
= saved_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 `)'. */ /* Parse to the closing `)'. */
if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN)) if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN))
{ {
...@@ -10366,8 +10422,17 @@ cp_parser_decltype (cp_parser *parser) ...@@ -10366,8 +10422,17 @@ cp_parser_decltype (cp_parser *parser)
return error_mark_node; return error_mark_node;
} }
return finish_decltype_type (expr, id_expression_or_member_access_p, expr = finish_decltype_type (expr, id_expression_or_member_access_p,
tf_warning_or_error); tf_warning_or_error);
/* Replace the decltype with a CPP_DECLTYPE so we don't need to parse
it again. */
start_token->type = CPP_DECLTYPE;
start_token->u.value = expr;
start_token->keyword = RID_MAX;
cp_lexer_purge_tokens_after (parser->lexer, start_token);
return expr;
} }
/* Special member functions [gram.special] */ /* Special member functions [gram.special] */
...@@ -12679,15 +12744,13 @@ cp_parser_simple_type_specifier (cp_parser* parser, ...@@ -12679,15 +12744,13 @@ cp_parser_simple_type_specifier (cp_parser* parser,
break; break;
case RID_DECLTYPE: case RID_DECLTYPE:
/* Parse the `decltype' type. */ /* Since DR 743, decltype can either be a simple-type-specifier by
type = cp_parser_decltype (parser); itself or begin a nested-name-specifier. Parsing it will replace
it with a CPP_DECLTYPE, so just rewind and let the CPP_DECLTYPE
if (decl_specs) handling below decide what to do. */
cp_parser_set_decl_spec_type (decl_specs, type, cp_parser_decltype (parser);
token->location, cp_lexer_set_token_position (parser->lexer, token);
/*user_defined_p=*/true); break;
return type;
case RID_TYPEOF: case RID_TYPEOF:
/* Consume the `typeof' token. */ /* Consume the `typeof' token. */
...@@ -12719,6 +12782,20 @@ cp_parser_simple_type_specifier (cp_parser* parser, ...@@ -12719,6 +12782,20 @@ cp_parser_simple_type_specifier (cp_parser* parser,
break; break;
} }
/* If token is an already-parsed decltype not followed by ::,
it's a simple-type-specifier. */
if (token->type == CPP_DECLTYPE
&& cp_lexer_peek_nth_token (parser->lexer, 2)->type != CPP_SCOPE)
{
type = token->u.value;
if (decl_specs)
cp_parser_set_decl_spec_type (decl_specs, type,
token->location,
/*user_defined_p=*/true);
cp_lexer_consume_token (parser->lexer);
return type;
}
/* If the type-specifier was for a built-in type, we're done. */ /* If the type-specifier was for a built-in type, we're done. */
if (type) if (type)
{ {
...@@ -18232,12 +18309,11 @@ cp_parser_base_clause (cp_parser* parser) ...@@ -18232,12 +18309,11 @@ cp_parser_base_clause (cp_parser* parser)
} }
/* Add BASE to the front of the list. */ /* Add BASE to the front of the list. */
if (base != error_mark_node) if (base && base != error_mark_node)
{ {
if (pack_expansion_p) if (pack_expansion_p)
/* Make this a pack expansion type. */ /* Make this a pack expansion type. */
TREE_VALUE (base) = make_pack_expansion (TREE_VALUE (base)); TREE_VALUE (base) = make_pack_expansion (TREE_VALUE (base));
if (!check_for_bare_parameter_packs (TREE_VALUE (base))) if (!check_for_bare_parameter_packs (TREE_VALUE (base)))
{ {
...@@ -18379,19 +18455,27 @@ cp_parser_base_specifier (cp_parser* parser) ...@@ -18379,19 +18455,27 @@ cp_parser_base_specifier (cp_parser* parser)
class_scope_p = (parser->scope && TYPE_P (parser->scope)); class_scope_p = (parser->scope && TYPE_P (parser->scope));
template_p = class_scope_p && cp_parser_optional_template_keyword (parser); template_p = class_scope_p && cp_parser_optional_template_keyword (parser);
/* Finally, look for the class-name. */ if (!parser->scope
type = cp_parser_class_name (parser, && cp_lexer_next_token_is_decltype (parser->lexer))
class_scope_p, /* DR 950 allows decltype as a base-specifier. */
template_p, type = cp_parser_decltype (parser);
typename_type, else
/*check_dependency_p=*/true, {
/*class_head_p=*/false, /* Otherwise, look for the class-name. */
/*is_declaration=*/true); type = cp_parser_class_name (parser,
class_scope_p,
template_p,
typename_type,
/*check_dependency_p=*/true,
/*class_head_p=*/false,
/*is_declaration=*/true);
type = TREE_TYPE (type);
}
if (type == error_mark_node) if (type == error_mark_node)
return error_mark_node; return error_mark_node;
return finish_base_specifier (TREE_TYPE (type), access, virtual_p); return finish_base_specifier (type, access, virtual_p);
} }
/* Exception handling [gram.exception] */ /* Exception handling [gram.exception] */
......
...@@ -23,25 +23,6 @@ along with GCC; see the file COPYING3. If not see ...@@ -23,25 +23,6 @@ along with GCC; see the file COPYING3. If not see
#include "tree.h" #include "tree.h"
#include "c-family/c-pragma.h" #include "c-family/c-pragma.h"
/* A token type for keywords, as opposed to ordinary identifiers. */
#define CPP_KEYWORD ((enum cpp_ttype) (N_TTYPES + 1))
/* A token type for template-ids. If a template-id is processed while
parsing tentatively, it is replaced with a CPP_TEMPLATE_ID token;
the value of the CPP_TEMPLATE_ID is whatever was returned by
cp_parser_template_id. */
#define CPP_TEMPLATE_ID ((enum cpp_ttype) (CPP_KEYWORD + 1))
/* A token type for nested-name-specifiers. If a
nested-name-specifier is processed while parsing tentatively, it is
replaced with a CPP_NESTED_NAME_SPECIFIER token; the value of the
CPP_NESTED_NAME_SPECIFIER is whatever was returned by
cp_parser_nested_name_specifier_opt. */
#define CPP_NESTED_NAME_SPECIFIER ((enum cpp_ttype) (CPP_TEMPLATE_ID + 1))
/* The number of token types, including C++-specific ones. */
#define N_CP_TTYPES ((int) (CPP_NESTED_NAME_SPECIFIER + 1))
/* A token's value and its associated deferred access checks and /* A token's value and its associated deferred access checks and
qualifying scope. */ qualifying scope. */
......
2011-07-19 Jason Merrill <jason@redhat.com>
PR c++/6709 (DR 743)
PR c++/42603 (DR 950)
* g++.dg/cpp0x/decltype21.C: New.
2011-07-20 Richard Guenther <rguenther@suse.de> 2011-07-20 Richard Guenther <rguenther@suse.de>
PR middle-end/18908 PR middle-end/18908
......
// PR c++/6709 (DR 743)
// PR c++/42603 (DR 950)
// { dg-options -std=c++0x }
template <class T>
T make();
struct p { typedef int t; };
struct c : decltype(make<p>()) {};
decltype(make<p>())::t t;
int f();
decltype(f())::t t2; // { dg-error "not a class" }
struct D: decltype(f()) { }; // { dg-error "not a class" }
// { dg-prune-output "expected initializer" }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment