Hi,

in this issue Daniel argued that the value of a noexcept expression should not depend on constructor elision. Then, in the audit trail Marc tentatively suggested something like the parser.c hunk below, which just disables our -felide-constructors optimization when parsing the noexcept expression. Over the last couple of days, I had a look, noticed that in any case we still have to handle templates, thus the pt.c hunk, and also that maybe we can avoid completely disabling -felide-constructors in noexcept expressions when we know for sure that the constructor at issue doen't throw: for that in call.s I'm further abusing the flag_elide_constructors global, in terms of using a special value of 2 when flag_elide_constructor is found == 1 when handling the expression. The below passes testing, anyway.

Thanks!
Paolo.

///////////////////////
Index: cp/call.c
===================================================================
--- cp/call.c   (revision 215750)
+++ cp/call.c   (working copy)
@@ -7249,9 +7249,14 @@ build_over_call (struct z_candidate *cand, int fla
 
   if (! flag_elide_constructors)
     /* Do things the hard way.  */;
-  else if (cand->num_convs == 1 
-           && (DECL_COPY_CONSTRUCTOR_P (fn) 
-               || DECL_MOVE_CONSTRUCTOR_P (fn)))
+  else if ((cand->num_convs == 1 
+           && (DECL_COPY_CONSTRUCTOR_P (fn) 
+               || DECL_MOVE_CONSTRUCTOR_P (fn)))
+          && (flag_elide_constructors == 1
+              || (flag_elide_constructors == 2
+                  && (!DEFERRED_NOEXCEPT_SPEC_P
+                      (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (fn)))
+                      && type_noexcept_p (TREE_TYPE (fn))))))
     {
       tree targ;
       tree arg = argarray[num_artificial_parms_for (fn)];
Index: cp/parser.c
===================================================================
--- cp/parser.c (revision 215750)
+++ cp/parser.c (working copy)
@@ -7136,10 +7136,15 @@ cp_parser_unary_expression (cp_parser *parser, boo
            bool saved_integral_constant_expression_p;
            bool saved_non_integral_constant_expression_p;
            bool saved_greater_than_is_operator_p;
+           int  saved_flag_elide_constructors;
 
            cp_lexer_consume_token (parser->lexer);
            cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN);
 
+           saved_flag_elide_constructors = flag_elide_constructors;
+           if (flag_elide_constructors == 1)
+             flag_elide_constructors = 2;
+
            saved_message = parser->type_definition_forbidden_message;
            parser->type_definition_forbidden_message
              = G_("types may not be defined in %<noexcept%> expressions");
@@ -7170,6 +7175,8 @@ cp_parser_unary_expression (cp_parser *parser, boo
 
            parser->type_definition_forbidden_message = saved_message;
 
+           flag_elide_constructors = saved_flag_elide_constructors;
+
            cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
            return finish_noexcept_expr (expr, tf_warning_or_error);
          }
Index: cp/pt.c
===================================================================
--- cp/pt.c     (revision 215750)
+++ cp/pt.c     (working copy)
@@ -14766,15 +14766,22 @@ tsubst_copy_and_build (tree t,
       }
 
     case NOEXCEPT_EXPR:
-      op1 = TREE_OPERAND (t, 0);
-      ++cp_unevaluated_operand;
-      ++c_inhibit_evaluation_warnings;
-      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;
-      RETURN (finish_noexcept_expr (op1, complain));
+      {
+       int saved_flag_elide_constructors;
+       op1 = TREE_OPERAND (t, 0);
+       ++cp_unevaluated_operand;
+       ++c_inhibit_evaluation_warnings;
+       saved_flag_elide_constructors = flag_elide_constructors;
+       if (flag_elide_constructors == 1)
+         flag_elide_constructors = 2;
+       op1 = tsubst_copy_and_build (op1, args, complain, in_decl,
+                                    /*function_p=*/false,
+                                    /*integral_constant_expression_p=*/false);
+       flag_elide_constructors = saved_flag_elide_constructors;
+       --cp_unevaluated_operand;
+       --c_inhibit_evaluation_warnings;
+       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