diff mbox series

[C++] Fix ICEs due to cp_parser_postfix_dot_deref_expression workaround (PR c++/84082, take 2)

Message ID 20180206202857.GC5867@tucnak
State New
Headers show
Series [C++] Fix ICEs due to cp_parser_postfix_dot_deref_expression workaround (PR c++/84082, take 2) | expand

Commit Message

Jakub Jelinek Feb. 6, 2018, 8:28 p.m. UTC
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  <jakub@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.



	Jakub

Comments

Jason Merrill Feb. 6, 2018, 10:45 p.m. UTC | #1
On Tue, Feb 6, 2018 at 3:28 PM, Jakub Jelinek <jakub@redhat.com> wrote:
> 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.
>
> +    case NON_LVALUE_EXPR:
> +      if (location_wrapper_p (*postfix_expression))

I don't think we need this test, as NON_LVALUE_EXPR should only appear
as a location wrapper.  OK with it removed.

Jason
diff mbox series

Patch

--- 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" }