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:
parent
65e32b88a6
commit
5aa3396cd4
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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))
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
22
gcc/testsuite/g++.dg/eh/spec5.C
Normal file
22
gcc/testsuite/g++.dg/eh/spec5.C
Normal 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();
|
||||
}
|
19
gcc/testsuite/g++.dg/eh/spec6.C
Normal file
19
gcc/testsuite/g++.dg/eh/spec6.C
Normal 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" }
|
||||
}
|
Loading…
Reference in New Issue
Block a user