Hi,

On 10/02/2014 07:37 PM, Jason Merrill wrote:
On 10/02/2014 12:44 PM, Paolo Carlini wrote:
+  s->noexcept_operand = scope_chain ? cp_noexcept_operand : 0;
    s->x_stmt_tree.stmts_are_full_exprs_p = true;

    scope_chain = s;
@@ -6182,6 +6183,7 @@ pop_from_top_level_1 (void)
    current_function_decl = s->function_decl;
    cp_unevaluated_operand = s->unevaluated_operand;
    c_inhibit_evaluation_warnings = s->inhibit_evaluation_warnings;
+  cp_noexcept_operand = s->noexcept_operand;

The benefit of putting it in scope_chain directly is that you don't need to change anything here. OK without these changes.
Oh, nice. Then I'm going to apply the below and resolve the bug.

Thanks,
Paolo.

///////////////////
/cp
2014-10-02  Paolo Carlini  <paolo.carl...@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.carl...@oracle.com>

        PR c++/53025
        * g++.dg/cpp0x/noexcept23.C: New.
        * g++.dg/cpp0x/noexcept24.C: Likewise.
Index: cp/call.c
===================================================================
--- cp/call.c   (revision 215801)
+++ cp/call.c   (working copy)
@@ -7251,7 +7251,11 @@ build_over_call (struct z_candidate *cand, int fla
     /* 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: cp/cp-tree.h
===================================================================
--- cp/cp-tree.h        (revision 215801)
+++ cp/cp-tree.h        (working copy)
@@ -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: cp/parser.c
===================================================================
--- cp/parser.c (revision 215801)
+++ cp/parser.c (working copy)
@@ -7156,7 +7156,9 @@ cp_parser_unary_expression (cp_parser *parser, boo
 
            ++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: cp/pt.c
===================================================================
--- cp/pt.c     (revision 215801)
+++ cp/pt.c     (working copy)
@@ -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: testsuite/g++.dg/cpp0x/noexcept23.C
===================================================================
--- testsuite/g++.dg/cpp0x/noexcept23.C (revision 0)
+++ testsuite/g++.dg/cpp0x/noexcept23.C (working copy)
@@ -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{})), "");
+}
Index: testsuite/g++.dg/cpp0x/noexcept24.C
===================================================================
--- testsuite/g++.dg/cpp0x/noexcept24.C (revision 0)
+++ testsuite/g++.dg/cpp0x/noexcept24.C (working copy)
@@ -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>();
+}

Reply via email to