]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR c++/24817 (g++ accepts multiple function template declarations even if exceptio...
authorMark Mitchell <mark@codesourcery.com>
Mon, 14 Nov 2005 05:45:45 +0000 (05:45 +0000)
committerMark Mitchell <mmitchel@gcc.gnu.org>
Mon, 14 Nov 2005 05:45:45 +0000 (05:45 +0000)
PR c++/24817
* decl.c (check_redeclaration_exception_specification): New
function.
(duplicate_decls): Use it.
* error.c (fndecl_to_string): Print the template parameter list.
PR c++/24817
* g++.dg/eh/spec8.C: New test.

From-SVN: r106884

gcc/cp/ChangeLog
gcc/cp/decl.c
gcc/cp/error.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/eh/spec8.C [new file with mode: 0644]

index 4fafe495d2e68e2cf3f4924c1cc2d39e2bffabe4..a4f0b8aee03a15ddf95f39fa6cc82e347fc0aa23 100644 (file)
@@ -1,5 +1,11 @@
 2005-11-13  Mark Mitchell  <mark@codesourcery.com>
 
+       PR c++/24817
+       * decl.c (check_redeclaration_exception_specification): New
+       function.
+       (duplicate_decls): Use it.
+       * error.c (fndecl_to_string): Print the template parameter list.
+
        PR c++/20293
        * cxx-pretty-print.c (pp_cxx_statement): Print qualifying scopes
        for namespaces.
index 7263b32d2ee592e339bc7b2facc7d731d721b40c..30d81a727f5a624d8940a55b85ca18237c9c082f 100644 (file)
@@ -1004,6 +1004,41 @@ warn_extern_redeclared_static (tree newdecl, tree olddecl)
   pedwarn ("previous declaration of %q+D", olddecl);
 }
 
+/* NEW_DECL is a redeclaration of OLD_DECL; both are functions or
+   function templates.  If their exception specifications do not
+   match, issue an a diagnostic.  */
+
+static void
+check_redeclaration_exception_specification (tree new_decl,
+                                            tree old_decl)
+{
+  tree new_type;
+  tree old_type;
+  tree new_exceptions;
+  tree old_exceptions;
+
+  new_type = TREE_TYPE (new_decl);
+  new_exceptions = TYPE_RAISES_EXCEPTIONS (new_type);
+  old_type = TREE_TYPE (old_decl);
+  old_exceptions = TYPE_RAISES_EXCEPTIONS (old_type);
+
+  /* [except.spec]
+
+     If any declaration of a function has an exception-specification,
+     all declarations, including the definition and an explicit
+     specialization, of that function shall have an
+     exception-specification with the same set of type-ids.  */
+  if ((pedantic || ! DECL_IN_SYSTEM_HEADER (old_decl))
+      && ! DECL_IS_BUILTIN (old_decl)
+      && flag_exceptions
+      && !comp_except_specs (new_exceptions, old_exceptions, 
+                            /*exact=*/true))
+    {
+      error ("declaration of %qF throws different exceptions", new_decl);
+      error ("from previous declaration %q+F", old_decl);
+    }
+}
+
 /* 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.
@@ -1495,30 +1530,35 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
 
   if (TREE_CODE (newdecl) == TEMPLATE_DECL)
     {
-      TREE_TYPE (olddecl) = TREE_TYPE (DECL_TEMPLATE_RESULT (olddecl));
+      tree old_result;
+      tree new_result;
+      old_result = DECL_TEMPLATE_RESULT (olddecl);
+      new_result = DECL_TEMPLATE_RESULT (newdecl);
+      TREE_TYPE (olddecl) = TREE_TYPE (old_result);
       DECL_TEMPLATE_SPECIALIZATIONS (olddecl)
        = chainon (DECL_TEMPLATE_SPECIALIZATIONS (olddecl),
                   DECL_TEMPLATE_SPECIALIZATIONS (newdecl));
 
+      if (DECL_FUNCTION_TEMPLATE_P (newdecl))
+       {
+         DECL_INLINE (old_result)
+           |= DECL_INLINE (new_result);
+         DECL_DECLARED_INLINE_P (old_result)
+           |= DECL_DECLARED_INLINE_P (new_result);
+         check_redeclaration_exception_specification (newdecl, olddecl);
+       }
+
       /* If the new declaration is a definition, update the file and
         line information on the declaration.  */
-      if (DECL_INITIAL (DECL_TEMPLATE_RESULT (olddecl)) == NULL_TREE
-         && DECL_INITIAL (DECL_TEMPLATE_RESULT (newdecl)) != NULL_TREE)
+      if (DECL_INITIAL (old_result) == NULL_TREE
+         && DECL_INITIAL (new_result) != NULL_TREE)
        {
          DECL_SOURCE_LOCATION (olddecl)
-           = DECL_SOURCE_LOCATION (DECL_TEMPLATE_RESULT (olddecl))
+           = DECL_SOURCE_LOCATION (old_result)
            = DECL_SOURCE_LOCATION (newdecl);
          if (DECL_FUNCTION_TEMPLATE_P (newdecl))
-           DECL_ARGUMENTS (DECL_TEMPLATE_RESULT (olddecl))
-             = DECL_ARGUMENTS (DECL_TEMPLATE_RESULT (newdecl));
-       }
-
-      if (DECL_FUNCTION_TEMPLATE_P (newdecl))
-       {
-         DECL_INLINE (DECL_TEMPLATE_RESULT (olddecl))
-           |= DECL_INLINE (DECL_TEMPLATE_RESULT (newdecl));
-         DECL_DECLARED_INLINE_P (DECL_TEMPLATE_RESULT (olddecl))
-           |= DECL_DECLARED_INLINE_P (DECL_TEMPLATE_RESULT (newdecl));
+           DECL_ARGUMENTS (old_result)
+             = DECL_ARGUMENTS (new_result);
        }
 
       return olddecl;
@@ -1550,26 +1590,8 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
 
       /* Do this after calling `merge_types' so that default
         parameters don't confuse us.  */
-      else if (TREE_CODE (newdecl) == FUNCTION_DECL
-         && (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (newdecl))
-             != TYPE_RAISES_EXCEPTIONS (TREE_TYPE (olddecl))))
-       {
-         TREE_TYPE (newdecl) = build_exception_variant (newtype,
-                                                        TYPE_RAISES_EXCEPTIONS (TREE_TYPE (newdecl)));
-         TREE_TYPE (olddecl) = build_exception_variant (newtype,
-                                                        TYPE_RAISES_EXCEPTIONS (oldtype));
-
-         if ((pedantic || ! DECL_IN_SYSTEM_HEADER (olddecl))
-             && ! DECL_IS_BUILTIN (olddecl)
-             && flag_exceptions
-             && !comp_except_specs (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (newdecl)),
-                                    TYPE_RAISES_EXCEPTIONS (TREE_TYPE (olddecl)), 1))
-           {
-             error ("declaration of %qF throws different exceptions",
-                    newdecl);
-             error ("than previous declaration %q+F", olddecl);
-           }
-       }
+      else if (TREE_CODE (newdecl) == FUNCTION_DECL)
+       check_redeclaration_exception_specification (newdecl, olddecl);
       TREE_TYPE (newdecl) = TREE_TYPE (olddecl) = newtype;
 
       /* Lay the type out, unless already done.  */
index 22c2d304d88ca02e84dfb14619d2a2a766fcd57e..674e407055fb48e0009d1e796a3d9f4a62af09b1 100644 (file)
@@ -2008,7 +2008,8 @@ fndecl_to_string (tree fndecl, int verbose)
 {
   int flags;
 
-  flags = TFF_EXCEPTION_SPECIFICATION | TFF_DECL_SPECIFIERS;
+  flags = TFF_EXCEPTION_SPECIFICATION | TFF_DECL_SPECIFIERS
+    | TFF_TEMPLATE_HEADER;
   if (verbose)
     flags |= TFF_FUNCTION_DEFAULT_ARGUMENTS;
   reinit_cxx_pp ();
index 7c192b0d053ef064f1526139cbf84db365f64cb3..6f9167fd4fbf5f1f03c125c11615cec496e6eb59 100644 (file)
@@ -1,3 +1,8 @@
+2005-11-13  Mark Mitchell  <mark@codesourcery.com>
+
+       PR c++/24817
+       * g++.dg/eh/spec8.C: New test.
+
 2005-11-14  Hans-Peter Nilsson  <hp@axis.com>
 
        * gcc.dg/pack-test-1.c: Gate on ! default_packed.
diff --git a/gcc/testsuite/g++.dg/eh/spec8.C b/gcc/testsuite/g++.dg/eh/spec8.C
new file mode 100644 (file)
index 0000000..7a35e6e
--- /dev/null
@@ -0,0 +1,11 @@
+// PR c++/24817
+
+struct exception {};
+
+template <typename T> void foo() throw(exception); // { dg-error "declaration" }
+template <typename T> void foo(); // { dg-error "exceptions" }
+
+struct bar
+{
+  template <typename T> friend void foo(); // { dg-error "exceptions" }
+};