re PR c++/9403 (parse error on template keyword used for disambiguation)
authorNathan Sidwell <nathan@codesourcery.com>
Sat, 25 Jan 2003 18:02:43 +0000 (18:02 +0000)
committerNathan Sidwell <nathan@gcc.gnu.org>
Sat, 25 Jan 2003 18:02:43 +0000 (18:02 +0000)
cp:
PR c++/9403
* parser.c (cp_parser_class_or_namespace_name): Reject duplicate
template keyword.
(cp_parser_base_specifier): Look for and consume a
TEMPLATE keyword. Replace switch with array index.

PR c++/795
* semantics.c (finish_non_static_data_member): Remember the
field's type even in a template.

PR c++/9415
* pt.c (tsubst_copy_and_build, CALL_EXPR): BASELINK exprs are
already scoped.

PR c++/8545
* parser.c (cp_parser_cast_expression): Be more tentative.
testsuite:
PR c++/9403
* g++.dg/parse/template3.C: New test.
* g++.old-deja/g++.pt/memclass5.C: Add needed template keyword.

PR c++/795
* g++.dg/parse/template4.C: New test.

PR c++/9415
* g++.dg/template/qual2.C: New test.

PR c++/8545
* g++.old-deja/g++.brendan/parse3.C: Remove XFAIL.

* g++.old-deja/g++.ns/bogus1.C: Change expected error.

From-SVN: r61791

gcc/cp/ChangeLog
gcc/cp/parser.c
gcc/cp/pt.c
gcc/cp/semantics.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/parse/template3.C [new file with mode: 0644]
gcc/testsuite/g++.dg/parse/template4.C [new file with mode: 0644]
gcc/testsuite/g++.dg/template/qual2.C [new file with mode: 0644]
gcc/testsuite/g++.old-deja/g++.brendan/parse3.C
gcc/testsuite/g++.old-deja/g++.ns/bogus1.C
gcc/testsuite/g++.old-deja/g++.pt/memclass5.C

index 336370f20518aaf9f902b2146ebd9a8d51f1d086..fe8898f28d6997a21be5279f919ffc151a854dc4 100644 (file)
@@ -1,3 +1,22 @@
+2003-01-25  Nathan Sidwell  <nathan@codesourcery.com>
+
+       PR c++/9403
+       * parser.c (cp_parser_class_or_namespace_name): Reject duplicate
+       template keyword.
+       (cp_parser_base_specifier): Look for and consume a
+       TEMPLATE keyword. Replace switch with array index.
+
+       PR c++/795
+       * semantics.c (finish_non_static_data_member): Remember the
+       field's type even in a template.
+
+       PR c++/9415
+       * pt.c (tsubst_copy_and_build, CALL_EXPR): BASELINK exprs are
+       already scoped.
+       
+       PR c++/8545
+       * parser.c (cp_parser_cast_expression): Be more tentative.
+
 2003-01-25  Kriang Lerdsuwanakij  <lerdsuwa@users.sourceforge.net>
 
        * cp-tree.h (flagged_type_tree_s): Remove.
index 4d809b810125ee1fa9554bac2759ae88582889ea..7e172abd55580bb51e1fc4a440e5ea0395b0fd4b 100644 (file)
@@ -3392,16 +3392,6 @@ cp_parser_class_or_namespace_name (cp_parser *parser,
   tree scope;
   bool only_class_p;
 
-  /* If the next token is the `template' keyword, we know that we are
-     looking at a class-name.  */
-  if (cp_lexer_next_token_is_keyword (parser->lexer, RID_TEMPLATE))
-    return cp_parser_class_name (parser, 
-                                typename_keyword_p,
-                                template_keyword_p,
-                                type_p,
-                                /*check_access_p=*/true,
-                                check_dependency_p,
-                                /*class_head_p=*/false);
   /* Before we try to parse the class-name, we must save away the
      current PARSER->SCOPE since cp_parser_class_name will destroy
      it.  */
@@ -3410,7 +3400,7 @@ cp_parser_class_or_namespace_name (cp_parser *parser,
   saved_object_scope = parser->object_scope;
   /* Try for a class-name first.  If the SAVED_SCOPE is a type, then
      there is no need to look for a namespace-name.  */
-  only_class_p = saved_scope && TYPE_P (saved_scope);
+  only_class_p = template_keyword_p || (saved_scope && TYPE_P (saved_scope));
   if (!only_class_p)
     cp_parser_parse_tentatively (parser);
   scope = cp_parser_class_name (parser, 
@@ -3931,7 +3921,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
              postfix_expression = build_x_arrow (postfix_expression);
            /* Check to see whether or not the expression is
               type-dependent.  */
-           dependent_p = (type_dependent_expression_p (postfix_expression));
+           dependent_p = type_dependent_expression_p (postfix_expression);
            /* The identifier following the `->' or `.' is not
               qualified.  */
            parser->scope = NULL_TREE;
@@ -4761,23 +4751,26 @@ cp_parser_cast_expression (cp_parser *parser, bool address_p)
       /* Restore the saved message.  */
       parser->type_definition_forbidden_message = saved_message;
 
-      /* If all went well, this is a cast.  */
+      /* If ok so far, parse the dependent expression. We cannot be
+         sure it is a cast. Consider `(T ())'.  It is a parenthesized
+         ctor of T, but looks like a cast to function returning T
+         without a dependent expression.  */
+      if (!cp_parser_error_occurred (parser))
+       expr = cp_parser_cast_expression (parser, /*address_p=*/false);
+
       if (cp_parser_parse_definitely (parser))
        {
-         /* Parse the dependent expression.  */
-         expr = cp_parser_cast_expression (parser, /*address_p=*/false);
          /* Warn about old-style casts, if so requested.  */
          if (warn_old_style_cast 
              && !in_system_header 
              && !VOID_TYPE_P (type) 
              && current_lang_name != lang_name_c)
            warning ("use of old-style cast");
+         
          /* Perform the cast.  */
          expr = build_c_cast (type, expr);
+         return expr;
        }
-
-      if (expr)
-       return expr;
     }
 
   /* If we get here, then it's not a cast, so it must be a
@@ -12175,12 +12168,20 @@ cp_parser_base_clause (cp_parser* parser)
 static tree
 cp_parser_base_specifier (cp_parser* parser)
 {
+  static const tree *const access_nodes[][2] =
+  {
+    /* This ordering must match the access_kind enumeration.  */
+    {&access_default_node,   &access_default_virtual_node},
+    {&access_public_node,    &access_public_virtual_node},
+    {&access_protected_node, &access_protected_virtual_node},
+    {&access_private_node,   &access_private_virtual_node}
+  };
   cp_token *token;
   bool done = false;
   bool virtual_p = false;
   bool duplicate_virtual_error_issued_p = false;
   bool duplicate_access_error_issued_p = false;
-  bool class_scope_p;
+  bool class_scope_p, template_p;
   access_kind access = ak_none;
   tree access_node;
   tree type;
@@ -12236,45 +12237,9 @@ cp_parser_base_specifier (cp_parser* parser)
        }
     }
 
-  /* Map `virtual_p' and `access' onto one of the access 
-     tree-nodes.  */
-  if (!virtual_p)
-    switch (access)
-      {
-      case ak_none:
-       access_node = access_default_node;
-       break;
-      case ak_public:
-       access_node = access_public_node;
-       break;
-      case ak_protected:
-       access_node = access_protected_node;
-       break;
-      case ak_private:
-       access_node = access_private_node;
-       break;
-      default:
-       abort ();
-      }
-  else
-    switch (access)
-      {
-      case ak_none:
-       access_node = access_default_virtual_node;
-       break;
-      case ak_public:
-       access_node = access_public_virtual_node;
-       break;
-      case ak_protected:
-       access_node = access_protected_virtual_node;
-       break;
-      case ak_private:
-       access_node = access_private_virtual_node;
-       break;
-      default:
-       abort ();
-      }
-
+  /* Map `virtual_p' and `access' onto one of the access tree-nodes.  */
+  access_node = *access_nodes[access][virtual_p];
+  
   /* Look for the optional `::' operator.  */
   cp_parser_global_scope_opt (parser, /*current_scope_valid_p=*/false);
   /* Look for the nested-name-specifier.  The simplest way to
@@ -12296,10 +12261,12 @@ cp_parser_base_specifier (cp_parser* parser)
   /* If the base class is given by a qualified name, assume that names
      we see are type names or templates, as appropriate.  */
   class_scope_p = (parser->scope && TYPE_P (parser->scope));
+  template_p = class_scope_p && cp_parser_optional_template_keyword (parser);
+  
   /* Finally, look for the class-name.  */
   type = cp_parser_class_name (parser, 
                               class_scope_p,
-                              class_scope_p,
+                              template_p,
                               /*type_p=*/true,
                               /*check_access=*/true,
                               /*check_dependency_p=*/true,
index ca75cb0b0d65a1cacf85410cca346a8d6c50e121..bbfec1483f083ca919bb5748002752c10a69b912 100644 (file)
@@ -8129,28 +8129,32 @@ tsubst_copy_and_build (t, args, complain, in_decl)
 
     case CALL_EXPR:
       {
-       tree function
-         = tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl);
-       if (TREE_CODE (function) == SCOPE_REF)
+       tree function, copy_args;
+
+       function = tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl);
+       copy_args = tsubst_copy_and_build (TREE_OPERAND (t, 1), args,
+                                          complain, in_decl);
+         
+       if (BASELINK_P (function))
+         return build_call_from_tree (function, copy_args, 1);
+       else if (TREE_CODE (function) == SCOPE_REF)
          {
            tree name = TREE_OPERAND (function, 1);
            if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
              name = build_nt (TEMPLATE_ID_EXPR,
                               TREE_OPERAND (name, 0),
                               TREE_OPERAND (name, 1));
-
-           return build_call_from_tree
-             (resolve_scoped_fn_name (TREE_OPERAND (function, 0), name),
-              tsubst_copy_and_build (TREE_OPERAND (t, 1), args, complain,
-                                     in_decl),
-              1);
+           
+           function = resolve_scoped_fn_name (TREE_OPERAND (function, 0),
+                                              name);
+           
+           return build_call_from_tree (function, copy_args, 1);
          }
        else
          {
            tree name = function;
            tree id;
-           tree copy_args = tsubst_copy_and_build
-             (TREE_OPERAND (t, 1), args, complain, in_decl);
+           
            if (copy_args != NULL_TREE && TREE_CODE (name) == LOOKUP_EXPR
                && !LOOKUP_EXPR_GLOBAL (name)
                && (TREE_CODE ((id = TREE_OPERAND (name, 0)))
index 19808e68583adf3808dfd4e5e996fc2f3c050178..fb6f25d116ffb63d1d0af57afc8c19fca02e9f04 100644 (file)
@@ -1214,7 +1214,8 @@ finish_non_static_data_member (tree decl, tree qualifying_scope)
     }
   TREE_USED (current_class_ptr) = 1;
   if (processing_template_decl)
-    return build_min_nt (COMPONENT_REF, current_class_ref, DECL_NAME (decl));
+    return build_min (COMPONENT_REF, TREE_TYPE (decl),
+                     current_class_ref, DECL_NAME (decl));
   else
     {
       tree access_type = current_class_type;
index f6a8dff0a9ffba9aba5540a4242c6184e7e0166f..7c331f1a98a167440450e539a048b6248cf421e9 100644 (file)
@@ -1,3 +1,20 @@
+2003-01-25  Nathan Sidwell  <nathan@codesourcery.com>
+
+       PR c++/9403
+       * g++.dg/parse/template3.C: New test.
+       * g++.old-deja/g++.pt/memclass5.C: Add needed template keyword.
+       
+       PR c++/795
+       * g++.dg/parse/template4.C: New test.
+       
+       PR c++/9415
+       * g++.dg/template/qual2.C: New test.
+       
+       PR c++/8545
+       * g++.old-deja/g++.brendan/parse3.C: Remove XFAIL.
+
+       * g++.old-deja/g++.ns/bogus1.C: Change expected error.
+
 2003-01-25  Roger Sayle  <roger@eyesopen.com>
 
        * gcc.c-torture/execute/switch-1.c: New test case.
diff --git a/gcc/testsuite/g++.dg/parse/template3.C b/gcc/testsuite/g++.dg/parse/template3.C
new file mode 100644 (file)
index 0000000..290721e
--- /dev/null
@@ -0,0 +1,17 @@
+// { dg-do compile }
+
+// Copyright (C) 2003 Free Software Foundation, Inc.
+// Contributed by Nathan Sidwell 24 Jan 2003 <nathan@codesourcery.com>
+
+// PR 9403. We failed to parse template keyword, and we accepted code
+// which required one.
+
+template<bool> struct Outer;
+
+template <bool b, typename T>
+struct X : Outer<b>::template Inner<T>
+{};
+
+template <bool b, typename T>
+struct Y : Outer<b>::Inner<T> {}; // { dg-error "" "" }
+
diff --git a/gcc/testsuite/g++.dg/parse/template4.C b/gcc/testsuite/g++.dg/parse/template4.C
new file mode 100644 (file)
index 0000000..11f11d5
--- /dev/null
@@ -0,0 +1,21 @@
+// { dg-do compile }
+
+// Copyright (C) 2003 Free Software Foundation, Inc.
+// Contributed by Nathan Sidwell 32 Jan 2003 <nathan@codesourcery.com>
+
+// PR 795. fields are not necessarily a dependent type.
+
+struct V
+{
+  template<typename T> T get ();
+};
+
+struct L
+{
+  V v;
+  
+  template<typename T> T at (int i)
+  {
+    return v.get<T> ();
+  }
+};
diff --git a/gcc/testsuite/g++.dg/template/qual2.C b/gcc/testsuite/g++.dg/template/qual2.C
new file mode 100644 (file)
index 0000000..aa6b10e
--- /dev/null
@@ -0,0 +1,29 @@
+// { dg-do run }
+
+// Copyright (C) 2003 Free Software Foundation, Inc.
+// Contributed by Nathan Sidwell 23 Jan 2003 <nathan@codesourcery.com>
+
+// PR9415. Forgot a lookup was scoped
+
+int here;
+int there;
+
+struct B
+{
+  virtual int activate() {return !here++;}
+};
+
+template <class K>
+struct TPL : public B
+{
+  int activate()
+  {
+    return !there++ && B::activate();
+  }
+};
+
+int main ()
+{
+  TPL<int> i;
+  return !i.activate ();
+}
index 8941356e061fea8686cf813b9183e9a41ae3676d..ffe72d2a38aa8bd914cef5b6b0d62cef105a6ccb 100644 (file)
@@ -6,6 +6,7 @@
 // when the parser's been cleaned up or rewritten, these two error
 // markers can go away, since they'll no longer occur.
 
+// Fixed. PR 8545, 2001 01 23
 class A
 {
   public:
@@ -19,5 +20,5 @@ A A::operator+(const A in)
     if (high==0)
       return A();    // this works
     else
-      return (A());  // this works not // gets bogus error - XFAIL *-*-* 
+      return (A());  // this works not
 }
index c61dea8e77e570ae628b817b6a70b2387cd23322..373688a99c3a053fd2dbb18f64be2b3c92488219 100644 (file)
@@ -2,7 +2,7 @@
 
 namespace N {}
 
-void f(int N::k); // ERROR - cannot use `::' in parameter declaration
+void f(int N::k); // ERROR - 
 
 class Foo
 {
index 6fc72199b6458376bad918423674f91c2e7192f9..5a0c037e7d2a6eedf2f71addbaa4af8e5da4e693 100644 (file)
@@ -14,7 +14,7 @@ void f ()
   b.A<T>::template B<U>::~B();
 }
 
-template <class T> struct C: public A<T>::B<T> { };
+template <class T> struct C: public A<T>::template B<T> { };
   
 int main ()
 {