]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
typeck2.c (add_exception_specifier): Only pedwarn for an incomplete type.
authorJason Merrill <jason@redhat.com>
Wed, 4 Sep 2002 23:24:00 +0000 (19:24 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Wed, 4 Sep 2002 23:24:00 +0000 (19:24 -0400)
        * 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

gcc/cp/ChangeLog
gcc/cp/call.c
gcc/cp/rtti.c
gcc/cp/typeck.c
gcc/cp/typeck2.c
gcc/testsuite/g++.dg/eh/spec5.C [new file with mode: 0644]
gcc/testsuite/g++.dg/eh/spec6.C [new file with mode: 0644]

index c701767f0eba55adb65b39bf36c0262c1312ef9c..6cbd01ef2444a3c59ccee536466110b1427ced81 100644 (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
index cbd7faf31a92af6d311c0e81dd1fcc519319852e..36819449bc0eb5a8e85010118aaf91ea09551c5e 100644 (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;
index 0584d60785c49be112ec757d94aafa361046d02b..3f671fc30f4fa49c6993eb4c9df8862ffe36069f 100644 (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))
index 8535cde4ae70f4f525fac07b25bfdeaa0feb0861..80da1ed0caaa8c396f1ec9957aa5221b273915c8 100644 (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
index e4d7e3eb0a2a429c632655374144073aade1ceaf..67d880905ddb24d7c8ecacc8f1850f7504e7951f 100644 (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);
+       }
+    }
+}
diff --git a/gcc/testsuite/g++.dg/eh/spec5.C b/gcc/testsuite/g++.dg/eh/spec5.C
new file mode 100644 (file)
index 0000000..be8f327
--- /dev/null
@@ -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 (file)
index 0000000..eb1177b
--- /dev/null
@@ -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" }
+}