* [C++ Patch/RFC] PR 65091
@ 2015-06-11 10:54 Paolo Carlini
2015-06-17 23:38 ` Paolo Carlini
0 siblings, 1 reply; 2+ messages in thread
From: Paolo Carlini @ 2015-06-11 10:54 UTC (permalink / raw)
To: gcc-patches; +Cc: Jason Merrill
[-- Attachment #1: Type: text/plain, Size: 1549 bytes --]
Hi,
I have been looking into this issue, which should be rather easy to
solve: the problem seems that in a template we are mishandling ~ as a
bitwise complement operator (vs destructor introducer). We end up here
in cp_parser_unqualified_id:
type_decl
= cp_parser_class_name (parser,
/*typename_keyword_p=*/false,
/*template_keyword_p=*/false,
typename_type,
/*check_dependency=*/false,
/*class_head_p=*/false,
declarator_p);
if (processing_template_decl
&& ! 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. */
type_decl = cp_parser_identifier (parser);
if (type_decl != error_mark_node)
type_decl = build_nt (BIT_NOT_EXPR, type_decl);
return type_decl;
}
and apparently the cp_parser_id_expression call at the beginning of
cp_parser_decltype_expr succeeds with a BIT_NOT_EXPR with an identifier
as argument. But that means that we are looking into the ~ class-name
production, which obviously doesn't make sense as decltype expression.
If we keep on working in cp_parser_decltype_expr we end up calling
cp_parser_expression (the same we do for things like !x or ++x) and
everything goes well. Anyway, draft tested on x86_64-linux.
Thanks!
Paolo.
//////////////////////////////
[-- Attachment #2: patch_65091 --]
[-- Type: text/plain, Size: 1114 bytes --]
Index: cp/parser.c
===================================================================
--- cp/parser.c (revision 224331)
+++ cp/parser.c (working copy)
@@ -12252,6 +12252,12 @@ cp_parser_decltype_expr (cp_parser *parser,
/*declarator_p=*/false,
/*optional_p=*/false);
+ /* The production ~ class-name is not ok here, keep looking, it's probably
+ a complement expression (c++/65091). */
+ if (TREE_CODE (expr) == BIT_NOT_EXPR
+ && identifier_p (TREE_OPERAND (expr, 0)))
+ expr = error_mark_node;
+
if (!cp_parser_error_occurred (parser) && expr != error_mark_node)
{
bool non_integral_constant_expression_p = false;
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); }
^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: [C++ Patch/RFC] PR 65091
2015-06-11 10:54 [C++ Patch/RFC] PR 65091 Paolo Carlini
@ 2015-06-17 23:38 ` Paolo Carlini
0 siblings, 0 replies; 2+ messages in thread
From: Paolo Carlini @ 2015-06-17 23:38 UTC (permalink / raw)
To: gcc-patches; +Cc: Jason Merrill
[-- Attachment #1: Type: text/plain, Size: 419 bytes --]
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.
//////////////////////
[-- Attachment #2: patch_65091_2 --]
[-- Type: text/plain, Size: 8456 bytes --]
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); }
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2015-06-17 22:58 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-06-11 10:54 [C++ Patch/RFC] PR 65091 Paolo Carlini
2015-06-17 23:38 ` Paolo Carlini
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).