Commit e1f0e7a6 by Mark Mitchell Committed by Mark Mitchell

re PR c++/24817 (g++ accepts multiple function template declarations even if…

re PR c++/24817 (g++ accepts multiple function template declarations even if exception-specification doesn't match.)

	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
parent c748a2c7
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.
......
......@@ -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. */
......
......@@ -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 ();
......
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.
// 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" }
};
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment