We entered type_dependent_object_expression_p considering an IDENTIFIER_NODE, which is always dependent. But because there's a global type with the same name, the identifier had global_type_node as its type, which isn't recognized as a dependent type. Fixed by handling IDENTIFIER_NODE directly.
Tested x86_64-pc-linux-gnu, applying to trunk.
commit d2b4bcf0dc04ea3ab7909d55bcc8a7d4703b34ca Author: Jason Merrill <ja...@redhat.com> Date: Fri Feb 17 14:00:10 2017 -0500 PR c++/78690 - ICE with using and global type with same name * pt.c (type_dependent_object_expression_p): True for IDENTIFIER_NODE. diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 04479d4..9e6ce8d 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -23932,6 +23932,10 @@ type_dependent_expression_p (tree expression) bool type_dependent_object_expression_p (tree object) { + /* An IDENTIFIER_NODE can sometimes have a TREE_TYPE, but it's still + dependent. */ + if (TREE_CODE (object) == IDENTIFIER_NODE) + return true; tree scope = TREE_TYPE (object); return (!scope || dependent_scope_p (scope)); } diff --git a/gcc/testsuite/g++.dg/template/dependent-scope1.C b/gcc/testsuite/g++.dg/template/dependent-scope1.C new file mode 100644 index 0000000..a5c18c4 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/dependent-scope1.C @@ -0,0 +1,17 @@ +// PR c++/78690 + +struct C; + +template <typename T> +struct A +{ + struct C { static void bar (); }; +}; + +template <typename T> +struct B +{ + using A<T>::C; + void + foo () { C.bar (); } +};