diff options
Diffstat (limited to 'gcc/cp/decl.c')
-rw-r--r-- | gcc/cp/decl.c | 90 |
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. */ |