Commit 5aa3396c by Jason Merrill Committed by Jason Merrill

typeck2.c (add_exception_specifier): Only pedwarn for an incomplete type.

        * typeck2.c (add_exception_specifier): Only pedwarn for an
        incomplete type.
        (require_complete_eh_spec_types): New fn.
        (cxx_incomplete_type_diagnostic): Also support pedwarning.
        * typeck.c (complete_type_or_diagnostic): Likewise.
        * call.c (build_call): Call require_complete_eh_spec_types.
        * rtti.c (get_pseudo_ti_desc): Give an error rather than aborting
        on an incomplete type.

From-SVN: r56822
parent 65e32b88
2002-09-05 Jason Merrill <jason@redhat.com>
* typeck2.c (add_exception_specifier): Only pedwarn for an
incomplete type.
(require_complete_eh_spec_types): New fn.
(cxx_incomplete_type_diagnostic): Also support pedwarning.
* typeck.c (complete_type_or_diagnostic): Likewise.
* call.c (build_call): Call require_complete_eh_spec_types.
* rtti.c (get_pseudo_ti_desc): Give an error rather than aborting
on an incomplete type.
2002-09-04 Jakub Jelinek <jakub@redhat.com> 2002-09-04 Jakub Jelinek <jakub@redhat.com>
* decl.c (start_cleanup_fn): Clear interface_only before * decl.c (start_cleanup_fn): Clear interface_only before
......
...@@ -356,6 +356,7 @@ build_call (function, parms) ...@@ -356,6 +356,7 @@ build_call (function, parms)
tree tmp; tree tmp;
tree decl; tree decl;
tree result_type; tree result_type;
tree fntype;
function = build_addr_func (function); function = build_addr_func (function);
...@@ -365,7 +366,8 @@ build_call (function, parms) ...@@ -365,7 +366,8 @@ build_call (function, parms)
return error_mark_node; return error_mark_node;
} }
result_type = TREE_TYPE (TREE_TYPE (TREE_TYPE (function))); fntype = TREE_TYPE (TREE_TYPE (function));
result_type = TREE_TYPE (fntype);
if (TREE_CODE (function) == ADDR_EXPR if (TREE_CODE (function) == ADDR_EXPR
&& TREE_CODE (TREE_OPERAND (function, 0)) == FUNCTION_DECL) && TREE_CODE (TREE_OPERAND (function, 0)) == FUNCTION_DECL)
...@@ -383,6 +385,7 @@ build_call (function, parms) ...@@ -383,6 +385,7 @@ build_call (function, parms)
if (decl && TREE_DEPRECATED (decl)) if (decl && TREE_DEPRECATED (decl))
warn_deprecated_use (decl); warn_deprecated_use (decl);
require_complete_eh_spec_types (fntype, decl);
if (decl && DECL_CONSTRUCTOR_P (decl)) if (decl && DECL_CONSTRUCTOR_P (decl))
is_constructor = 1; is_constructor = 1;
......
...@@ -1198,7 +1198,8 @@ get_pseudo_ti_desc (type) ...@@ -1198,7 +1198,8 @@ get_pseudo_ti_desc (type)
return ptm_desc_type_node; return ptm_desc_type_node;
else if (!COMPLETE_TYPE_P (type)) else if (!COMPLETE_TYPE_P (type))
{ {
my_friendly_assert (at_eof, 20020609); if (!at_eof)
cxx_incomplete_type_error (NULL_TREE, type);
return class_desc_type_node; return class_desc_type_node;
} }
else if (!CLASSTYPE_N_BASECLASSES (type)) else if (!CLASSTYPE_N_BASECLASSES (type))
......
...@@ -155,16 +155,16 @@ complete_type (type) ...@@ -155,16 +155,16 @@ complete_type (type)
return type; return type;
} }
/* Like complete_type, but issue an error if the TYPE cannot be /* Like complete_type, but issue an error if the TYPE cannot be completed.
completed. VALUE is used for informative diagnostics. WARN_ONLY VALUE is used for informative diagnostics. DIAG_TYPE indicates the type
will cause a warning message to be printed, instead of an error. of diagnostic: 0 for an error, 1 for a warning, 2 for a pedwarn.
Returns NULL_TREE if the type cannot be made complete. */ Returns NULL_TREE if the type cannot be made complete. */
tree tree
complete_type_or_diagnostic (type, value, warn_only) complete_type_or_diagnostic (type, value, diag_type)
tree type; tree type;
tree value; tree value;
int warn_only; int diag_type;
{ {
type = complete_type (type); type = complete_type (type);
if (type == error_mark_node) if (type == error_mark_node)
...@@ -172,7 +172,7 @@ complete_type_or_diagnostic (type, value, warn_only) ...@@ -172,7 +172,7 @@ complete_type_or_diagnostic (type, value, warn_only)
return NULL_TREE; return NULL_TREE;
else if (!COMPLETE_TYPE_P (type)) else if (!COMPLETE_TYPE_P (type))
{ {
cxx_incomplete_type_diagnostic (value, type, warn_only); cxx_incomplete_type_diagnostic (value, type, diag_type);
return NULL_TREE; return NULL_TREE;
} }
else else
......
...@@ -182,24 +182,30 @@ abstract_virtuals_error (decl, type) ...@@ -182,24 +182,30 @@ abstract_virtuals_error (decl, type)
/* Print an error message for invalid use of an incomplete type. /* Print an error message for invalid use of an incomplete type.
VALUE is the expression that was used (or 0 if that isn't known) VALUE is the expression that was used (or 0 if that isn't known)
and TYPE is the type that was invalid. If WARN_ONLY is nonzero, a and TYPE is the type that was invalid. DIAG_TYPE indicates the
warning is printed, otherwise an error is printed. */ type of diagnostic: 0 for an error, 1 for a warning, 2 for a
pedwarn. */
void void
cxx_incomplete_type_diagnostic (value, type, warn_only) cxx_incomplete_type_diagnostic (value, type, diag_type)
tree value; tree value;
tree type; tree type;
int warn_only; int diag_type;
{ {
int decl = 0; int decl = 0;
void (*p_msg) PARAMS ((const char *, ...)); void (*p_msg) PARAMS ((const char *, ...));
void (*p_msg_at) PARAMS ((const char *, ...)); void (*p_msg_at) PARAMS ((const char *, ...));
if (warn_only) if (diag_type == 1)
{ {
p_msg = warning; p_msg = warning;
p_msg_at = cp_warning_at; p_msg_at = cp_warning_at;
} }
else if (diag_type == 2)
{
p_msg = pedwarn;
p_msg_at = cp_pedwarn_at;
}
else else
{ {
p_msg = error; p_msg = error;
...@@ -1345,6 +1351,7 @@ add_exception_specifier (list, spec, complain) ...@@ -1345,6 +1351,7 @@ add_exception_specifier (list, spec, complain)
int ok; int ok;
tree core = spec; tree core = spec;
int is_ptr; int is_ptr;
int diag_type = -1; /* none */
if (spec == error_mark_node) if (spec == error_mark_node)
return list; return list;
...@@ -1366,7 +1373,15 @@ add_exception_specifier (list, spec, complain) ...@@ -1366,7 +1373,15 @@ add_exception_specifier (list, spec, complain)
else if (processing_template_decl) else if (processing_template_decl)
ok = 1; ok = 1;
else else
ok = COMPLETE_TYPE_P (complete_type (core)); {
ok = 1;
/* 15.4/1 says that types in an exception specifier must be complete,
but it seems more reasonable to only require this on definitions
and calls. So just give a pedwarn at this point; we will give an
error later if we hit one of those two cases. */
if (!COMPLETE_TYPE_P (complete_type (core)))
diag_type = 2; /* pedwarn */
}
if (ok) if (ok)
{ {
...@@ -1378,8 +1393,12 @@ add_exception_specifier (list, spec, complain) ...@@ -1378,8 +1393,12 @@ add_exception_specifier (list, spec, complain)
if (!probe) if (!probe)
list = tree_cons (NULL_TREE, spec, list); list = tree_cons (NULL_TREE, spec, list);
} }
else if (complain) else
cxx_incomplete_type_error (NULL_TREE, core); diag_type = 0; /* error */
if (diag_type >= 0 && complain)
cxx_incomplete_type_diagnostic (NULL_TREE, core, diag_type);
return list; return list;
} }
...@@ -1418,3 +1437,34 @@ merge_exception_specifiers (list, add) ...@@ -1418,3 +1437,34 @@ merge_exception_specifiers (list, add)
} }
return list; return list;
} }
/* Subroutine of build_call. Ensure that each of the types in the
exception specification is complete. Technically, 15.4/1 says that
they need to be complete when we see a declaration of the function,
but we should be able to get away with only requiring this when the
function is defined or called. See also add_exception_specifier. */
void
require_complete_eh_spec_types (fntype, decl)
tree fntype, decl;
{
tree raises;
/* Don't complain about calls to op new. */
if (decl && DECL_ARTIFICIAL (decl))
return;
for (raises = TYPE_RAISES_EXCEPTIONS (fntype); raises;
raises = TREE_CHAIN (raises))
{
tree type = TREE_VALUE (raises);
if (type && !COMPLETE_TYPE_P (type))
{
if (decl)
error
("call to function `%D' which throws incomplete type `%#T'",
decl, type);
else
error ("call to function which throws incomplete type `%#T'",
decl);
}
}
}
// Test for extension to allow incomplete types in an
// exception-specification for a declaration.
// { dg-do run }
// { dg-options "-fpermissive -w" }
struct A;
struct B
{
void f () throw (A);
};
struct A {};
void B::f () throw (A) {}
int main ()
{
B b;
b.f();
}
// Test that we don't allow incomplete types in an exception-specification
// for a definition, or at a call site.
// { dg-options "-fpermissive -w" }
struct A; // { dg-error "" }
struct B
{
void f () throw (A);
};
void B::f () throw (A) {} // { dg-error "A" }
int main ()
{
B b;
b.f(); // { dg-error "A" }
}
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