The problem here was that finish_qualified_id_expr was throwing away the nested-name-specifier, which is necessary to avoid this error.
Tested x86_64-pc-linux-gnu, applying to trunk and 8.
commit b96ede757f83783d388623b26312a0514bfec8a6 Author: Jason Merrill <ja...@redhat.com> Date: Tue Jun 5 01:05:09 2018 +0200 PR c++/85731 - wrong error with qualified-id in template. * semantics.c (finish_qualified_id_expr): build_qualified_name for unbound names in the current class. diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index e00331a3ea4..a3426623385 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -2098,6 +2098,8 @@ finish_qualified_id_expr (tree qualifying_class, non-type template argument handling. */ if (processing_template_decl && (!currently_open_class (qualifying_class) + || TREE_CODE (expr) == IDENTIFIER_NODE + || TREE_CODE (expr) == TEMPLATE_ID_EXPR || TREE_CODE (expr) == BIT_NOT_EXPR)) expr = build_qualified_name (TREE_TYPE (expr), qualifying_class, expr, diff --git a/gcc/testsuite/g++.dg/template/qualified-id7.C b/gcc/testsuite/g++.dg/template/qualified-id7.C new file mode 100644 index 00000000000..fd952f6fbcf --- /dev/null +++ b/gcc/testsuite/g++.dg/template/qualified-id7.C @@ -0,0 +1,15 @@ +// PR c++/85731 +// { dg-do compile { target c++11 } } + + template <typename T> + struct Outer { + struct Inner; + template <int I> static void f(); + }; + + template <typename T> + struct Outer<T>::Inner { + decltype(Outer<T>::f<42>()) f(); + }; + + int main() { Outer<int>::Inner().f(); }