re PR c++/12735 (duplicate error messages for redeclaration errors)
authorMark Mitchell <mark@codesourcery.com>
Wed, 12 Nov 2003 18:15:02 +0000 (18:15 +0000)
committerMark Mitchell <mmitchel@gcc.gnu.org>
Wed, 12 Nov 2003 18:15:02 +0000 (18:15 +0000)
PR c++/12735
* cp-tree.h (duplicate_decls): Return a tree.
* decl.c (duplicate_decls): Clarify documentation.  Return
error_mark_node to indicate a failed redeclaration.
* friend.c (do_friend): Handle that case.
* name-lookup.c (pushdecl): Likewise.

From-SVN: r73503

gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/friend.c
gcc/cp/name-lookup.c

index d3b8316b4649aab3797804d54040703ec0c80ea4..647bcd02661a90ed777eae04875f371ba976e5b6 100644 (file)
@@ -1,3 +1,12 @@
+2003-11-12  Mark Mitchell  <mark@codesourcery.com>
+
+       PR c++/12735
+       * cp-tree.h (duplicate_decls): Return a tree.
+       * decl.c (duplicate_decls): Clarify documentation.  Return
+       error_mark_node to indicate a failed redeclaration.
+       * friend.c (do_friend): Handle that case.
+       * name-lookup.c (pushdecl): Likewise.
+
 2003-11-11  Jason Merrill  <jason@redhat.com>
 
        * cp-tree.h (DECL_NAMESPACE_ASSOCIATIONS): New macro.
index def9b81e3510ffa9e9d60cc00b71b5df675633e6..1c6154f469dc9e3c5445100d26e8a0c40cd7dc7b 100644 (file)
@@ -3623,7 +3623,7 @@ extern void pushtag                               (tree, tree, int);
 extern tree make_anon_name                     (void);
 extern void clear_anon_tags                    (void);
 extern int decls_match                         (tree, tree);
-extern int duplicate_decls                     (tree, tree);
+extern tree duplicate_decls                    (tree, tree);
 extern tree pushdecl_top_level                 (tree);
 extern tree pushdecl_top_level_and_finish       (tree, tree);
 extern tree push_using_decl                     (tree, tree);
index 0f7a8bcf62b4296324cce33a02cc8114090bb5e3..3894c7ac0ecd518e9d6e8c5ddebaaf21b7bb50c3 100644 (file)
@@ -1137,14 +1137,14 @@ warn_extern_redeclared_static (tree newdecl, tree olddecl)
   cp_pedwarn_at ("previous declaration of `%D'", olddecl);
 }
 
-/* Handle when a new declaration NEWDECL has the same name as an old
-   one OLDDECL in the same binding contour.  Prints an error message
-   if appropriate.
+/* If NEWDECL is a redeclaration of OLDDECL, merge the declarations.
+   If the redeclaration is invalid, a diagnostic is issued, and the
+   error_mark_node is returned.  Otherwise, OLDDECL is returned.
 
-   If safely possible, alter OLDDECL to look like NEWDECL, and return 1.
-   Otherwise, return 0.  */
+   If NEWDECL is not a redeclaration of OLDDECL, NULL_TREE is
+   returned.  */
 
-int
+tree
 duplicate_decls (tree newdecl, tree olddecl)
 {
   unsigned olddecl_uid = DECL_UID (olddecl);
@@ -1152,7 +1152,7 @@ duplicate_decls (tree newdecl, tree olddecl)
   int new_defines_function = 0;
 
   if (newdecl == olddecl)
-    return 1;
+    return olddecl;
 
   types_match = decls_match (newdecl, olddecl);
 
@@ -1205,7 +1205,7 @@ duplicate_decls (tree newdecl, tree olddecl)
        {
           /* Avoid warnings redeclaring anticipated built-ins.  */
           if (DECL_ANTICIPATED (olddecl))
-            return 0;
+            return NULL_TREE;
 
          /* If you declare a built-in or predefined function name as static,
             the old definition is overridden, but optionally warn this was a
@@ -1217,7 +1217,7 @@ duplicate_decls (tree newdecl, tree olddecl)
                            DECL_BUILT_IN (olddecl) ? "built-in" : "library",
                            olddecl);
              /* Discard the old built-in function.  */
-             return 0;
+             return NULL_TREE;
            }
          /* If the built-in is not ansi, then programs can override
             it even globally without an error.  */
@@ -1230,7 +1230,7 @@ duplicate_decls (tree newdecl, tree olddecl)
              error ("conflicts with built-in declaration `%#D'",
                        olddecl);
            }
-         return 0;
+         return NULL_TREE;
        }
       else if (!types_match)
        {
@@ -1257,7 +1257,7 @@ duplicate_decls (tree newdecl, tree olddecl)
            }
          else
            /* Discard the old built-in function.  */
-           return 0;
+           return NULL_TREE;
 
          /* Replace the old RTL to avoid problems with inlining.  */
          SET_DECL_RTL (olddecl, DECL_RTL (newdecl));
@@ -1302,14 +1302,14 @@ duplicate_decls (tree newdecl, tree olddecl)
             get shadowed, and know that if we need to find a TYPE_DECL
             for a given name, we can look in the IDENTIFIER_TYPE_VALUE
             slot of the identifier.  */
-         return 0;
+         return NULL_TREE;
        }
 
       if ((TREE_CODE (newdecl) == FUNCTION_DECL
           && DECL_FUNCTION_TEMPLATE_P (olddecl))
          || (TREE_CODE (olddecl) == FUNCTION_DECL
              && DECL_FUNCTION_TEMPLATE_P (newdecl)))
-       return 0;
+       return NULL_TREE;
 
       error ("`%#D' redeclared as different kind of symbol", newdecl);
       if (TREE_CODE (olddecl) == TREE_LIST)
@@ -1319,14 +1319,14 @@ duplicate_decls (tree newdecl, tree olddecl)
       /* New decl is completely inconsistent with the old one =>
         tell caller to replace the old one.  */
 
-      return 0;
+      return NULL_TREE;
     }
   else if (!types_match)
     {
       if (CP_DECL_CONTEXT (newdecl) != CP_DECL_CONTEXT (olddecl))
        /* These are certainly not duplicate declarations; they're
           from different scopes.  */
-       return 0;
+       return NULL_TREE;
 
       if (TREE_CODE (newdecl) == TEMPLATE_DECL)
        {
@@ -1354,7 +1354,7 @@ duplicate_decls (tree newdecl, tree olddecl)
              error ("new declaration `%#D'", newdecl);
              cp_error_at ("ambiguates old declaration `%#D'", olddecl);
            }
-         return 0;
+         return NULL_TREE;
        }
       if (TREE_CODE (newdecl) == FUNCTION_DECL)
        {
@@ -1371,7 +1371,7 @@ duplicate_decls (tree newdecl, tree olddecl)
              cp_error_at ("ambiguates old declaration `%#D'", olddecl);
            }
          else
-           return 0;
+           return NULL_TREE;
        }
 
       /* Already complained about this, so don't do so again.  */
@@ -1381,7 +1381,7 @@ duplicate_decls (tree newdecl, tree olddecl)
          error ("conflicting declaration '%#D'", newdecl);
          cp_error_at ("'%D' has a previous declaration as `%#D'",
                        olddecl, olddecl);
-          return false;
+          return NULL_TREE;
        }
     }
   else if (TREE_CODE (newdecl) == FUNCTION_DECL
@@ -1401,7 +1401,7 @@ duplicate_decls (tree newdecl, tree olddecl)
        can occur if we instantiate a template class, and then
        specialize one of its methods.  This situation is valid, but
        the declarations must be merged in the usual way.  */
-    return 0;
+    return NULL_TREE;
   else if (TREE_CODE (newdecl) == FUNCTION_DECL
           && ((DECL_TEMPLATE_INSTANTIATION (olddecl)
                && !DECL_USE_TEMPLATE (newdecl))
@@ -1409,12 +1409,20 @@ duplicate_decls (tree newdecl, tree olddecl)
                   && !DECL_USE_TEMPLATE (olddecl))))
     /* One of the declarations is a template instantiation, and the
        other is not a template at all.  That's OK.  */
-    return 0;
+    return NULL_TREE;
   else if (TREE_CODE (newdecl) == NAMESPACE_DECL
            && DECL_NAMESPACE_ALIAS (newdecl)
            && DECL_NAMESPACE_ALIAS (newdecl) == DECL_NAMESPACE_ALIAS (olddecl))
-    /* Redeclaration of namespace alias, ignore it.  */
-    return 1;
+    /* In [namespace.alias] we have:
+
+        In a declarative region, a namespace-alias-definition can be
+        used to redefine a namespace-alias declared in that declarative
+        region to refer only to the namespace to which it already
+        refers.  
+
+      Therefore, if we encounter a second alias directive for the same
+      alias, we can just ignore the second directive.  */
+    return olddecl;
   else
     {
       const char *errmsg = redeclaration_error_message (newdecl, olddecl);
@@ -1426,7 +1434,7 @@ duplicate_decls (tree newdecl, tree olddecl)
                          && namespace_bindings_p ())
                         ? "`%#D' previously defined here"
                         : "`%#D' previously declared here", olddecl);
-         return 0;
+         return error_mark_node;
        }
       else if (TREE_CODE (olddecl) == FUNCTION_DECL
               && DECL_INITIAL (olddecl) != NULL_TREE
@@ -1506,7 +1514,7 @@ duplicate_decls (tree newdecl, tree olddecl)
   if (TREE_CODE (olddecl) == TYPE_DECL
       && (DECL_IMPLICIT_TYPEDEF_P (olddecl)
          || DECL_IMPLICIT_TYPEDEF_P (newdecl)))
-    return 0;
+    return NULL_TREE;
 
   /* If new decl is `static' and an `extern' was seen previously,
      warn about it.  */
@@ -1585,7 +1593,7 @@ duplicate_decls (tree newdecl, tree olddecl)
            = DECL_SOURCE_LOCATION (newdecl);
        }
 
-      return 1;
+      return olddecl;
     }
 
   if (types_match)
@@ -1914,7 +1922,7 @@ duplicate_decls (tree newdecl, tree olddecl)
              && TREE_STATIC (olddecl))))
     make_decl_rtl (olddecl, NULL);
 
-  return 1;
+  return olddecl;
 }
 \f
 /* Generate an implicit declaration for identifier FUNCTIONID
@@ -10218,7 +10226,19 @@ start_function (tree declspecs, tree declarator, tree attrs, int flags)
       /* A specialization is not used to guide overload resolution.  */
       if (!DECL_TEMPLATE_SPECIALIZATION (decl1)
          && ! DECL_FUNCTION_MEMBER_P (decl1))
-       decl1 = pushdecl (decl1);
+       {
+         tree olddecl = pushdecl (decl1);
+
+         if (olddecl == error_mark_node)
+           /* If something went wrong when registering the declaration,
+              use DECL1; we have to have a FUNCTION_DECL to use when
+              parsing the body of the function.  */
+           ;
+         else
+           /* Otherwise, OLDDECL is either a previous declaration of
+              the same function or DECL1 itself.  */
+           decl1 = olddecl;
+       }
       else
        {
          /* We need to set the DECL_CONTEXT.  */
index 889631763a535cdcc5de8ebed49b691b33d8ea1b..e9547005bba48da6a2e4207ca9c6df74b595878b 100644 (file)
@@ -455,6 +455,9 @@ do_friend (tree ctype, tree declarator, tree decl, tree parmdecls,
            }
        }
 
+      if (decl == error_mark_node)
+       return error_mark_node;
+      
       add_friend (current_class_type, 
                  is_friend_template ? DECL_TI_TEMPLATE (decl) : decl,
                  /*complain=*/true);
index 185c04fb63d3571f5125839e3d42be48a0a29d04..a31aeebbcafe8e686ba448fabfed615d4f44d84c 100644 (file)
@@ -680,33 +680,38 @@ pushdecl (tree x)
              /* Throw away the redeclaration.  */
              POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t);
            }
-         else if (TREE_CODE (t) != TREE_CODE (x))
-           {
-             if (duplicate_decls (x, t))
-               POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t);
-           }
-         else if (duplicate_decls (x, t))
-           {
-             if (TREE_CODE (t) == TYPE_DECL)
-               SET_IDENTIFIER_TYPE_VALUE (name, TREE_TYPE (t));
-             else if (TREE_CODE (t) == FUNCTION_DECL)
-               check_default_args (t);
-
-             POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t);
-           }
-         else if (DECL_MAIN_P (x))
+         else
            {
-             /* A redeclaration of main, but not a duplicate of the
-                previous one.
-
-                [basic.start.main]
+             tree olddecl = duplicate_decls (x, t);
+             
+             /* If the redeclaration failed, we can stop at this
+                point.  */
+             if (olddecl == error_mark_node)
+               POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
+
+             if (olddecl)
+               {
+                 if (TREE_CODE (t) == TYPE_DECL)
+                   SET_IDENTIFIER_TYPE_VALUE (name, TREE_TYPE (t));
+                 else if (TREE_CODE (t) == FUNCTION_DECL)
+                   check_default_args (t);
 
-                This function shall not be overloaded.  */
-             cp_error_at ("invalid redeclaration of `%D'", t);
-             error ("as `%D'", x);
-             /* We don't try to push this declaration since that
-                causes a crash.  */
-             POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, x);
+                 POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t);
+               }
+             else if (DECL_MAIN_P (x))
+               {
+                 /* A redeclaration of main, but not a duplicate of the
+                    previous one.
+                    
+                    [basic.start.main]
+                    
+                    This function shall not be overloaded.  */
+                 cp_error_at ("invalid redeclaration of `%D'", t);
+                 error ("as `%D'", x);
+                 /* We don't try to push this declaration since that
+                    causes a crash.  */
+                 POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, x);
+               }
            }
        }
 
@@ -1982,7 +1987,7 @@ push_overloaded_decl (tree decl, int flags)
                error ("`%#D' conflicts with previous using declaration `%#D'",
                          decl, fn);
 
-             if (duplicate_decls (decl, fn))
+             if (duplicate_decls (decl, fn) == fn)
                POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, fn);
            }
        }