From 1e5f79b61994f8ffccad62a58031f5937aa16ae3 Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Wed, 28 Jun 2017 15:41:36 -0400 Subject: [PATCH] PR c++/54769 - wrong lookup of dependent template-name. * parser.c (cp_parser_template_name): Handle dependent object type. (cp_parser_nested_name_specifier_opt): Make template_keyword_p a parameter. (cp_parser_id_expression): Pass it. (cp_parser_diagnose_invalid_type_name): Handle TEMPLATE_ID_EXPR. From-SVN: r249752 --- gcc/cp/ChangeLog | 7 ++++ gcc/cp/parser.c | 52 ++++++++++++++++-------- gcc/testsuite/g++.dg/template/lookup11.C | 11 +++++ 3 files changed, 54 insertions(+), 16 deletions(-) create mode 100644 gcc/testsuite/g++.dg/template/lookup11.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 7f611727536..3b3bb6d51fe 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,12 @@ 2017-06-28 Jason Merrill + PR c++/54769 - wrong lookup of dependent template-name. + * parser.c (cp_parser_template_name): Handle dependent object type. + (cp_parser_nested_name_specifier_opt): Make template_keyword_p a + parameter. + (cp_parser_id_expression): Pass it. + (cp_parser_diagnose_invalid_type_name): Handle TEMPLATE_ID_EXPR. + * parser.c (cp_parser_template_id): Use the range location on the TEMPLATE_ID_EXPR. diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 246af7623be..c9fc2844b7f 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -2039,7 +2039,7 @@ static cp_expr cp_parser_id_expression static cp_expr cp_parser_unqualified_id (cp_parser *, bool, bool, bool, bool); static tree cp_parser_nested_name_specifier_opt - (cp_parser *, bool, bool, bool, bool); + (cp_parser *, bool, bool, bool, bool, bool = false); static tree cp_parser_nested_name_specifier (cp_parser *, bool, bool, bool, bool); static tree cp_parser_qualifying_entity @@ -3253,6 +3253,10 @@ cp_parser_diagnose_invalid_type_name (cp_parser *parser, tree id, error_at (location_of (id), "%qE in namespace %qE does not name a template type", id, parser->scope); + else if (TREE_CODE (id) == TEMPLATE_ID_EXPR) + error_at (location_of (id), + "%qE in namespace %qE does not name a template type", + TREE_OPERAND (id, 0), parser->scope); else error_at (location_of (id), "%qE in namespace %qE does not name a type", @@ -3296,6 +3300,10 @@ cp_parser_diagnose_invalid_type_name (cp_parser *parser, tree id, error_at (location_of (id), "%qE in %q#T does not name a template type", id, parser->scope); + else if (TREE_CODE (id) == TEMPLATE_ID_EXPR) + error_at (location_of (id), + "%qE in %q#T does not name a template type", + TREE_OPERAND (id, 0), parser->scope); else error_at (location_of (id), "%qE in %q#T does not name a type", @@ -5420,16 +5428,21 @@ cp_parser_id_expression (cp_parser *parser, /* Look for the optional `::' operator. */ global_scope_p - = (cp_parser_global_scope_opt (parser, /*current_scope_valid_p=*/false) - != NULL_TREE); + = (!template_keyword_p + && (cp_parser_global_scope_opt (parser, + /*current_scope_valid_p=*/false) + != NULL_TREE)); + /* Look for the optional nested-name-specifier. */ nested_name_specifier_p = (cp_parser_nested_name_specifier_opt (parser, /*typename_keyword_p=*/false, check_dependency_p, /*type_p=*/false, - declarator_p) + declarator_p, + template_keyword_p) != NULL_TREE); + /* If there is a nested-name-specifier, then we are looking at the first qualified-id production. */ if (nested_name_specifier_p) @@ -5874,7 +5887,8 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser, bool typename_keyword_p, bool check_dependency_p, bool type_p, - bool is_declaration) + bool is_declaration, + bool template_keyword_p /* = false */) { bool success = false; cp_token_position start = 0; @@ -5892,7 +5906,6 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser, tree new_scope; tree old_scope; tree saved_qualifying_scope; - bool template_keyword_p; /* Spot cases that cannot be the beginning of a nested-name-specifier. */ @@ -5967,8 +5980,6 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser, first time through the loop. */ if (success) template_keyword_p = cp_parser_optional_template_keyword (parser); - else - template_keyword_p = false; /* Save the old scope since the name lookup we are about to do might destroy it. */ @@ -15861,15 +15872,19 @@ cp_parser_template_name (cp_parser* parser, no point in doing name-lookup, so we just return IDENTIFIER. But, if the qualifying scope is non-dependent then we can (and must) do name-lookup normally. */ - if (template_keyword_p - && (!parser->scope - || (TYPE_P (parser->scope) - && dependent_type_p (parser->scope)))) + if (template_keyword_p) { - /* We're optimizing away the call to cp_parser_lookup_name, but we - still need to do this. */ - parser->context->object_type = NULL_TREE; - return identifier; + tree scope = (parser->scope ? parser->scope + : parser->context->object_type); + if (scope && TYPE_P (scope) + && (!CLASS_TYPE_P (scope) + || (check_dependency_p && dependent_type_p (scope)))) + { + /* We're optimizing away the call to cp_parser_lookup_name, but + we still need to do this. */ + parser->context->object_type = NULL_TREE; + return identifier; + } } } @@ -15882,6 +15897,11 @@ cp_parser_template_name (cp_parser* parser, /*ambiguous_decls=*/NULL, token->location); + /* If the lookup failed and we got the 'template' keyword, believe it. */ + if (decl == error_mark_node && template_keyword_p + && processing_template_decl) + return identifier; + decl = strip_using_decl (decl); /* If DECL is a template, then the name was a template-name. */ diff --git a/gcc/testsuite/g++.dg/template/lookup11.C b/gcc/testsuite/g++.dg/template/lookup11.C new file mode 100644 index 00000000000..203460eda73 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/lookup11.C @@ -0,0 +1,11 @@ +// PR c++/81026 + +namespace std { + template struct extent; +} +using namespace std; + +template +struct S { + void f() { T().template extent<42>(); } +}; -- 2.30.2