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 <pola...@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