mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-04-11 03:50:27 +08:00
c++: Member template function lookup failure [PR94799]
My earlier patch for this PR, r11-86, broke pybind11. That patch changed cp_parser_class_name to also consider the object expression scope (parser->context->object_type) to fix parsing of p->template A<T>::foo(); // consider p's scope too Here we reject b.operator typename B<T>::type(); because 'typename_p' in cp_parser_class_name uses 'scope', which means that 'typename_p' will be true for the example above. Then we create a TYPENAME_TYPE via make_typename_type, which fails when tsubsting it; the code basically created 'typename B::B' and then we complain that there is no member named 'B' in 'A<int>'. So, when deciding if we should create a TYPENAME_TYPE, don't consider the object_type scope, like we did pre-r11-86. gcc/cp/ChangeLog: PR c++/94799 * parser.c (cp_parser_class_name): Use parser->scope when setting typename_p. gcc/testsuite/ChangeLog: PR c++/94799 * g++.dg/template/lookup16.C: New test.
This commit is contained in:
parent
43cb72263f
commit
323dd42552
@ -23794,13 +23794,10 @@ cp_parser_class_name (cp_parser *parser,
|
||||
bool enum_ok)
|
||||
{
|
||||
tree decl;
|
||||
tree scope;
|
||||
bool typename_p;
|
||||
cp_token *token;
|
||||
tree identifier = NULL_TREE;
|
||||
|
||||
/* All class-names start with an identifier. */
|
||||
token = cp_lexer_peek_token (parser->lexer);
|
||||
cp_token *token = cp_lexer_peek_token (parser->lexer);
|
||||
if (token->type != CPP_NAME && token->type != CPP_TEMPLATE_ID)
|
||||
{
|
||||
cp_parser_error (parser, "expected class-name");
|
||||
@ -23816,14 +23813,16 @@ cp_parser_class_name (cp_parser *parser,
|
||||
|
||||
where we first want to look up A<T>::a in the class of the object
|
||||
expression, as per [basic.lookup.classref]. */
|
||||
scope = parser->scope ? parser->scope : parser->context->object_type;
|
||||
tree scope = parser->scope ? parser->scope : parser->context->object_type;
|
||||
if (scope == error_mark_node)
|
||||
return error_mark_node;
|
||||
|
||||
/* Any name names a type if we're following the `typename' keyword
|
||||
in a qualified name where the enclosing scope is type-dependent. */
|
||||
typename_p = (typename_keyword_p && scope && TYPE_P (scope)
|
||||
&& dependent_type_p (scope));
|
||||
const bool typename_p = (typename_keyword_p
|
||||
&& parser->scope
|
||||
&& TYPE_P (parser->scope)
|
||||
&& dependent_type_p (parser->scope));
|
||||
/* Handle the common case (an identifier, but not a template-id)
|
||||
efficiently. */
|
||||
if (token->type == CPP_NAME
|
||||
|
23
gcc/testsuite/g++.dg/template/lookup16.C
Normal file
23
gcc/testsuite/g++.dg/template/lookup16.C
Normal file
@ -0,0 +1,23 @@
|
||||
// PR c++/94799
|
||||
// { dg-do compile { target c++11 } }
|
||||
|
||||
template <typename> struct A {
|
||||
typedef int type;
|
||||
operator int();
|
||||
};
|
||||
|
||||
template <typename T> using B = A<T>;
|
||||
|
||||
template <typename T> typename B<T>::type foo(B<T> b)
|
||||
{
|
||||
auto r1 = b.operator typename A<T>::type();
|
||||
auto r2 = b.operator typename A<T>::template A<T>::type();
|
||||
auto r3 = b.operator typename B<T>::type();
|
||||
auto r4 = b.operator typename B<T>::template A<T>::type();
|
||||
return r1 + r2 + r3 + r4;
|
||||
}
|
||||
|
||||
void bar()
|
||||
{
|
||||
foo(A<int>());
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user