Commit 5904d9d9 by Alexandre Oliva Committed by Alexandre Oliva

[PR c++/84789] do not fail to resolve typename into template-independent

Although resolve_typename_type always takes a template-dependent
type-id, and it usually resolves it to another template-dependent
type-id, it is not correct to require the latter: in declarators,
template-dependent scopes may turn out to name template-independent
types, as in the pr84789-2.C and pr84789-3.C testcases.

The ill-formed testcase pr84789.C trips the same too-strict assert,
and also gets fixed by removing the assertion on the simplified scope.
However, whereas when the dependent type cannot be resolved, we get an
error that suggests 'typename' is missing:

pr84789.C:12:3: error: need ‘typename’ before ‘typename B<T>::A::I::I’
because ‘typename B<T>::A::I’ is a dependent scope
   B<T>::A::I::I i;
   ^~~~

when it can, we got errors that did not point at that possibility,
which may be confusing:

pr84789.C:9:15: error: ‘A::I’ {aka ‘int’} is not a class type
   B<T>::A::I::I i; // { dg-error "typename" }
               ^
pr84789.C:9:15: error: ‘I’ in ‘A::I’ {aka ‘int’} does not name a type

Changing the parser diagnostic code that reports an invalid type name
so that it does not attempt to reparse the name as a declarator gets
us the superior diagnostic of a missing 'typename' keyword.


for  gcc/cp/ChangeLog

	PR c++/84789
	* pt.c (resolve_typename_type): Drop assert that stopped
	simplification to template-independent types.  Add assert to
	verify the initial scope is template dependent.
	* parser.c (cp_parser_parse_and_diagnose_invalid_type_name):
	Reparse the id expression as a type-name, not a declarator.

for  gcc/testsuite/ChangeLog

	PR c++/84789
	* g++.dg/template/pr84789.C: New.
	* g++.dg/template/pr84789-2.C: New.
	* g++.dg/template/pr84789-3.C: New.
	* g++.dg/parse/dtor11.C: Accept alternate error message.

From-SVN: r258792
parent 3ec16e36
2018-03-22 Alexandre Oliva <aoliva@redhat.com>
PR c++/84789
* pt.c (resolve_typename_type): Drop assert that stopped
simplification to template-independent types. Add assert to
verify the initial scope is template dependent.
* parser.c (cp_parser_parse_and_diagnose_invalid_type_name):
Reparse the id expression as a type-name, not a declarator.
PR c++/84729
* init.c (build_vec_init): Error at parenthesized array init.
......
......@@ -3455,7 +3455,7 @@ cp_parser_parse_and_diagnose_invalid_type_name (cp_parser *parser)
/*template_keyword_p=*/false,
/*check_dependency_p=*/true,
/*template_p=*/NULL,
/*declarator_p=*/true,
/*declarator_p=*/false,
/*optional_p=*/false);
/* If the next token is a (, this is a function with no explicit return
type, i.e. constructor, destructor or conversion op. */
......@@ -25249,6 +25249,9 @@ resolve_typename_type (tree type, bool only_current_p)
gcc_assert (TREE_CODE (type) == TYPENAME_TYPE);
scope = TYPE_CONTEXT (type);
/* We shouldn't have built a TYPENAME_TYPE with a non-dependent scope. */
gcc_checking_assert (uses_template_parms (scope));
/* Usually the non-qualified identifier of a TYPENAME_TYPE is
TYPE_IDENTIFIER (type). But when 'type' is a typedef variant of
a TYPENAME_TYPE node, then TYPE_NAME (type) is set to the TYPE_DECL representing
......@@ -25285,8 +25288,6 @@ resolve_typename_type (tree type, bool only_current_p)
/* scope is either the template itself or a compatible instantiation
like X<T>, so look up the name in the original template. */
scope = CLASSTYPE_PRIMARY_TEMPLATE_TYPE (scope);
/* We shouldn't have built a TYPENAME_TYPE with a non-dependent scope. */
gcc_checking_assert (uses_template_parms (scope));
/* If scope has no fields, it can't be a current instantiation. Check this
before currently_open_class to avoid infinite recursion (71515). */
if (!TYPE_FIELDS (scope))
......
2018-03-22 Alexandre Oliva <aoliva@redhat.com>
PR c++/84789
* g++.dg/template/pr84789.C: New.
* g++.dg/template/pr84789-2.C: New.
* g++.dg/template/pr84789-3.C: New.
* g++.dg/parse/dtor11.C: Accept alternate error message.
PR c++/84729
* g++.dg/pr84729.C: New.
* g++.old-deja/g++.ext/arrnew2.C: Require error.
......
......@@ -8,5 +8,5 @@ struct A
struct B
{
A::~B B(); // { dg-error "as member of" }
A::~B B(); // { dg-error "as member of|as a type" }
};
// { dg-do compile }
struct K {
struct L {
static double j;
};
};
template <typename T>
struct M {
struct N {
static int i;
};
};
template <typename T>
struct O {
typedef M<T> P;
typedef K Q;
};
template <typename T>
int O<T>::P::N::i = 42; // This is obfuscated, but apparently ok.
template <typename T>
double O<T>::Q::L::j = 42.0; // { dg-error "non-template" }
// { dg-do compile }
struct A
{
static int i;
};
struct B
{
typedef ::A A;
};
int B::A::i = 0;
struct K
{
struct L
{
template <typename T>
static void f(T);
};
};
template <typename T>
struct O
{
typedef K Q;
};
template <typename T>
void O<T>::Q::L::f(T)
{
}
// { dg-do compile }
struct A
{
typedef int I;
};
template<typename> struct B : A {};
template<typename T> struct C : B<T>
{
B<T>::A::I::I i; // { dg-error "typename" }
};
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment