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

Reply via email to