* constexpr.c (is_sub_constant_expr): Remove unused function.
* cp-tree.h (is_sub_constant_expr): Remove declaration.
* except.c (check_noexcept_r): Don't consider a call to a constexpr
function noexcept.
* g++.dg/cpp0x/constexpr-noexcept.C: Adjust the expected result.
* g++.dg/cpp0x/constexpr-noexcept3.C: Likewise.
* g++.dg/cpp0x/constexpr-noexcept4.C: Likewise.
* g++.dg/cpp0x/constexpr-noexcept8.C: New test.
* g++.dg/cpp0x/inh-ctor32.C: Remove dg-message.
* g++.dg/cpp1y/constexpr-noexcept1.C: New test.
From-SVN: r270320
* except.c (build_noexcept_spec): Use build_converted_constant_bool_expr
instead of perform_implicit_conversion_flags.
+ PR c++/87603 - constexpr functions are no longer noexcept.
+ * constexpr.c (is_sub_constant_expr): Remove unused function.
+ * cp-tree.h (is_sub_constant_expr): Remove declaration.
+ * except.c (check_noexcept_r): Don't consider a call to a constexpr
+ function noexcept.
+
2019-04-11 Jakub Jelinek <jakub@redhat.com>
PR translation/90035
return r;
}
-/* Returns true if T is a valid subexpression of a constant expression,
- even if it isn't itself a constant expression. */
-
-bool
-is_sub_constant_expr (tree t)
-{
- bool non_constant_p = false;
- bool overflow_p = false;
- hash_map <tree, tree> map;
- HOST_WIDE_INT constexpr_ops_count = 0;
-
- constexpr_ctx ctx
- = { NULL, &map, NULL, NULL, NULL, NULL, &constexpr_ops_count,
- true, true, false };
-
- instantiate_constexpr_fns (t);
- cxx_eval_constant_expression (&ctx, t, false, &non_constant_p,
- &overflow_p);
- return !non_constant_p && !overflow_p;
-}
-
/* If T represents a constant expression returns its reduced value.
Otherwise return error_mark_node. If T is dependent, then
return NULL. */
tsubst_flags_t = tf_warning_or_error,
bool = false);
extern tree fold_simple (tree);
-extern bool is_sub_constant_expr (tree);
extern bool reduced_constant_expression_p (tree);
extern bool is_instantiation_of_constexpr (tree);
extern bool var_in_constexpr_fn (tree);
&& (DECL_ARTIFICIAL (fn)
|| nothrow_libfn_p (fn)))
return TREE_NOTHROW (fn) ? NULL_TREE : fn;
- /* A call to a constexpr function is noexcept if the call
- is a constant expression. */
- if (DECL_DECLARED_CONSTEXPR_P (fn)
- && is_sub_constant_expr (t))
- return NULL_TREE;
+ /* We used to treat a call to a constexpr function as noexcept if
+ the call was a constant expression (CWG 1129). This has changed
+ in P0003 whereby noexcept has no special rule for constant
+ expressions anymore. Since the current behavior is important for
+ certain library functionality, we treat this as a DR, therefore
+ adjusting the behavior for C++11 and C++14. Previously, we had
+ to evaluate the noexcept-specifier's operand here, but that could
+ cause instantiations that would fail. */
}
if (!TYPE_NOTHROW_P (type))
return fn;
+2019-04-12 Marek Polacek <polacek@redhat.com>
+
+ PR c++/87603 - constexpr functions are no longer noexcept.
+ * g++.dg/cpp0x/constexpr-noexcept.C: Adjust the expected result.
+ * g++.dg/cpp0x/constexpr-noexcept3.C: Likewise.
+ * g++.dg/cpp0x/constexpr-noexcept4.C: Likewise.
+ * g++.dg/cpp0x/constexpr-noexcept8.C: New test.
+ * g++.dg/cpp0x/inh-ctor32.C: Remove dg-message.
+ * g++.dg/cpp1y/constexpr-noexcept1.C: New test.
+
2019-04-12 Marek Polacek <polacek@redhat.com>
* g++.dg/cpp0x/noexcept30.C: Tweak dg-error.
constexpr bool ok = noexcept(value(42));
-static_assert(ok, "Assertion failure");
+// We used to treat a call to a constexpr function as noexcept if
+// the call was a constant expression. We no longer do since
+// c++/87603.
+static_assert(!ok, "Assertion failure");
constexpr int f(int i) { return i; }
#define SA(X) static_assert (X, #X)
-SA(noexcept(f(42)));
+/* We used to assert that the following *is* noexcept, but this has changed
+ in c++/87603. */
+SA(!noexcept(f(42)));
int j;
SA(!noexcept(f(j)));
// { dg-do compile { target c++11 } }
-// A call is noexcept if it is a valid subexpression of a constant
-// expression, even if it is not itself a constant expression.
+// We used to treat a call to a constexpr function as noexcept if
+// the call was a constant expression. We no longer do since
+// c++/87603.
#define SA(X) static_assert(X,#X)
int main()
{
constexpr int i = 42;
- SA(noexcept(*f(&i)));
- SA(noexcept(f(&i)));
+ SA(!noexcept(*f(&i)));
+ SA(!noexcept(f(&i)));
}
--- /dev/null
+// PR c++/87603
+// { dg-do compile { target c++11 } }
+
+struct Y { };
+
+ bool operator<(Y a, Y b) { return false; }
+constexpr bool operator>(Y a, Y b) { return false; }
+
+static_assert(!noexcept(Y{} > Y{}), "");
+static_assert(!noexcept(Y{} < Y{}), "");
};
struct bar : boo {
template <typename ...T>
- constexpr bar(T ... args) : boo(args...) {} // { dg-message "sorry, unimplemented: passing arguments to ellipsis" }
+ constexpr bar(T ... args) : boo(args...) {}
};
void f() noexcept(noexcept(bar{0,1}));
}
};
struct bor : boo {
template <typename ...T>
- constexpr bor(T ... args) : boo(args...) {} // { dg-message "sorry, unimplemented: passing arguments to ellipsis" }
+ constexpr bor(T ... args) : boo(args...) {}
};
struct bar : bor {
using bor::bor;
};
- void f() noexcept(noexcept(bar{0,1})); // { dg-message "'constexpr' expansion" }
+ void f() noexcept(noexcept(bar{0,1}));
}
namespace no_constexpr_noninherited_ctor {
--- /dev/null
+// PR c++/87603
+// { dg-do compile { target c++14 } }
+
+template<typename T>
+struct basic_string_view
+{
+ constexpr basic_string_view(T p) noexcept { (void) p.i; }
+};
+
+struct X { } x;
+
+bool b = noexcept(basic_string_view<X>{x});