PR c++/54769 - wrong lookup of dependent template-name.
authorJason Merrill <jason@redhat.com>
Wed, 28 Jun 2017 19:41:36 +0000 (15:41 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Wed, 28 Jun 2017 19:41:36 +0000 (15:41 -0400)
* 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
gcc/cp/parser.c
gcc/testsuite/g++.dg/template/lookup11.C [new file with mode: 0644]

index 7f611727536942f8ae5a279b432b1db118c41f6d..3b3bb6d51fef61343afae508444883ce9f2d6403 100644 (file)
@@ -1,5 +1,12 @@
 2017-06-28  Jason Merrill  <jason@redhat.com>
 
+       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.
 
index 246af7623be9d837070dd4750efc69df0877c46a..c9fc2844b7fa1cfd62ecf991231bd27160962a18 100644 (file)
@@ -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 (file)
index 0000000..203460e
--- /dev/null
@@ -0,0 +1,11 @@
+// PR c++/81026
+
+namespace std {
+  template<class> struct extent;
+}
+using namespace std;
+
+template <class T>
+struct S {
+  void f() { T().template extent<42>(); }
+};