[C++ Patch/RFC] PR 65091
Paolo Carlini
paolo.carlini@oracle.com
Wed Jun 17 23:38:00 GMT 2015
Hi again,
I'm finishing testing this different idea, a much bigger patch but
arguably more neat: add a bool parameter to cp_parser_id_expression and
then to cp_parser_unqualified_id and pass down 'true' from
cp_parser_decltype_expr (this is also nicely consistent with the 'true'
we are passing to cp_parser_postfix_expression and cp_parser_expression).
What do you think?
Thanks,
Paolo.
//////////////////////
-------------- next part --------------
Index: cp/parser.c
===================================================================
--- cp/parser.c (revision 224575)
+++ cp/parser.c (working copy)
@@ -1953,9 +1953,10 @@ static bool cp_parser_translation_unit
static tree cp_parser_primary_expression
(cp_parser *, bool, bool, bool, cp_id_kind *);
static tree cp_parser_id_expression
- (cp_parser *, bool, bool, bool *, bool, bool);
+ (cp_parser *, bool, bool, bool * = NULL,
+ bool = false, bool = false, bool = false);
static tree cp_parser_unqualified_id
- (cp_parser *, bool, bool, bool, bool);
+ (cp_parser *, bool, bool, bool, bool, bool);
static tree cp_parser_nested_name_specifier_opt
(cp_parser *, bool, bool, bool, bool);
static tree cp_parser_nested_name_specifier
@@ -3095,8 +3096,7 @@ cp_parser_parse_and_diagnose_invalid_type_name (cp
/*template_keyword_p=*/false,
/*check_dependency_p=*/true,
/*template_p=*/NULL,
- /*declarator_p=*/true,
- /*optional_p=*/false);
+ /*declarator_p=*/true);
/* If the next token is a (, this is a function with no explicit return
type, i.e. constructor, destructor or conversion op. */
if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN)
@@ -4637,9 +4637,7 @@ cp_parser_primary_expression (cp_parser *parser,
= cp_parser_id_expression (parser,
/*template_keyword_p=*/false,
/*check_dependency_p=*/true,
- &template_p,
- /*declarator_p=*/false,
- /*optional_p=*/false);
+ &template_p);
if (id_expression == error_mark_node)
return error_mark_node;
id_expr_token = token;
@@ -4821,7 +4819,8 @@ cp_parser_id_expression (cp_parser *parser,
bool check_dependency_p,
bool *template_p,
bool declarator_p,
- bool optional_p)
+ bool optional_p,
+ bool decltype_p)
{
bool global_scope_p;
bool nested_name_specifier_p;
@@ -4865,7 +4864,8 @@ cp_parser_id_expression (cp_parser *parser,
unqualified_id = cp_parser_unqualified_id (parser, *template_p,
check_dependency_p,
declarator_p,
- /*optional_p=*/false);
+ /*optional_p=*/false,
+ decltype_p);
/* Restore the SAVED_SCOPE for our caller. */
parser->scope = saved_scope;
parser->object_scope = saved_object_scope;
@@ -4925,7 +4925,8 @@ cp_parser_id_expression (cp_parser *parser,
return cp_parser_unqualified_id (parser, template_keyword_p,
/*check_dependency_p=*/true,
declarator_p,
- optional_p);
+ optional_p,
+ decltype_p);
}
/* Parse an unqualified-id.
@@ -4955,7 +4956,8 @@ cp_parser_unqualified_id (cp_parser* parser,
bool template_keyword_p,
bool check_dependency_p,
bool declarator_p,
- bool optional_p)
+ bool optional_p,
+ bool decltype_p)
{
cp_token *token;
@@ -5161,7 +5163,13 @@ cp_parser_unqualified_id (cp_parser* parser,
&& ! cp_parser_parse_definitely (parser))
{
/* We couldn't find a type with this name, so just accept
- it and check for a match at instantiation time. */
+ it and check for a match at instantiation time. However
+ don't do that if we are parsing the immediate operand of
+ a decltype as an id-expression, because definitely the
+ production ~ class-name isn't ok and we want to look for
+ a complement expression (c++/65091). */
+ if (decltype_p)
+ return error_mark_node;
type_decl = cp_parser_identifier (parser);
if (type_decl != error_mark_node)
type_decl = build_nt (BIT_NOT_EXPR, type_decl);
@@ -6709,9 +6717,7 @@ cp_parser_postfix_dot_deref_expression (cp_parser
(parser,
cp_parser_optional_template_keyword (parser),
/*check_dependency_p=*/true,
- &template_p,
- /*declarator_p=*/false,
- /*optional_p=*/false));
+ &template_p));
/* In general, build a SCOPE_REF if the member name is qualified.
However, if the name was not dependent and has already been
resolved; there is no need to build the SCOPE_REF. For example;
@@ -12250,7 +12256,8 @@ cp_parser_decltype_expr (cp_parser *parser,
/*check_dependency_p=*/true,
/*template_p=*/NULL,
/*declarator_p=*/false,
- /*optional_p=*/false);
+ /*optional_p=*/false,
+ /*decltype_p=*/true);
if (!cp_parser_error_occurred (parser) && expr != error_mark_node)
{
@@ -13629,9 +13636,7 @@ cp_parser_type_parameter (cp_parser* parser, bool
= cp_parser_id_expression (parser,
/*template_keyword_p=*/false,
/*check_dependency_p=*/true,
- /*template_p=*/&is_template,
- /*declarator_p=*/false,
- /*optional_p=*/false);
+ /*template_p=*/&is_template);
if (TREE_CODE (default_argument) == TYPE_DECL)
/* If the id-expression was a template-id that refers to
a template-class, we already have the declaration here,
@@ -14273,9 +14278,7 @@ cp_parser_template_argument (cp_parser* parser)
argument = cp_parser_id_expression (parser,
/*template_keyword_p=*/false,
/*check_dependency_p=*/true,
- &template_p,
- /*declarator_p=*/false,
- /*optional_p=*/false);
+ &template_p);
/* If the next token isn't a `,' or a `>', then this argument wasn't
really finished. */
if (!cp_parser_next_token_ends_template_argument_p (parser))
@@ -16441,7 +16444,8 @@ cp_parser_using_declaration (cp_parser* parser,
/*template_keyword_p=*/false,
/*check_dependency_p=*/true,
/*declarator_p=*/true,
- /*optional_p=*/false);
+ /*optional_p=*/false,
+ /*decltype_p=*/false);
if (access_declaration_p)
{
@@ -23253,7 +23257,8 @@ cp_parser_constructor_declarator_p (cp_parser *par
/*template_keyword_p=*/false,
/*check_dependency_p=*/false,
/*declarator_p=*/true,
- /*optional_p=*/false);
+ /*optional_p=*/false,
+ /*decltype_p=*/false);
if (is_overloaded_fn (id))
id = DECL_NAME (get_first_fn (id));
if (!constructor_name_p (id, nested_name_specifier))
@@ -27823,10 +27828,7 @@ cp_parser_omp_var_list_no_open (cp_parser *parser,
token = cp_lexer_peek_token (parser->lexer);
name = cp_parser_id_expression (parser, /*template_p=*/false,
- /*check_dependency_p=*/true,
- /*template_p=*/NULL,
- /*declarator_p=*/false,
- /*optional_p=*/false);
+ /*check_dependency_p=*/true);
if (name == error_mark_node)
goto skip_comma;
@@ -28529,10 +28531,7 @@ cp_parser_omp_clause_reduction (cp_parser *parser,
saved_colon_corrects_to_scope_p = parser->colon_corrects_to_scope_p;
parser->colon_corrects_to_scope_p = false;
id = cp_parser_id_expression (parser, /*template_p=*/false,
- /*check_dependency_p=*/true,
- /*template_p=*/NULL,
- /*declarator_p=*/false,
- /*optional_p=*/false);
+ /*check_dependency_p=*/true);
parser->colon_corrects_to_scope_p = saved_colon_corrects_to_scope_p;
if (identifier_p (id))
{
@@ -32166,10 +32165,7 @@ cp_parser_omp_declare_reduction_exprs (tree fndecl
{
cp_parser_parse_tentatively (parser);
tree fn_name = cp_parser_id_expression (parser, /*template_p=*/false,
- /*check_dependency_p=*/true,
- /*template_p=*/NULL,
- /*declarator_p=*/false,
- /*optional_p=*/false);
+ /*check_dependency_p=*/true);
vec<tree, va_gc> *args;
if (fn_name == error_mark_node
|| cp_parser_error_occurred (parser)
@@ -33347,8 +33343,7 @@ cp_parser_cilk_simd_linear (cp_parser *parser, tre
break;
}
- tree var_name = cp_parser_id_expression (parser, false, true, NULL,
- false, false);
+ tree var_name = cp_parser_id_expression (parser, false, true);
tree decl = cp_parser_lookup_name_simple (parser, var_name,
token->location);
if (decl == error_mark_node)
Index: testsuite/g++.dg/cpp0x/decltype63.C
===================================================================
--- testsuite/g++.dg/cpp0x/decltype63.C (revision 0)
+++ testsuite/g++.dg/cpp0x/decltype63.C (working copy)
@@ -0,0 +1,9 @@
+// PR c++/65091
+// { dg-do compile { target c++11 } }
+
+template<typename T>
+auto foo(T x) -> decltype(~x)
+{ return ~x; }
+
+int bar()
+{ return foo(10); }
More information about the Gcc-patches
mailing list