aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/decl.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cp/decl.c')
-rw-r--r--gcc/cp/decl.c90
1 files changed, 56 insertions, 34 deletions
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index c6ee7cb3b92..6e0c5dca02d 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -1064,6 +1064,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.
@@ -1555,30 +1590,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;
@@ -1622,26 +1662,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. */