aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarek Polacek <polacek@redhat.com>2018-05-16 20:37:45 +0000
committerMarek Polacek <mpolacek@gcc.gnu.org>2018-05-16 20:37:45 +0000
commit0932d398ef91373c74d8ad08f26f484206bc8fc9 (patch)
treef07207965ef5224f6862314f5e9d2f16fbee6150
parent110fb19f6c6a4a9dfb9cfe00d3295cccf5b00507 (diff)
downloadgcc-0932d398ef91373c74d8ad08f26f484206bc8fc9.zip
gcc-0932d398ef91373c74d8ad08f26f484206bc8fc9.tar.gz
gcc-0932d398ef91373c74d8ad08f26f484206bc8fc9.tar.bz2
re PR c++/85363 (Throwing exception from member constructor (brace initializer vs initializer list))
PR c++/85363 * call.c (set_flags_from_callee): Handle AGGR_INIT_EXPRs too. * tree.c (bot_manip): Call set_flags_from_callee for AGGR_INIT_EXPRs too. * g++.dg/cpp0x/initlist-throw1.C: New test. * g++.dg/cpp0x/initlist-throw2.C: New test. From-SVN: r260300
-rw-r--r--gcc/cp/ChangeLog7
-rw-r--r--gcc/cp/call.c14
-rw-r--r--gcc/cp/tree.c2
-rw-r--r--gcc/testsuite/ChangeLog7
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/initlist-throw1.C29
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/initlist-throw2.C33
6 files changed, 85 insertions, 7 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 3ccaebe..7d3f0c2 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,10 @@
+2018-05-16 Marek Polacek <polacek@redhat.com>
+
+ PR c++/85363
+ * call.c (set_flags_from_callee): Handle AGGR_INIT_EXPRs too.
+ * tree.c (bot_manip): Call set_flags_from_callee for
+ AGGR_INIT_EXPRs too.
+
2018-05-15 Jason Merrill <jason@redhat.com>
* cp-tree.h (cp_expr): Remove copy constructor.
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 09a3618..4d04785 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -319,15 +319,17 @@ build_call_n (tree function, int n, ...)
void
set_flags_from_callee (tree call)
{
- bool nothrow;
- tree decl = get_callee_fndecl (call);
+ /* Handle both CALL_EXPRs and AGGR_INIT_EXPRs. */
+ tree decl = cp_get_callee_fndecl_nofold (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);
- if (CALL_EXPR_FN (call))
- nothrow |= TYPE_NOTHROW_P (TREE_TYPE (TREE_TYPE (CALL_EXPR_FN (call))));
- else if (internal_fn_flags (CALL_EXPR_IFN (call)) & ECF_NOTHROW)
+ bool nothrow = decl && TREE_NOTHROW (decl);
+ tree callee = cp_get_callee (call);
+ if (callee)
+ nothrow |= TYPE_NOTHROW_P (TREE_TYPE (TREE_TYPE (callee)));
+ else if (TREE_CODE (call) == CALL_EXPR
+ && internal_fn_flags (CALL_EXPR_IFN (call)) & ECF_NOTHROW)
nothrow = true;
if (!nothrow && at_function_scope_p () && cfun && cp_function_chain)
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index ecb88df..db81da9 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -2987,7 +2987,7 @@ bot_manip (tree* tp, int* walk_subtrees, void* data_)
/* Make a copy of this node. */
t = copy_tree_r (tp, walk_subtrees, NULL);
- if (TREE_CODE (*tp) == CALL_EXPR)
+ if (TREE_CODE (*tp) == CALL_EXPR || TREE_CODE (*tp) == AGGR_INIT_EXPR)
set_flags_from_callee (*tp);
if (data.clear_location && EXPR_HAS_LOCATION (*tp))
SET_EXPR_LOCATION (*tp, input_location);
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 186fece..9eab3ad 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,4 +1,11 @@
+2018-05-16 Marek Polacek <polacek@redhat.com>
+
+ PR c++/85363
+ * g++.dg/cpp0x/initlist-throw1.C: New test.
+ * g++.dg/cpp0x/initlist-throw2.C: New test.
+
2018-05-16 Carl Love <cel@us.ibm.com>
+
* gcc.target/powerpc/vsx-vector-6-be.c: Remove file.
* gcc.target/powerpc/vsx-vector-6-be.p7.c: New test file.
* gcc.target/powerpc/vsx-vector-6-be.p8.c: New test file.
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist-throw1.C b/gcc/testsuite/g++.dg/cpp0x/initlist-throw1.C
new file mode 100644
index 0000000..264c6c7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist-throw1.C
@@ -0,0 +1,29 @@
+// PR c++/85363
+// { dg-do run { target c++11 } }
+
+int
+init (int f)
+{
+ throw f;
+}
+
+struct X {
+ X (int f) : n {init (f)} {}
+ int n;
+};
+
+struct P {
+ X x{20};
+};
+
+int
+main ()
+{
+ try {
+ P p {};
+ }
+ catch (int n) {
+ return 0;
+ }
+ return 1;
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist-throw2.C b/gcc/testsuite/g++.dg/cpp0x/initlist-throw2.C
new file mode 100644
index 0000000..2bb0583
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist-throw2.C
@@ -0,0 +1,33 @@
+// PR c++/85363
+// { dg-do run { target c++11 } }
+
+int
+init (int f)
+{
+ throw f;
+}
+
+struct X {
+ X () : n {init (42)} {}
+ int n;
+};
+
+struct P {
+ struct R {
+ struct Q {
+ X x = {};
+ } q;
+ } r;
+};
+
+int
+main ()
+{
+ try {
+ P p {};
+ }
+ catch (int n) {
+ return 0;
+ }
+ return 1;
+}