re PR c++/53025 ([C++11] noexcept operator depends on copy-elision)
authorPaolo Carlini <paolo.carlini@oracle.com>
Thu, 2 Oct 2014 18:05:55 +0000 (18:05 +0000)
committerPaolo Carlini <paolo@gcc.gnu.org>
Thu, 2 Oct 2014 18:05:55 +0000 (18:05 +0000)
/cp
2014-10-02  Paolo Carlini  <paolo.carlini@oracle.com>

PR c++/53025
* cp-tree.h (struct saved_scope): Add noexcept_operand.
(cp_noexcept_operand): Define.
* call.c (build_over_call): Use it.
* parser.c (cp_parser_unary_expression, [RID_NOEXCEPT]): Likewise.
* pt.c (tsubst_copy_and_build, [NOEXCEPT_EXPR]): Likewise.

/testsuite
2014-10-02  Paolo Carlini  <paolo.carlini@oracle.com>

PR c++/53025
* g++.dg/cpp0x/noexcept23.C: New.
* g++.dg/cpp0x/noexcept24.C: Likewise.

From-SVN: r215813

gcc/cp/ChangeLog
gcc/cp/call.c
gcc/cp/cp-tree.h
gcc/cp/parser.c
gcc/cp/pt.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/cpp0x/noexcept23.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/noexcept24.C [new file with mode: 0644]

index a3cfa05e23d19bb7c0c6741f2545a6e7f8e1b912..b5b3f596bd860337f70c34c2eca730b4f0a8c07d 100644 (file)
@@ -1,3 +1,12 @@
+2014-10-02  Paolo Carlini  <paolo.carlini@oracle.com>
+
+       PR c++/53025
+       * cp-tree.h (struct saved_scope): Add noexcept_operand.
+       (cp_noexcept_operand): Define.
+       * call.c (build_over_call): Use it.
+       * parser.c (cp_parser_unary_expression, [RID_NOEXCEPT]): Likewise.
+       * pt.c (tsubst_copy_and_build, [NOEXCEPT_EXPR]): Likewise.
+
 2014-10-01  Jason Merrill  <jason@redhat.com>
 
        PR c++/63362
index 3c8b338382abdfc7bfcd3ed05be060fb7961150d..347070c9c965d4ed3695b3307652c0f5af13f467 100644 (file)
@@ -7251,7 +7251,11 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
     /* Do things the hard way.  */;
   else if (cand->num_convs == 1 
            && (DECL_COPY_CONSTRUCTOR_P (fn) 
-               || DECL_MOVE_CONSTRUCTOR_P (fn)))
+               || DECL_MOVE_CONSTRUCTOR_P (fn))
+          /* It's unsafe to elide the constructor when handling
+             a noexcept-expression, it may evaluate to the wrong
+             value (c++/53025).  */
+          && cp_noexcept_operand == 0)
     {
       tree targ;
       tree arg = argarray[num_artificial_parms_for (fn)];
index 14ec837dc9c267122ae13fd6c0c9dce55ec402d0..fe1651ef010dc2eeab36ff8f4eda4b60fd284882 100644 (file)
@@ -1058,6 +1058,7 @@ struct GTY(()) saved_scope {
 
   int unevaluated_operand;
   int inhibit_evaluation_warnings;
+  int noexcept_operand;
   /* If non-zero, implicit "omp declare target" attribute is added into the
      attribute lists.  */
   int omp_declare_target_attribute;
@@ -1124,6 +1125,10 @@ struct GTY(()) saved_scope {
 
 #define local_specializations scope_chain->x_local_specializations
 
+/* Nonzero if we are parsing the operand of a noexcept operator.  */
+
+#define cp_noexcept_operand scope_chain->noexcept_operand
+
 /* A list of private types mentioned, for deferred access checking.  */
 
 extern GTY(()) struct saved_scope *scope_chain;
index 01b2fadfe0176ec0417c5db78dfddc989f077cc4..63ed1c0dfea9303f9868b15e0dcd2b187c3ea8a6 100644 (file)
@@ -7156,7 +7156,9 @@ cp_parser_unary_expression (cp_parser *parser, bool address_p, bool cast_p,
 
            ++cp_unevaluated_operand;
            ++c_inhibit_evaluation_warnings;
+           ++cp_noexcept_operand;
            expr = cp_parser_expression (parser);
+           --cp_noexcept_operand;
            --c_inhibit_evaluation_warnings;
            --cp_unevaluated_operand;
 
index f03e74cd514d1c857a4aaea94ffe855b843d2c42..d1dddff3ac2e0bca23dcec6e7ff4b779ef93a955 100644 (file)
@@ -14769,11 +14769,13 @@ tsubst_copy_and_build (tree t,
       op1 = TREE_OPERAND (t, 0);
       ++cp_unevaluated_operand;
       ++c_inhibit_evaluation_warnings;
+      ++cp_noexcept_operand;
       op1 = tsubst_copy_and_build (op1, args, complain, in_decl,
                                   /*function_p=*/false,
                                   /*integral_constant_expression_p=*/false);
       --cp_unevaluated_operand;
       --c_inhibit_evaluation_warnings;
+      --cp_noexcept_operand;
       RETURN (finish_noexcept_expr (op1, complain));
 
     case MODOP_EXPR:
index 760471c450d44aa3a17420bdd8f14ed2c34cb31f..d9aa1e5dd2116a667a4b57b636f33668a69b9cab 100644 (file)
@@ -1,3 +1,9 @@
+2014-10-02  Paolo Carlini  <paolo.carlini@oracle.com>
+
+       PR c++/53025
+       * g++.dg/cpp0x/noexcept23.C: New.
+       * g++.dg/cpp0x/noexcept24.C: Likewise.
+
 2014-10-02  Marek Polacek  <polacek@redhat.com>
 
        * gcc.dg/noncompile/20020130-1.c: Use -std=gnu89.
diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept23.C b/gcc/testsuite/g++.dg/cpp0x/noexcept23.C
new file mode 100644 (file)
index 0000000..5a01df4
--- /dev/null
@@ -0,0 +1,14 @@
+// PR c++/53025
+// { dg-do compile { target c++11 } }
+
+struct A {
+  A() noexcept {}
+  A(const A&) noexcept(false) {}
+};
+
+void a(A) noexcept {}
+
+void f()
+{
+  static_assert(!noexcept(a(A{})), "");
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept24.C b/gcc/testsuite/g++.dg/cpp0x/noexcept24.C
new file mode 100644 (file)
index 0000000..c17ddfa
--- /dev/null
@@ -0,0 +1,22 @@
+// PR c++/53025
+// { dg-do compile { target c++11 } }
+
+template<typename T>
+struct A {
+  A() noexcept {}
+  A(const A&) noexcept(false) {}
+};
+
+template<typename T>
+void a(A<T>) noexcept {}
+
+template<typename T>
+void f()
+{
+  static_assert(!noexcept(a(A<T>{})), "");
+}
+
+void g()
+{
+  f<int>();
+}