aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/cp/ChangeLog11
-rw-r--r--gcc/cp/call.c5
-rw-r--r--gcc/cp/rtti.c3
-rw-r--r--gcc/cp/typeck.c12
-rw-r--r--gcc/cp/typeck2.c66
-rw-r--r--gcc/testsuite/g++.dg/eh/spec5.C22
-rw-r--r--gcc/testsuite/g++.dg/eh/spec6.C19
7 files changed, 122 insertions, 16 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index c701767..6cbd01e 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index cbd7faf..3681944 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -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;
diff --git a/gcc/cp/rtti.c b/gcc/cp/rtti.c
index 0584d60..3f671fc 100644
--- a/gcc/cp/rtti.c
+++ b/gcc/cp/rtti.c
@@ -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))
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 8535cde..80da1ed 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -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
diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c
index e4d7e3e..67d8809 100644
--- a/gcc/cp/typeck2.c
+++ b/gcc/cp/typeck2.c
@@ -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);
+ }
+ }
+}
diff --git a/gcc/testsuite/g++.dg/eh/spec5.C b/gcc/testsuite/g++.dg/eh/spec5.C
new file mode 100644
index 0000000..be8f327
--- /dev/null
+++ b/gcc/testsuite/g++.dg/eh/spec5.C
@@ -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();
+}
diff --git a/gcc/testsuite/g++.dg/eh/spec6.C b/gcc/testsuite/g++.dg/eh/spec6.C
new file mode 100644
index 0000000..eb1177b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/eh/spec6.C
@@ -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" }
+}