From 2e6a4932c6fc77dc57413586a49ef3584cde4967 Mon Sep 17 00:00:00 2001 From: jason Date: Fri, 13 Nov 2009 14:40:13 +0000 Subject: [PATCH] PR c++/11987 * parser.c (cp_parser_direct_declarator): Give helpful error about trying to define member of a dependent typedef. * pt.c (resolve_typename_type): Don't resolve a typedef typename. * tree.c (typedef_variant_p): New. * cp-tree.h: Declare it. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@154149 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/cp/ChangeLog | 9 +++++++++ gcc/cp/cp-tree.h | 1 + gcc/cp/parser.c | 15 +++++++++++---- gcc/cp/pt.c | 3 +++ gcc/cp/tree.c | 8 ++++++++ gcc/testsuite/ChangeLog | 6 ++++++ gcc/testsuite/g++.dg/parse/typename11.C | 16 ++++++++++++++++ gcc/testsuite/g++.dg/template/crash48.C | 2 +- 8 files changed, 55 insertions(+), 5 deletions(-) create mode 100644 gcc/testsuite/g++.dg/parse/typename11.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 988b6023dae..1ffa86a78e9 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,12 @@ +2009-11-13 Jason Merrill + + PR c++/11987 + * parser.c (cp_parser_direct_declarator): Give helpful error about + trying to define member of a dependent typedef. + * pt.c (resolve_typename_type): Don't resolve a typedef typename. + * tree.c (typedef_variant_p): New. + * cp-tree.h: Declare it. + 2009-11-12 Jason Merrill PR c++/27078 diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index f66a00948ae..a71dc739cfa 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -5098,6 +5098,7 @@ extern bool type_has_nontrivial_copy_init (const_tree); extern bool class_tmpl_impl_spec_p (const_tree); extern int zero_init_p (const_tree); extern tree strip_typedefs (tree); +extern bool typedef_variant_p (tree); extern tree copy_binfo (tree, tree, tree, tree *, int); extern int member_p (const_tree); diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index f77ec55251f..05def24ce23 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -14191,10 +14191,17 @@ cp_parser_direct_declarator (cp_parser* parser, /*only_current_p=*/false); /* If that failed, the declarator is invalid. */ if (TREE_CODE (type) == TYPENAME_TYPE) - error_at (declarator_id_start_token->location, - "%<%T::%E%> is not a type", - TYPE_CONTEXT (qualifying_scope), - TYPE_IDENTIFIER (qualifying_scope)); + { + if (typedef_variant_p (type)) + error_at (declarator_id_start_token->location, + "cannot define member of dependent typedef " + "%qT", type); + else + error_at (declarator_id_start_token->location, + "%<%T::%E%> is not a type", + TYPE_CONTEXT (qualifying_scope), + TYPE_IDENTIFIER (qualifying_scope)); + } qualifying_scope = type; } diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 0e688bf406a..85d9fff7b56 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -17689,6 +17689,9 @@ resolve_typename_type (tree type, bool only_current_p) to look inside it. */ if (only_current_p && !currently_open_class (scope)) return type; + /* If this is a typedef, we don't want to look inside (c++/11987). */ + if (typedef_variant_p (type)) + return type; /* If SCOPE isn't the template itself, it will not have a valid TYPE_FIELDS list. */ if (same_type_p (scope, CLASSTYPE_PRIMARY_TEMPLATE_TYPE (scope))) diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index 9dae1843616..f9e1cd707a9 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -1067,6 +1067,14 @@ strip_typedefs (tree t) return cp_build_qualified_type (result, cp_type_quals (t)); } +/* Returns true iff TYPE is a type variant created for a typedef. */ + +bool +typedef_variant_p (tree type) +{ + return is_typedef_decl (TYPE_NAME (type)); +} + /* Makes a copy of BINFO and TYPE, which is to be inherited into a graph dominated by T. If BINFO is NULL, TYPE is a dependent base, diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 3194252e449..20f4686bf7e 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2009-11-13 Jason Merrill + + PR c++/11987 + * g++.dg/parse/typename11.C: New. + * g++.dg/template/crash48.C: Adjust. + 2009-11-13 Uros Bizjak PR testsuite/42001 diff --git a/gcc/testsuite/g++.dg/parse/typename11.C b/gcc/testsuite/g++.dg/parse/typename11.C new file mode 100644 index 00000000000..a79e6d88708 --- /dev/null +++ b/gcc/testsuite/g++.dg/parse/typename11.C @@ -0,0 +1,16 @@ +// PR c++/11987 + +template struct X { + struct I { I(); }; +}; + +template struct Y : X { + typedef typename X::I I; +}; + +// note: I is nested type in X, not Y! +template +Y::I::I () {} // { dg-error "dependent typedef" } +// { dg-error "no type|dependent type" "" { target *-*-* } 13 } + +template struct Y<1>; diff --git a/gcc/testsuite/g++.dg/template/crash48.C b/gcc/testsuite/g++.dg/template/crash48.C index deb944685bd..6aa3aa3ed26 100644 --- a/gcc/testsuite/g++.dg/template/crash48.C +++ b/gcc/testsuite/g++.dg/template/crash48.C @@ -7,4 +7,4 @@ template struct A typedef typename T::X X; }; -template A::X::X() {} // { dg-error "no type|invalid use|not a type" } +template A::X::X() {} // { dg-error "no type|invalid use|not a type|dependent" } -- 2.11.0