On Fri, Feb 02, 2018 at 03:13:21PM -0500, Jason Merrill wrote: > > Or should I change the switch body to do other kind = overrides? > > I think we want to avoid clobbering NON_LVALUE_EXPR location wrappers, too. > > This has gotten large enough that it should break out into its own function. > > OK with those changes.
So like this? Bootstrapped/regtested on x86_64-linux and i686-linux. 2018-02-06 Jakub Jelinek <ja...@redhat.com> PR c++/84082 * parser.c (cp_parser_dot_deref_incomplete): New function. (cp_parser_postfix_dot_deref_expression): Use it. * g++.dg/template/incomplete11.C: New test. * g++.dg/parse/crash67.C: Expect an incomplete type diagnostics too. --- gcc/cp/parser.c.jj 2018-01-31 19:07:35.401199026 +0100 +++ gcc/cp/parser.c 2018-02-03 19:08:37.828664789 +0100 @@ -7387,6 +7387,63 @@ cp_parser_postfix_open_square_expression return postfix_expression; } +/* A subroutine of cp_parser_postfix_dot_deref_expression. Handle dot + dereference of incomplete type, returns true if error_mark_node should + be returned from caller, otherwise adjusts *SCOPE, *POSTFIX_EXPRESSION + and *DEPENDENT_P. */ + +bool +cp_parser_dot_deref_incomplete (tree *scope, cp_expr *postfix_expression, + bool *dependent_p) +{ + /* In a template, be permissive by treating an object expression + of incomplete type as dependent (after a pedwarn). */ + diagnostic_t kind = (processing_template_decl + && MAYBE_CLASS_TYPE_P (*scope) ? DK_PEDWARN : DK_ERROR); + + switch (TREE_CODE (*postfix_expression)) + { + case CAST_EXPR: + case REINTERPRET_CAST_EXPR: + case CONST_CAST_EXPR: + case STATIC_CAST_EXPR: + case DYNAMIC_CAST_EXPR: + case IMPLICIT_CONV_EXPR: + case VIEW_CONVERT_EXPR: + kind = DK_ERROR; + break; + case NON_LVALUE_EXPR: + if (location_wrapper_p (*postfix_expression)) + kind = DK_ERROR; + break; + case OVERLOAD: + /* Don't emit any diagnostic for OVERLOADs. */ + kind = DK_IGNORED; + break; + default: + /* Avoid clobbering e.g. DECLs. */ + if (!EXPR_P (*postfix_expression)) + kind = DK_ERROR; + break; + } + + if (kind == DK_IGNORED) + return false; + + location_t exploc = location_of (*postfix_expression); + cxx_incomplete_type_diagnostic (exploc, *postfix_expression, *scope, kind); + if (!MAYBE_CLASS_TYPE_P (*scope)) + return true; + if (kind == DK_ERROR) + *scope = *postfix_expression = error_mark_node; + else if (processing_template_decl) + { + *dependent_p = true; + *scope = TREE_TYPE (*postfix_expression) = NULL_TREE; + } + return false; +} + /* A subroutine of cp_parser_postfix_expression that also gets hijacked by cp_parser_builtin_offsetof. We're looking for @@ -7451,26 +7508,9 @@ cp_parser_postfix_dot_deref_expression ( { scope = complete_type (scope); if (!COMPLETE_TYPE_P (scope) - /* Avoid clobbering e.g. OVERLOADs or DECLs. */ - && EXPR_P (postfix_expression)) - { - /* In a template, be permissive by treating an object expression - of incomplete type as dependent (after a pedwarn). */ - diagnostic_t kind = (processing_template_decl - && MAYBE_CLASS_TYPE_P (scope) - ? DK_PEDWARN - : DK_ERROR); - cxx_incomplete_type_diagnostic - (location_of (postfix_expression), - postfix_expression, scope, kind); - if (!MAYBE_CLASS_TYPE_P (scope)) - return error_mark_node; - if (processing_template_decl) - { - dependent_p = true; - scope = TREE_TYPE (postfix_expression) = NULL_TREE; - } - } + && cp_parser_dot_deref_incomplete (&scope, &postfix_expression, + &dependent_p)) + return error_mark_node; } if (!dependent_p) --- gcc/testsuite/g++.dg/template/incomplete11.C.jj 2018-02-03 17:56:10.536083614 +0100 +++ gcc/testsuite/g++.dg/template/incomplete11.C 2018-02-03 17:56:10.536083614 +0100 @@ -0,0 +1,10 @@ +// PR c++/84082 +// { dg-do compile } +// { dg-options "" } + +struct A; + +template<typename> void foo() +{ + static int a[A().operator=(A())]; // { dg-error "invalid use of incomplete type 'struct A'" } +} --- gcc/testsuite/g++.dg/parse/crash67.C.jj 2018-01-31 19:07:33.571220455 +0100 +++ gcc/testsuite/g++.dg/parse/crash67.C 2018-02-03 17:56:10.536083614 +0100 @@ -3,4 +3,4 @@ class x0; template <x1> x2() { // { dg-error "declared|type" } -x0 x3 = x3. // { dg-error "expected" } +x0 x3 = x3. // { dg-error "expected|incomplete type" } Jakub