re PR c++/50424 (G++ doesn't notice possible throw from default argument)
authorJason Merrill <jason@redhat.com>
Fri, 16 Sep 2011 21:16:16 +0000 (17:16 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Fri, 16 Sep 2011 21:16:16 +0000 (17:16 -0400)
PR c++/50424
* call.c (set_flags_from_callee): Split out from build_call_a.
* cp-tree.h: Declare it.
* tree.c (bot_manip): Call it.

From-SVN: r178918

gcc/cp/ChangeLog
gcc/cp/call.c
gcc/cp/cp-tree.h
gcc/cp/tree.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/eh/defarg1.C [new file with mode: 0644]

index c52dcd76e18e812c8a979ae8b2223e16c3e1ec67..a6de5fae3c7e1210aeb7deaae99337dbe0b50234 100644 (file)
@@ -1,3 +1,10 @@
+2011-09-16  Jason Merrill  <jason@redhat.com>
+
+       PR c++/50424
+       * call.c (set_flags_from_callee): Split out from build_call_a.
+       * cp-tree.h: Declare it.
+       * tree.c (bot_manip): Call it.
+
 2011-09-15  Jason Merrill  <jason@redhat.com>
 
        PR c++/50365
index 81df80ed88ecd093d7488a2781cf13a8d6acc567..bdbede7fbe646860592c9327d3075981e0dcaf87 100644 (file)
@@ -306,11 +306,32 @@ build_call_n (tree function, int n, ...)
     }
 }
 
+/* Update various flags in cfun and the call itself based on what is being
+   called.  Split out of build_call_a so that bot_manip can use it too.  */
+
+void
+set_flags_from_callee (tree call)
+{
+  int nothrow;
+  tree decl = get_callee_fndecl (call);
+
+  /* We check both the decl and the type; a function may be known not to
+     throw without being declared throw().  */
+  nothrow = ((decl && TREE_NOTHROW (decl))
+            || TYPE_NOTHROW_P (TREE_TYPE (TREE_TYPE (CALL_EXPR_FN (call)))));
+
+  if (!nothrow && at_function_scope_p () && cfun && cp_function_chain)
+    cp_function_chain->can_throw = 1;
+
+  if (decl && TREE_THIS_VOLATILE (decl) && cfun && cp_function_chain)
+    current_function_returns_abnormally = 1;
+
+  TREE_NOTHROW (call) = nothrow;
+}
+
 tree
 build_call_a (tree function, int n, tree *argarray)
 {
-  int is_constructor = 0;
-  int nothrow;
   tree decl;
   tree result_type;
   tree fntype;
@@ -327,60 +348,45 @@ build_call_a (tree function, int n, tree *argarray)
   if (SCALAR_TYPE_P (result_type) || VOID_TYPE_P (result_type))
     result_type = cv_unqualified (result_type);
 
-  if (TREE_CODE (function) == ADDR_EXPR
-      && TREE_CODE (TREE_OPERAND (function, 0)) == FUNCTION_DECL)
-    {
-      decl = TREE_OPERAND (function, 0);
-      if (!TREE_USED (decl))
-       {
-         /* We invoke build_call directly for several library
-            functions.  These may have been declared normally if
-            we're building libgcc, so we can't just check
-            DECL_ARTIFICIAL.  */
-         gcc_assert (DECL_ARTIFICIAL (decl)
-                     || !strncmp (IDENTIFIER_POINTER (DECL_NAME (decl)),
-                                  "__", 2));
-         mark_used (decl);
-       }
-    }
-  else
-    decl = NULL_TREE;
-
-  /* We check both the decl and the type; a function may be known not to
-     throw without being declared throw().  */
-  nothrow = ((decl && TREE_NOTHROW (decl))
-            || TYPE_NOTHROW_P (TREE_TYPE (TREE_TYPE (function))));
+  function = build_call_array_loc (input_location,
+                                  result_type, function, n, argarray);
+  set_flags_from_callee (function);
 
-  if (!nothrow && at_function_scope_p () && cfun && cp_function_chain)
-    cp_function_chain->can_throw = 1;
+  decl = get_callee_fndecl (function);
 
-  if (decl && TREE_THIS_VOLATILE (decl) && cfun && cp_function_chain)
-    current_function_returns_abnormally = 1;
+  if (decl && !TREE_USED (decl))
+    {
+      /* We invoke build_call directly for several library
+        functions.  These may have been declared normally if
+        we're building libgcc, so we can't just check
+        DECL_ARTIFICIAL.  */
+      gcc_assert (DECL_ARTIFICIAL (decl)
+                 || !strncmp (IDENTIFIER_POINTER (DECL_NAME (decl)),
+                              "__", 2));
+      mark_used (decl);
+    }
 
   if (decl && TREE_DEPRECATED (decl))
     warn_deprecated_use (decl, NULL_TREE);
   require_complete_eh_spec_types (fntype, decl);
 
-  if (decl && DECL_CONSTRUCTOR_P (decl))
-    is_constructor = 1;
+  TREE_HAS_CONSTRUCTOR (function) = (decl && DECL_CONSTRUCTOR_P (decl));
 
   /* Don't pass empty class objects by value.  This is useful
      for tags in STL, which are used to control overload resolution.
      We don't need to handle other cases of copying empty classes.  */
   if (! decl || ! DECL_BUILT_IN (decl))
     for (i = 0; i < n; i++)
-      if (is_empty_class (TREE_TYPE (argarray[i]))
-         && ! TREE_ADDRESSABLE (TREE_TYPE (argarray[i])))
-       {
-         tree t = build0 (EMPTY_CLASS_EXPR, TREE_TYPE (argarray[i]));
-         argarray[i] = build2 (COMPOUND_EXPR, TREE_TYPE (t),
-                               argarray[i], t);
-       }
-
-  function = build_call_array_loc (input_location,
-                                  result_type, function, n, argarray);
-  TREE_HAS_CONSTRUCTOR (function) = is_constructor;
-  TREE_NOTHROW (function) = nothrow;
+      {
+       tree arg = CALL_EXPR_ARG (function, i);
+       if (is_empty_class (TREE_TYPE (arg))
+           && ! TREE_ADDRESSABLE (TREE_TYPE (arg)))
+         {
+           tree t = build0 (EMPTY_CLASS_EXPR, TREE_TYPE (arg));
+           arg = build2 (COMPOUND_EXPR, TREE_TYPE (t), arg, t);
+           CALL_EXPR_ARG (function, i) = arg;
+         }
+      }
 
   return function;
 }
@@ -6736,7 +6742,6 @@ build_cxx_call (tree fn, int nargs, tree *argarray)
   fn = build_call_a (fn, nargs, argarray);
   SET_EXPR_LOCATION (fn, loc);
 
-  /* If this call might throw an exception, note that fact.  */
   fndecl = get_callee_fndecl (fn);
 
   /* Check that arguments to builtin functions match the expectations.  */
index 12a289571df00d25e07cfbf18f833f79bc646d21..8e52e282a3bb16ae0382f0bcaac7663175d25104 100644 (file)
@@ -4721,6 +4721,7 @@ extern bool check_dtor_name                       (tree, tree);
 extern tree build_conditional_expr             (tree, tree, tree, 
                                                  tsubst_flags_t);
 extern tree build_addr_func                    (tree);
+extern void set_flags_from_callee              (tree);
 extern tree build_call_a                       (tree, int, tree*);
 extern tree build_call_n                       (tree, int, ...);
 extern bool null_ptr_cst_p                     (tree);
index 13421a4e7ab2d21c29c42e1a1aff1f8bfe64673e..998795302c341a190060134a17c211d1a6c06777 100644 (file)
@@ -1898,7 +1898,10 @@ bot_manip (tree* tp, int* walk_subtrees, void* data)
     }
 
   /* Make a copy of this node.  */
-  return copy_tree_r (tp, walk_subtrees, NULL);
+  t = copy_tree_r (tp, walk_subtrees, NULL);
+  if (TREE_CODE (*tp) == CALL_EXPR)
+    set_flags_from_callee (*tp);
+  return t;
 }
 
 /* Replace all remapped VAR_DECLs in T with their new equivalents.
index 010f028ac3c477a146fa5a2072b292089142a0ad..220bfa580416e1f0cf7d5f2f6083421beb9cd8a6 100644 (file)
@@ -1,3 +1,8 @@
+2011-09-16  Jason Merrill  <jason@redhat.com>
+
+       PR c++/50424
+       * g++.dg/eh/defarg1.C: New.
+
 2011-09-16  Jakub Jelinek  <jakub@redhat.com>
 
        * gcc.dg/vect/vect-reduc-10.c: New test.
diff --git a/gcc/testsuite/g++.dg/eh/defarg1.C b/gcc/testsuite/g++.dg/eh/defarg1.C
new file mode 100644 (file)
index 0000000..5c6e4df
--- /dev/null
@@ -0,0 +1,10 @@
+// PR c++/50424
+// { dg-do run }
+
+int f() { throw 1; }
+void g( int = f() ) { }
+void h() { g(); }
+int main()
+{
+  try { h(); } catch (int) { }
+}