+2019-01-23 Marek Polacek <polacek@redhat.com>
+
+ PR c++/88757 - qualified name treated wrongly as type.
+ * parser.c (cp_parser_direct_declarator): Don't treat qualified-ids
+ in parameter-list as types if name lookup for declarator-id didn't
+ find one or more function templates.
+
2019-01-23 Jakub Jelinek <jakub@redhat.com>
PR c/44715
if (pack_expansion_p)
maybe_warn_variadic_templates ();
+
+ /* We're looking for this case in [temp.res]:
+ A qualified-id is assumed to name a type if [...]
+ - it is a decl-specifier of the decl-specifier-seq of a
+ parameter-declaration in a declarator of a function or
+ function template declaration, ... */
+ if (cxx_dialect >= cxx2a
+ && (flags & CP_PARSER_FLAGS_TYPENAME_OPTIONAL)
+ && declarator->kind == cdk_id
+ /* ...whose declarator-id is qualified. */
+ && qualifying_scope != NULL_TREE
+ && !at_class_scope_p ()
+ && cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
+ {
+ /* Now we have something like
+ template <typename T> int C::x(S::p);
+ which can be a function template declaration or a
+ variable template definition. If name lookup for
+ the declarator-id C::x finds one or more function
+ templates, assume S::p to name a type. Otherwise,
+ don't. */
+ tree decl
+ = cp_parser_lookup_name_simple (parser, unqualified_name,
+ token->location);
+ if (!is_overloaded_fn (decl))
+ flags &= ~CP_PARSER_FLAGS_TYPENAME_OPTIONAL;
+ }
}
handle_declarator:;
+2019-01-23 Marek Polacek <polacek@redhat.com>
+
+ PR c++/88757 - qualified name treated wrongly as type.
+ * g++.dg/cpp0x/dependent2.C: New test.
+ * g++.dg/cpp2a/typename10.C: Remove dg-error.
+ * g++.dg/cpp2a/typename12.C: New test.
+ * g++.dg/template/static30.C: Remove dg-error.
+
2019-01-23 Jakub Jelinek <jakub@redhat.com>
PR c/44715
--- /dev/null
+// PR c++/88757
+// { dg-do compile { target c++11 } }
+
+template <class T> struct C {
+ static int x;
+};
+template <class U> struct S {
+ static const int size = 1;
+};
+template <class T> int C<T>::x(S<T>::size);
template<typename T> extern T::type v; // #1a
//template<typename T> T::type v(typename T::value); // #1b
}
-template<typename T> T::type N2::v(T::value); // { dg-error "" }
+template<typename T> T::type N2::v(T::value);
namespace A {
inline namespace B { template<typename T> int f(typename T::foo); }
--- /dev/null
+// P0634R3
+// { dg-do compile { target c++2a } }
+
+struct W {
+ template<typename T>
+ static int fn1 (T::X);
+ template<typename T>
+ static int fn2 (T::X);
+ template<typename T>
+ static int fn2 (T::X, int);
+};
+
+template<typename T>
+int W::fn1 (T::X p) { return p; }
+
+template<typename T>
+int W::fn2 (T::X p) { return p; }
+
+template<typename T>
+int fn2 (typename T::X p) { return p; }
static const int i2;
};
-template <int N> const int A<N>::i1(A<N>::i); // { dg-error "no declaration matches" "" { target c++2a } }
+template <int N> const int A<N>::i1(A<N>::i);
template <int N> const int A<N>::i2(3, A<N>::i); // { dg-error "expression list" }