109 lines
3.7 KiB
Diff
109 lines
3.7 KiB
Diff
|
commit 506d5f399bef7f2d8c48fd83d853c6ff7811a226
|
||
|
Author: Jason Merrill <jason@redhat.com>
|
||
|
Date: Wed Jul 26 10:39:34 2023 -0400
|
||
|
|
||
|
c++: member vs global template [PR106310]
|
||
|
|
||
|
For backward compatibility we still want to allow patterns like
|
||
|
this->A<T>::foo, but the template keyword in a qualified name is
|
||
|
specifically to specify that a dependent name is a template, so don't look
|
||
|
in the enclosing scope at all.
|
||
|
|
||
|
Also fix handling of dependent bases: if member lookup in the current
|
||
|
instantiation fails and we have dependent bases, the lookup is dependent.
|
||
|
We were already handling that for the case where lookup in the enclosing
|
||
|
scope also fails, but we also want it to affect that lookup itself.
|
||
|
|
||
|
PR c++/106310
|
||
|
|
||
|
gcc/cp/ChangeLog:
|
||
|
|
||
|
* parser.c (cp_parser_template_name): Skip non-member
|
||
|
lookup after the template keyword.
|
||
|
(cp_parser_lookup_name): Pass down template_keyword_p.
|
||
|
|
||
|
gcc/testsuite/ChangeLog:
|
||
|
|
||
|
* g++.dg/template/template-keyword4.C: New test.
|
||
|
|
||
|
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
|
||
|
index 8287934a679..8df715596eb 100644
|
||
|
--- a/gcc/cp/parser.c
|
||
|
+++ b/gcc/cp/parser.c
|
||
|
@@ -2610,7 +2610,7 @@ static tree cp_parser_objc_struct_declaration
|
||
|
/* Utility Routines */
|
||
|
|
||
|
static cp_expr cp_parser_lookup_name
|
||
|
- (cp_parser *, tree, enum tag_types, bool, bool, bool, tree *, location_t);
|
||
|
+ (cp_parser *, tree, enum tag_types, int, bool, bool, tree *, location_t);
|
||
|
static tree cp_parser_lookup_name_simple
|
||
|
(cp_parser *, tree, location_t);
|
||
|
static tree cp_parser_maybe_treat_template_as_class
|
||
|
@@ -17748,7 +17748,7 @@ cp_parser_template_name (cp_parser* parser,
|
||
|
/* Look up the name. */
|
||
|
decl = cp_parser_lookup_name (parser, identifier,
|
||
|
tag_type,
|
||
|
- /*is_template=*/true,
|
||
|
+ /*is_template=*/1 + template_keyword_p,
|
||
|
/*is_namespace=*/false,
|
||
|
check_dependency_p,
|
||
|
/*ambiguous_decls=*/NULL,
|
||
|
@@ -29254,7 +29254,7 @@ prefer_type_arg (tag_types tag_type)
|
||
|
refer to types are ignored.
|
||
|
|
||
|
If IS_TEMPLATE is TRUE, bindings that do not refer to templates are
|
||
|
- ignored.
|
||
|
+ ignored. If IS_TEMPLATE IS 2, the 'template' keyword was specified.
|
||
|
|
||
|
If IS_NAMESPACE is TRUE, bindings that do not refer to namespaces
|
||
|
are ignored.
|
||
|
@@ -29269,7 +29269,7 @@ prefer_type_arg (tag_types tag_type)
|
||
|
static cp_expr
|
||
|
cp_parser_lookup_name (cp_parser *parser, tree name,
|
||
|
enum tag_types tag_type,
|
||
|
- bool is_template,
|
||
|
+ int is_template,
|
||
|
bool is_namespace,
|
||
|
bool check_dependency,
|
||
|
tree *ambiguous_decls,
|
||
|
@@ -29454,7 +29454,14 @@ cp_parser_lookup_name (cp_parser *parser, tree name,
|
||
|
else
|
||
|
decl = NULL_TREE;
|
||
|
|
||
|
- if (!decl)
|
||
|
+ /* If we didn't find a member and have dependent bases, the member lookup
|
||
|
+ is now dependent. */
|
||
|
+ if (!dep && !decl && any_dependent_bases_p (object_type))
|
||
|
+ dep = true;
|
||
|
+
|
||
|
+ if (dep && is_template == 2)
|
||
|
+ /* The template keyword specifies a dependent template. */;
|
||
|
+ else if (!decl)
|
||
|
/* Look it up in the enclosing context. DR 141: When looking for a
|
||
|
template-name after -> or ., only consider class templates. */
|
||
|
decl = lookup_name (name, is_namespace ? LOOK_want::NAMESPACE
|
||
|
diff --git a/gcc/testsuite/g++.dg/template/template-keyword4.C b/gcc/testsuite/g++.dg/template/template-keyword4.C
|
||
|
new file mode 100644
|
||
|
index 00000000000..a7ab9bb8ca6
|
||
|
--- /dev/null
|
||
|
+++ b/gcc/testsuite/g++.dg/template/template-keyword4.C
|
||
|
@@ -0,0 +1,18 @@
|
||
|
+// PR c++/106310
|
||
|
+
|
||
|
+template <class T>
|
||
|
+struct set{};
|
||
|
+
|
||
|
+template< typename T >
|
||
|
+struct Base
|
||
|
+{
|
||
|
+ template< int > int set(T const &);
|
||
|
+};
|
||
|
+
|
||
|
+template< typename T >
|
||
|
+struct Derived : Base< T >
|
||
|
+{
|
||
|
+ void f(T const &arg) {
|
||
|
+ this->template set< 0 >(arg);
|
||
|
+ }
|
||
|
+};
|