re PR c++/11551 (g++ accepts typedef as destructor name)
authorMark Mitchell <mark@codesourcery.com>
Thu, 21 Aug 2003 17:44:16 +0000 (17:44 +0000)
committerMark Mitchell <mmitchel@gcc.gnu.org>
Thu, 21 Aug 2003 17:44:16 +0000 (17:44 +0000)
PR c++/11551
* parser.c (cp_parser_id_expression): Add declarator_p parameter.
(cp_parser_primary_expression): Adjust call to
cp_parser_id_expression.
(cp_parser_unqualified_id): Complain about the use of
typedef-names in a destructor declarator.
(cp_parser_postfix_expression): Adjust call to
cp_parser_id_expression.
(cp_parser_type_parameter): Likewise.
(cp_parser_template_argument): Likewise.
(cp_parser_declarator_id): Likewise.

PR c++/11919
* call.c (standard_conversion): Use same_type_p, not pointer
equality, to compare types.

PR c++/10762
* parser.c (cp_parser_using_declaration): Check for invalid uses
of template-ids here...
* decl2.c (do_class_using_decl): ... rather than here.

PR c++/11919
* g++.dg/overload/prom1.C: New test.

PR c++/11551
* g++.dg/parse/dtor2.C: New test.

PR c++/10762
* g++.dg/parse/using2.C: New test.

From-SVN: r70652

gcc/cp/ChangeLog
gcc/cp/call.c
gcc/cp/decl2.c
gcc/cp/parser.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/overload/prom1.C [new file with mode: 0644]
gcc/testsuite/g++.dg/parse/dtor2.C [new file with mode: 0644]
gcc/testsuite/g++.dg/parse/using2.C [new file with mode: 0644]

index 8ef1aeb0d1f170a27dcba772455eda71ed0acf2f..ec4f44458bd03b306d77e98a8eca534ac55a5667 100644 (file)
@@ -1,3 +1,26 @@
+2003-08-21  Mark Mitchell  <mark@codesourcery.com>
+
+       PR c++/11551
+       * parser.c (cp_parser_id_expression): Add declarator_p parameter.
+       (cp_parser_primary_expression): Adjust call to
+       cp_parser_id_expression.
+       (cp_parser_unqualified_id): Complain about the use of
+       typedef-names in a destructor declarator.
+       (cp_parser_postfix_expression): Adjust call to
+       cp_parser_id_expression.
+       (cp_parser_type_parameter): Likewise.
+       (cp_parser_template_argument): Likewise.
+       (cp_parser_declarator_id): Likewise.
+
+       PR c++/11919
+       * call.c (standard_conversion): Use same_type_p, not pointer
+       equality, to compare types.
+
+       PR c++/10762
+       * parser.c (cp_parser_using_declaration): Check for invalid uses
+       of template-ids here...
+       * decl2.c (do_class_using_decl): ... rather than here.
+
 2003-08-20  Mark Mitchell  <mark@codesourcery.com>
 
        PR c++/11834
index afdc2911891c58ba3abe3be0568ae5b99d0a79c3..a76d2ac022ab4154a9d348611d386f36b90f36be 100644 (file)
@@ -795,7 +795,7 @@ standard_conversion (tree to, tree from, tree expr)
       conv = build_conv (STD_CONV, to, conv);
 
       /* Give this a better rank if it's a promotion.  */
-      if (to == type_promotes_to (from)
+      if (same_type_p (to, type_promotes_to (from))
          && ICS_STD_RANK (TREE_OPERAND (conv, 0)) <= PROMO_RANK)
        ICS_STD_RANK (conv) = PROMO_RANK;
     }
index a38d993e0670b98aee60bf345041476e964f5d9e..4eb5c0e6daeaa04d92d514252c09b02875de5cc2 100644 (file)
@@ -4091,27 +4091,13 @@ do_class_using_decl (tree decl)
       error ("using-declaration cannot name destructor");
       return NULL_TREE;
     }
-  else if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
-    {
-    template_id_error:;
-      
-      error ("a using-declaration cannot specify a template-id");
-      return NULL_TREE;
-    }
   if (TREE_CODE (name) == TYPE_DECL)
-    {
-      if (CLASSTYPE_USE_TEMPLATE (TREE_TYPE (name)))
-       goto template_id_error;
-      name = DECL_NAME (name);
-    }
+    name = DECL_NAME (name);
   else if (TREE_CODE (name) == TEMPLATE_DECL)
      name = DECL_NAME (name);
   else if (BASELINK_P (name))
     {
       tree fns = BASELINK_FUNCTIONS (name);
-      
-      if (TREE_CODE (fns) == TEMPLATE_ID_EXPR)
-       goto template_id_error;
       name = DECL_NAME (get_first_fn (fns));
     }
 
index b2a111314634e15d1191b27d11e63ca25dae85b8..c177a6c778d7dbe4d6bf688abba0e5620335b63c 100644 (file)
@@ -1296,9 +1296,9 @@ static bool cp_parser_translation_unit
 static tree cp_parser_primary_expression
   (cp_parser *, cp_id_kind *, tree *);
 static tree cp_parser_id_expression
-  (cp_parser *, bool, bool, bool *);
+  (cp_parser *, bool, bool, bool *, bool);
 static tree cp_parser_unqualified_id
-  (cp_parser *, bool, bool);
+  (cp_parser *, bool, bool, bool);
 static tree cp_parser_nested_name_specifier_opt
   (cp_parser *, bool, bool, bool);
 static tree cp_parser_nested_name_specifier
@@ -2398,7 +2398,8 @@ cp_parser_primary_expression (cp_parser *parser,
          = cp_parser_id_expression (parser, 
                                     /*template_keyword_p=*/false,
                                     /*check_dependency_p=*/true,
-                                    /*template_p=*/NULL);
+                                    /*template_p=*/NULL,
+                                    /*declarator_p=*/false);
        if (id_expression == error_mark_node)
          return error_mark_node;
        /* If we have a template-id, then no further lookup is
@@ -2495,13 +2496,17 @@ cp_parser_primary_expression (cp_parser *parser,
 
    If *TEMPLATE_P is non-NULL, it is set to true iff the
    `template' keyword is used to explicitly indicate that the entity
-   named is a template.  */
+   named is a template.  
+
+   If DECLARATOR_P is true, the id-expression is appearing as part of
+   a declarator, rather than as part of an exprsesion.  */
 
 static tree
 cp_parser_id_expression (cp_parser *parser,
                         bool template_keyword_p,
                         bool check_dependency_p,
-                        bool *template_p)
+                        bool *template_p,
+                        bool declarator_p)
 {
   bool global_scope_p;
   bool nested_name_specifier_p;
@@ -2542,7 +2547,8 @@ cp_parser_id_expression (cp_parser *parser,
       saved_qualifying_scope = parser->qualifying_scope;
       /* Process the final unqualified-id.  */
       unqualified_id = cp_parser_unqualified_id (parser, *template_p,
-                                                check_dependency_p);
+                                                check_dependency_p,
+                                                declarator_p);
       /* Restore the SAVED_SCOPE for our caller.  */
       parser->scope = saved_scope;
       parser->object_scope = saved_object_scope;
@@ -2597,7 +2603,8 @@ cp_parser_id_expression (cp_parser *parser,
     }
   else
     return cp_parser_unqualified_id (parser, template_keyword_p,
-                                    /*check_dependency_p=*/true);
+                                    /*check_dependency_p=*/true,
+                                    declarator_p);
 }
 
 /* Parse an unqualified-id.
@@ -2618,12 +2625,15 @@ cp_parser_id_expression (cp_parser *parser,
    BIT_NOT_EXPR is an IDENTIFIER_NODE for the class-name.  For the
    other productions, see the documentation accompanying the
    corresponding parsing functions.  If CHECK_DEPENDENCY_P is false,
-   names are looked up in uninstantiated templates.  */
+   names are looked up in uninstantiated templates.  If DECLARATOR_P
+   is true, the unqualified-id is appearing as part of a declarator,
+   rather than as part of an expression.  */
 
 static tree
 cp_parser_unqualified_id (cp_parser* parser, 
                           bool template_keyword_p,
-                         bool check_dependency_p)
+                         bool check_dependency_p,
+                         bool declarator_p)
 {
   cp_token *token;
 
@@ -2781,6 +2791,16 @@ cp_parser_unqualified_id (cp_parser* parser,
        else if (type_decl == error_mark_node)
          return error_mark_node;
 
+       /* [class.dtor]
+
+          A typedef-name that names a class shall not be used as the
+          identifier in the declarator for a destructor declaration.  */
+       if (declarator_p 
+           && !DECL_IMPLICIT_TYPEDEF_P (type_decl)
+           && !DECL_SELF_REFERENCE_P (type_decl))
+         error ("typedef-name `%D' used as destructor declarator",
+                type_decl);
+
        return build_nt (BIT_NOT_EXPR, TREE_TYPE (type_decl));
       }
 
@@ -3625,7 +3645,8 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
                name = cp_parser_id_expression (parser,
                                                template_p,
                                                /*check_dependency_p=*/true,
-                                               /*template_p=*/NULL);
+                                               /*template_p=*/NULL,
+                                               /*declarator_p=*/false);
                /* In general, build a SCOPE_REF if the member name is
                   qualified.  However, if the name was not dependent
                   and has already been resolved; there is no need to
@@ -7386,7 +7407,8 @@ cp_parser_type_parameter (cp_parser* parser)
              = cp_parser_id_expression (parser,
                                         /*template_keyword_p=*/false,
                                         /*check_dependency_p=*/true,
-                                        /*template_p=*/NULL);
+                                        /*template_p=*/NULL,
+                                        /*declarator_p=*/false);
            /* Look up the name.  */
            default_argument 
              = cp_parser_lookup_name_simple (parser, default_argument);
@@ -7805,7 +7827,8 @@ cp_parser_template_argument (cp_parser* parser)
   argument = cp_parser_id_expression (parser, 
                                      /*template_keyword_p=*/false,
                                      /*check_dependency_p=*/true,
-                                     &template_p);
+                                     &template_p,
+                                     /*declarator_p=*/false);
   /* If the next token isn't a `,' or a `>', then this argument wasn't
      really finished.  */
   if (!cp_parser_next_token_ends_template_argument_p (parser))
@@ -8992,35 +9015,47 @@ cp_parser_using_declaration (cp_parser* parser)
   /* Parse the unqualified-id.  */
   identifier = cp_parser_unqualified_id (parser, 
                                         /*template_keyword_p=*/false,
-                                        /*check_dependency_p=*/true);
+                                        /*check_dependency_p=*/true,
+                                        /*declarator_p=*/true);
 
   /* The function we call to handle a using-declaration is different
      depending on what scope we are in.  */
-  scope = current_scope ();
-  if (scope && TYPE_P (scope))
-    {
-      /* Create the USING_DECL.  */
-      decl = do_class_using_decl (build_nt (SCOPE_REF,
-                                           parser->scope,
-                                           identifier));
-      /* Add it to the list of members in this class.  */
-      finish_member_declaration (decl);
-    }
+  if (identifier == error_mark_node)
+    ;
+  else if (TREE_CODE (identifier) != IDENTIFIER_NODE
+          && TREE_CODE (identifier) != BIT_NOT_EXPR)
+    /* [namespace.udecl]
+
+       A using declaration shall not name a template-id.  */
+    error ("a template-id may not appear in a using-declaration");
   else
     {
-      decl = cp_parser_lookup_name_simple (parser, identifier);
-      if (decl == error_mark_node)
+      scope = current_scope ();
+      if (scope && TYPE_P (scope))
        {
-         if (parser->scope && parser->scope != global_namespace)
-           error ("`%D::%D' has not been declared", 
-                  parser->scope, identifier);
-         else
-           error ("`::%D' has not been declared", identifier);
+         /* Create the USING_DECL.  */
+         decl = do_class_using_decl (build_nt (SCOPE_REF,
+                                               parser->scope,
+                                               identifier));
+         /* Add it to the list of members in this class.  */
+         finish_member_declaration (decl);
        }
-      else if (scope)
-       do_local_using_decl (decl);
       else
-       do_toplevel_using_decl (decl);
+       {
+         decl = cp_parser_lookup_name_simple (parser, identifier);
+         if (decl == error_mark_node)
+           {
+             if (parser->scope && parser->scope != global_namespace)
+               error ("`%D::%D' has not been declared", 
+                      parser->scope, identifier);
+             else
+               error ("`::%D' has not been declared", identifier);
+           }
+         else if (scope)
+           do_local_using_decl (decl);
+         else
+           do_toplevel_using_decl (decl);
+       }
     }
 
   /* Look for the final `;'.  */
@@ -10119,7 +10154,8 @@ cp_parser_declarator_id (cp_parser* parser)
   id_expression = cp_parser_id_expression (parser,
                                           /*template_keyword_p=*/false,
                                           /*check_dependency_p=*/false,
-                                          /*template_p=*/NULL);
+                                          /*template_p=*/NULL,
+                                          /*declarator_p=*/true);
   /* If the name was qualified, create a SCOPE_REF to represent 
      that.  */
   if (parser->scope)
index 65d03080db4c90f7ee5dbbc3b998b83b0d06e9ab..6aa9a0a3a72419e8d66bb891ec7f500ef6ce7ab0 100644 (file)
@@ -1,3 +1,14 @@
+2003-08-21  Mark Mitchell  <mark@codesourcery.com>
+
+       PR c++/11919
+       * g++.dg/overload/prom1.C: New test.
+
+       PR c++/11551
+       * g++.dg/parse/dtor2.C: New test.
+
+       PR c++/10762
+       * g++.dg/parse/using2.C: New test.
+
 2003-08-21  Kazu Hirata  <kazu@cs.umass.edu>
 
        PR target/11805
diff --git a/gcc/testsuite/g++.dg/overload/prom1.C b/gcc/testsuite/g++.dg/overload/prom1.C
new file mode 100644 (file)
index 0000000..9eb387d
--- /dev/null
@@ -0,0 +1,9 @@
+void foo(signed char) {}
+typedef int bar;
+void foo(bar) {}
+
+int main (int, char **) {
+  char c;
+  foo(c);
+  return 0;
+}
diff --git a/gcc/testsuite/g++.dg/parse/dtor2.C b/gcc/testsuite/g++.dg/parse/dtor2.C
new file mode 100644 (file)
index 0000000..60e132b
--- /dev/null
@@ -0,0 +1,4 @@
+struct A {
+  typedef A A2;
+  ~A2(); // { dg-error "" }
+};
diff --git a/gcc/testsuite/g++.dg/parse/using2.C b/gcc/testsuite/g++.dg/parse/using2.C
new file mode 100644 (file)
index 0000000..bfdb09f
--- /dev/null
@@ -0,0 +1,8 @@
+namespace N {
+  template <typename T>
+  struct foo {};
+}
+
+int main() {
+  using N::foo<double>; // { dg-error "" }
+}