diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 4258b7e8681..429a5700199 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,9 @@ +2001-03-15 Gabriel Dos Reis + + Correct semantics restrictions checking in throw-expression. + * except.c (is_admissible_throw_operand): New function. + (build_throw): Use it. + 2001-03-14 Mark Mitchell * decl.c (cp_make_fnname_decl): Set DECL_IGNORED_P on __FUNCTION__ diff --git a/gcc/cp/except.c b/gcc/cp/except.c index fbfb709d133..595d3d66b28 100644 --- a/gcc/cp/except.c +++ b/gcc/cp/except.c @@ -53,6 +53,7 @@ static tree build_eh_type_type_ref PARAMS ((tree)); static tree build_terminate_handler PARAMS ((void)); static tree alloc_eh_object PARAMS ((tree)); static int complete_ptr_ref_or_void_ptr_p PARAMS ((tree, tree)); +static bool is_admissible_throw_operand PARAMS ((tree)); static int can_convert_eh PARAMS ((tree, tree)); static void check_handlers_1 PARAMS ((tree, tree)); static void initialize_handler_parm PARAMS ((tree)); @@ -1027,7 +1028,7 @@ build_throw (e) if (e != NULL_TREE) { - if (!complete_ptr_ref_or_void_ptr_p (TREE_TYPE (e), e)) + if (!is_admissible_throw_operand (e)) return error_mark_node; } @@ -1070,6 +1071,38 @@ complete_ptr_ref_or_void_ptr_p (type, from) return 1; } +/* Return truth-value if EXPRESSION is admissible in throw-expression, + i.e. if it is not of incomplete type or a pointer/reference to such + a type or of an abstract class type. */ + +static bool +is_admissible_throw_operand (expr) + tree expr; +{ + tree type = TREE_TYPE (expr); + + /* 15.1/4 [...] The type of the throw-expression shall not be an + incomplete type, or a pointer or a reference to an incomplete + type, other than void*, const void*, volatile void*, or + const volatile void*. Except for these restriction and the + restrictions on type matching mentioned in 15.3, the operand + of throw is treated exactly as a function argument in a call + (5.2.2) or the operand of a return statement. */ + if (!complete_ptr_ref_or_void_ptr_p (type, expr)) + return false; + + /* 10.4/3 An abstract class shall not be used as a parameter type, + as a function return type or as type of an explicit + conversion. */ + else if (CLASS_TYPE_P (type) && CLASSTYPE_PURE_VIRTUALS (type)) + { + cp_error ("Expression '%E' of abstract class type '%T' cannot be used in throw-expression", expr, type); + return false; + } + + return true; +} + /* Returns nonzero if FN is a declaration of a standard C library function which is known not to throw. diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 163ef96fef9..12bb57f93dd 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2001-03-15 Gabriel Dos Reis + + * g++.old-deja/g++.other/eh4.C: New test. + 2001-03-14 Neil Booth * gcc.dg/cpp/mi1.c: Update. diff --git a/gcc/testsuite/g++.old-deja/g++.other/eh4.C b/gcc/testsuite/g++.old-deja/g++.other/eh4.C new file mode 100644 index 00000000000..437d9a70958 --- /dev/null +++ b/gcc/testsuite/g++.old-deja/g++.other/eh4.C @@ -0,0 +1,12 @@ +// Origin: Jean-Marc Bourguet +// Build, don't link: + +class foo { +public: + foo() {}; + void throwMe () { + throw *this; // ERROR + }; + virtual void test () = 0; +}; +