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 <[email protected]>
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