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. * 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
This commit is contained in:
parent
cc3bae3dc2
commit
c46f1a1791
|
@ -3,6 +3,12 @@
|
||||||
* except.c (build_noexcept_spec): Use build_converted_constant_bool_expr
|
* except.c (build_noexcept_spec): Use build_converted_constant_bool_expr
|
||||||
instead of perform_implicit_conversion_flags.
|
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>
|
2019-04-11 Jakub Jelinek <jakub@redhat.com>
|
||||||
|
|
||||||
PR translation/90035
|
PR translation/90035
|
||||||
|
|
|
@ -5423,27 +5423,6 @@ cxx_eval_outermost_constant_expr (tree t, bool allow_non_constant,
|
||||||
return r;
|
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.
|
/* If T represents a constant expression returns its reduced value.
|
||||||
Otherwise return error_mark_node. If T is dependent, then
|
Otherwise return error_mark_node. If T is dependent, then
|
||||||
return NULL. */
|
return NULL. */
|
||||||
|
|
|
@ -7720,7 +7720,6 @@ extern tree fold_non_dependent_init (tree,
|
||||||
tsubst_flags_t = tf_warning_or_error,
|
tsubst_flags_t = tf_warning_or_error,
|
||||||
bool = false);
|
bool = false);
|
||||||
extern tree fold_simple (tree);
|
extern tree fold_simple (tree);
|
||||||
extern bool is_sub_constant_expr (tree);
|
|
||||||
extern bool reduced_constant_expression_p (tree);
|
extern bool reduced_constant_expression_p (tree);
|
||||||
extern bool is_instantiation_of_constexpr (tree);
|
extern bool is_instantiation_of_constexpr (tree);
|
||||||
extern bool var_in_constexpr_fn (tree);
|
extern bool var_in_constexpr_fn (tree);
|
||||||
|
|
|
@ -1128,11 +1128,14 @@ check_noexcept_r (tree *tp, int * /*walk_subtrees*/, void * /*data*/)
|
||||||
&& (DECL_ARTIFICIAL (fn)
|
&& (DECL_ARTIFICIAL (fn)
|
||||||
|| nothrow_libfn_p (fn)))
|
|| nothrow_libfn_p (fn)))
|
||||||
return TREE_NOTHROW (fn) ? NULL_TREE : fn;
|
return TREE_NOTHROW (fn) ? NULL_TREE : fn;
|
||||||
/* A call to a constexpr function is noexcept if the call
|
/* We used to treat a call to a constexpr function as noexcept if
|
||||||
is a constant expression. */
|
the call was a constant expression (CWG 1129). This has changed
|
||||||
if (DECL_DECLARED_CONSTEXPR_P (fn)
|
in P0003 whereby noexcept has no special rule for constant
|
||||||
&& is_sub_constant_expr (t))
|
expressions anymore. Since the current behavior is important for
|
||||||
return NULL_TREE;
|
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))
|
if (!TYPE_NOTHROW_P (type))
|
||||||
return fn;
|
return fn;
|
||||||
|
|
|
@ -1,3 +1,13 @@
|
||||||
|
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>
|
2019-04-12 Marek Polacek <polacek@redhat.com>
|
||||||
|
|
||||||
* g++.dg/cpp0x/noexcept30.C: Tweak dg-error.
|
* g++.dg/cpp0x/noexcept30.C: Tweak dg-error.
|
||||||
|
|
|
@ -10,4 +10,7 @@ constexpr T value(T t) noexcept(is_funny<T>::value) { return t; } // Line 7
|
||||||
|
|
||||||
constexpr bool ok = noexcept(value(42));
|
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");
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
|
|
||||||
constexpr int f(int i) { return i; }
|
constexpr int f(int i) { return i; }
|
||||||
#define SA(X) static_assert (X, #X)
|
#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;
|
int j;
|
||||||
SA(!noexcept(f(j)));
|
SA(!noexcept(f(j)));
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
// { dg-do compile { target c++11 } }
|
// { dg-do compile { target c++11 } }
|
||||||
// A call is noexcept if it is a valid subexpression of a constant
|
// We used to treat a call to a constexpr function as noexcept if
|
||||||
// expression, even if it is not itself a constant expression.
|
// the call was a constant expression. We no longer do since
|
||||||
|
// c++/87603.
|
||||||
|
|
||||||
#define SA(X) static_assert(X,#X)
|
#define SA(X) static_assert(X,#X)
|
||||||
|
|
||||||
|
@ -9,6 +10,6 @@ constexpr const int* f(const int *p) { return p; }
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
constexpr int i = 42;
|
constexpr int i = 42;
|
||||||
SA(noexcept(*f(&i)));
|
SA(!noexcept(*f(&i)));
|
||||||
SA(noexcept(f(&i)));
|
SA(!noexcept(f(&i)));
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
// 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{}), "");
|
|
@ -168,7 +168,7 @@ namespace derived_ctor {
|
||||||
};
|
};
|
||||||
struct bar : boo {
|
struct bar : boo {
|
||||||
template <typename ...T>
|
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}));
|
void f() noexcept(noexcept(bar{0,1}));
|
||||||
}
|
}
|
||||||
|
@ -200,12 +200,12 @@ namespace derived_ctor {
|
||||||
};
|
};
|
||||||
struct bor : boo {
|
struct bor : boo {
|
||||||
template <typename ...T>
|
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 {
|
struct bar : bor {
|
||||||
using bor::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 {
|
namespace no_constexpr_noninherited_ctor {
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
// 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});
|
Loading…
Reference in New Issue