diff mbox

C++ PATCH to fix a couple of ice-on-invalid with incomplete type (PR c++/79420, c++/79463)

Message ID 20170214164024.GX13736@redhat.com
State New
Headers show

Commit Message

Marek Polacek Feb. 14, 2017, 4:40 p.m. UTC
In both these PRs the problem is the same: we have a non-dependent incomplete
postfix expression in a template, and since r245223 we treat it as dependent
(with a pedwarn), and erase its type.  For OVERLOADs this is bad because we'll hit
this in tsubst_copy:
    case OVERLOAD:
      /* An OVERLOAD will always be a non-dependent overload set; an
         overload set from function scope will just be represented with an
         IDENTIFIER_NODE, and from class scope with a BASELINK.  */
      gcc_assert (!uses_template_parms (t)); 

and for VAR_DECLs it's bad because the subsequent code cannot cope with its
null type.  Jason suggested to only clobber EXPR_P trees and said that these
could stay dependent.  But only resetting the type for EXPR_Ps would mean that
we'd print the incomplete type diagnostics twice, so I decided to do this
instead.  It's all invalid code, so it doesn't seem to be a problem to skip the
dependent_p = true; line and resetting the scope.

Bootstrapped/regtested on x86_64-linux, ok for trunk?

2017-02-14  Marek Polacek  <polacek@redhat.com>

	PR c++/79420
	PR c++/79463
	* parser.c (cp_parser_postfix_dot_deref_expression): Avoid
	clobbering if the postfix expression isn't an EXPR_P.

	* g++.dg/cpp1y/pr79463.C: New.
	* g++.dg/template/incomplete10.C: New.
	* g++.dg/template/incomplete9.C: New.


	Marek

Comments

Jason Merrill Feb. 14, 2017, 5:14 p.m. UTC | #1
OK.

On Tue, Feb 14, 2017 at 11:40 AM, Marek Polacek <polacek@redhat.com> wrote:
> In both these PRs the problem is the same: we have a non-dependent incomplete
> postfix expression in a template, and since r245223 we treat it as dependent
> (with a pedwarn), and erase its type.  For OVERLOADs this is bad because we'll hit
> this in tsubst_copy:
>     case OVERLOAD:
>       /* An OVERLOAD will always be a non-dependent overload set; an
>          overload set from function scope will just be represented with an
>          IDENTIFIER_NODE, and from class scope with a BASELINK.  */
>       gcc_assert (!uses_template_parms (t));
>
> and for VAR_DECLs it's bad because the subsequent code cannot cope with its
> null type.  Jason suggested to only clobber EXPR_P trees and said that these
> could stay dependent.  But only resetting the type for EXPR_Ps would mean that
> we'd print the incomplete type diagnostics twice, so I decided to do this
> instead.  It's all invalid code, so it doesn't seem to be a problem to skip the
> dependent_p = true; line and resetting the scope.
>
> Bootstrapped/regtested on x86_64-linux, ok for trunk?
>
> 2017-02-14  Marek Polacek  <polacek@redhat.com>
>
>         PR c++/79420
>         PR c++/79463
>         * parser.c (cp_parser_postfix_dot_deref_expression): Avoid
>         clobbering if the postfix expression isn't an EXPR_P.
>
>         * g++.dg/cpp1y/pr79463.C: New.
>         * g++.dg/template/incomplete10.C: New.
>         * g++.dg/template/incomplete9.C: New.
>
> diff --git gcc/cp/parser.c gcc/cp/parser.c
> index ce45bba..ccafefd 100644
> --- gcc/cp/parser.c
> +++ gcc/cp/parser.c
> @@ -7331,7 +7331,9 @@ cp_parser_postfix_dot_deref_expression (cp_parser *parser,
>                    (scope, current_class_type))))
>         {
>           scope = complete_type (scope);
> -         if (!COMPLETE_TYPE_P (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).  */
> diff --git gcc/testsuite/g++.dg/cpp1y/pr79463.C gcc/testsuite/g++.dg/cpp1y/pr79463.C
> index e69de29..fdf668b 100644
> --- gcc/testsuite/g++.dg/cpp1y/pr79463.C
> +++ gcc/testsuite/g++.dg/cpp1y/pr79463.C
> @@ -0,0 +1,7 @@
> +// PR c++/79463
> +// { dg-options "-g" }
> +// { dg-do compile { target c++14 } }
> +
> +struct A;
> +extern A a; // { dg-error "'a' has incomplete type" }
> +template < int > int f = a.x;
> diff --git gcc/testsuite/g++.dg/template/incomplete10.C gcc/testsuite/g++.dg/template/incomplete10.C
> index e69de29..f0b406d 100644
> --- gcc/testsuite/g++.dg/template/incomplete10.C
> +++ gcc/testsuite/g++.dg/template/incomplete10.C
> @@ -0,0 +1,13 @@
> +// PR c++/79420
> +
> +struct S;
> +extern S s; // { dg-error "'s' has incomplete type" }
> +template<int> int f ()
> +{
> +  return s.x;
> +}
> +
> +void g ()
> +{
> +  f<0> ();
> +}
> diff --git gcc/testsuite/g++.dg/template/incomplete9.C gcc/testsuite/g++.dg/template/incomplete9.C
> index e69de29..9e03232 100644
> --- gcc/testsuite/g++.dg/template/incomplete9.C
> +++ gcc/testsuite/g++.dg/template/incomplete9.C
> @@ -0,0 +1,11 @@
> +// PR c++/79420
> +
> +template<int> int f ()
> +{
> +  return f.x; // { dg-error "overloaded function with no contextual type information" }
> +}
> +
> +void g ()
> +{
> +  f<0> ();
> +}
>
>         Marek
diff mbox

Patch

diff --git gcc/cp/parser.c gcc/cp/parser.c
index ce45bba..ccafefd 100644
--- gcc/cp/parser.c
+++ gcc/cp/parser.c
@@ -7331,7 +7331,9 @@  cp_parser_postfix_dot_deref_expression (cp_parser *parser,
 		   (scope, current_class_type))))
 	{
 	  scope = complete_type (scope);
-	  if (!COMPLETE_TYPE_P (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).  */
diff --git gcc/testsuite/g++.dg/cpp1y/pr79463.C gcc/testsuite/g++.dg/cpp1y/pr79463.C
index e69de29..fdf668b 100644
--- gcc/testsuite/g++.dg/cpp1y/pr79463.C
+++ gcc/testsuite/g++.dg/cpp1y/pr79463.C
@@ -0,0 +1,7 @@ 
+// PR c++/79463
+// { dg-options "-g" }
+// { dg-do compile { target c++14 } }
+
+struct A;
+extern A a; // { dg-error "'a' has incomplete type" }
+template < int > int f = a.x;
diff --git gcc/testsuite/g++.dg/template/incomplete10.C gcc/testsuite/g++.dg/template/incomplete10.C
index e69de29..f0b406d 100644
--- gcc/testsuite/g++.dg/template/incomplete10.C
+++ gcc/testsuite/g++.dg/template/incomplete10.C
@@ -0,0 +1,13 @@ 
+// PR c++/79420
+
+struct S;
+extern S s; // { dg-error "'s' has incomplete type" }
+template<int> int f ()
+{
+  return s.x;
+}
+
+void g ()
+{
+  f<0> ();
+}
diff --git gcc/testsuite/g++.dg/template/incomplete9.C gcc/testsuite/g++.dg/template/incomplete9.C
index e69de29..9e03232 100644
--- gcc/testsuite/g++.dg/template/incomplete9.C
+++ gcc/testsuite/g++.dg/template/incomplete9.C
@@ -0,0 +1,11 @@ 
+// PR c++/79420
+
+template<int> int f ()
+{
+  return f.x; // { dg-error "overloaded function with no contextual type information" }
+}
+
+void g ()
+{
+  f<0> ();
+}