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
This commit is contained in:
Jason Merrill 2002-09-04 19:24:00 -04:00 committed by Jason Merrill
parent 65e32b88a6
commit 5aa3396cd4
7 changed files with 122 additions and 16 deletions

View File

@ -1,3 +1,14 @@
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>
* decl.c (start_cleanup_fn): Clear interface_only before

View File

@ -356,6 +356,7 @@ build_call (function, parms)
tree tmp;
tree decl;
tree result_type;
tree fntype;
function = build_addr_func (function);
@ -365,7 +366,8 @@ build_call (function, parms)
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
&& TREE_CODE (TREE_OPERAND (function, 0)) == FUNCTION_DECL)
@ -383,6 +385,7 @@ build_call (function, parms)
if (decl && TREE_DEPRECATED (decl))
warn_deprecated_use (decl);
require_complete_eh_spec_types (fntype, decl);
if (decl && DECL_CONSTRUCTOR_P (decl))
is_constructor = 1;

View File

@ -1198,7 +1198,8 @@ get_pseudo_ti_desc (type)
return ptm_desc_type_node;
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;
}
else if (!CLASSTYPE_N_BASECLASSES (type))

View File

@ -155,16 +155,16 @@ complete_type (type)
return type;
}
/* Like complete_type, but issue an error if the TYPE cannot be
completed. VALUE is used for informative diagnostics. WARN_ONLY
will cause a warning message to be printed, instead of an error.
/* Like complete_type, but issue an error if the TYPE cannot be completed.
VALUE is used for informative diagnostics. DIAG_TYPE indicates the type
of diagnostic: 0 for an error, 1 for a warning, 2 for a pedwarn.
Returns NULL_TREE if the type cannot be made complete. */
tree
complete_type_or_diagnostic (type, value, warn_only)
complete_type_or_diagnostic (type, value, diag_type)
tree type;
tree value;
int warn_only;
int diag_type;
{
type = complete_type (type);
if (type == error_mark_node)
@ -172,7 +172,7 @@ complete_type_or_diagnostic (type, value, warn_only)
return NULL_TREE;
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;
}
else

View File

@ -182,24 +182,30 @@ abstract_virtuals_error (decl, 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)
and TYPE is the type that was invalid. If WARN_ONLY is nonzero, a
warning is printed, otherwise an error is printed. */
and TYPE is the type that was invalid. DIAG_TYPE indicates the
type of diagnostic: 0 for an error, 1 for a warning, 2 for a
pedwarn. */
void
cxx_incomplete_type_diagnostic (value, type, warn_only)
cxx_incomplete_type_diagnostic (value, type, diag_type)
tree value;
tree type;
int warn_only;
int diag_type;
{
int decl = 0;
void (*p_msg) PARAMS ((const char *, ...));
void (*p_msg_at) PARAMS ((const char *, ...));
if (warn_only)
if (diag_type == 1)
{
p_msg = warning;
p_msg_at = cp_warning_at;
}
else if (diag_type == 2)
{
p_msg = pedwarn;
p_msg_at = cp_pedwarn_at;
}
else
{
p_msg = error;
@ -1345,6 +1351,7 @@ add_exception_specifier (list, spec, complain)
int ok;
tree core = spec;
int is_ptr;
int diag_type = -1; /* none */
if (spec == error_mark_node)
return list;
@ -1366,7 +1373,15 @@ add_exception_specifier (list, spec, complain)
else if (processing_template_decl)
ok = 1;
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)
{
@ -1378,8 +1393,12 @@ add_exception_specifier (list, spec, complain)
if (!probe)
list = tree_cons (NULL_TREE, spec, list);
}
else if (complain)
cxx_incomplete_type_error (NULL_TREE, core);
else
diag_type = 0; /* error */
if (diag_type >= 0 && complain)
cxx_incomplete_type_diagnostic (NULL_TREE, core, diag_type);
return list;
}
@ -1418,3 +1437,34 @@ merge_exception_specifiers (list, add)
}
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);
}
}
}

View File

@ -0,0 +1,22 @@
// 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();
}

View File

@ -0,0 +1,19 @@
// 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" }
}