c++: Fix noexcept with unevaluated operand [PR101087]

It sounds plausible that this assert

  int f();
  static_assert(noexcept(sizeof(f())));

should pass: sizeof produces a std::size_t and its operand is not
evaluated, so it can't throw.  noexcept should only evaluate to
false for potentially evaluated operands.  Therefore I think that
check_noexcept_r shouldn't walk into operands of sizeof/decltype/
alignof/typeof.

	PR c++/101087

gcc/cp/ChangeLog:

	* cp-tree.h (unevaluated_p): New.
	* except.c (check_noexcept_r): Use it.  Don't walk into
	unevaluated operands.

gcc/testsuite/ChangeLog:

	* g++.dg/cpp0x/noexcept70.C: New test.
This commit is contained in:
Marek Polacek 2021-07-07 20:02:18 -04:00
parent b14ac7b29c
commit dee00bf689
3 changed files with 24 additions and 3 deletions

View File

@ -8465,6 +8465,19 @@ is_constrained_auto (const_tree t)
return is_auto (t) && PLACEHOLDER_TYPE_CONSTRAINTS_INFO (t);
}
/* True if CODE, a tree code, denotes a tree whose operand is not evaluated
as per [expr.context], i.e., an operand to sizeof, typeof, decltype, or
alignof. */
inline bool
unevaluated_p (tree_code code)
{
return (code == DECLTYPE_TYPE
|| code == ALIGNOF_EXPR
|| code == SIZEOF_EXPR
|| code == NOEXCEPT_EXPR);
}
/* RAII class to push/pop the access scope for T. */
struct push_access_scope_guard

View File

@ -1033,12 +1033,15 @@ check_handlers (tree handlers)
expression whose type is a polymorphic class type (10.3). */
static tree
check_noexcept_r (tree *tp, int * /*walk_subtrees*/, void * /*data*/)
check_noexcept_r (tree *tp, int *walk_subtrees, void *)
{
tree t = *tp;
enum tree_code code = TREE_CODE (t);
if ((code == CALL_EXPR && CALL_EXPR_FN (t))
|| code == AGGR_INIT_EXPR)
if (unevaluated_p (code))
*walk_subtrees = false;
else if ((code == CALL_EXPR && CALL_EXPR_FN (t))
|| code == AGGR_INIT_EXPR)
{
/* We can only use the exception specification of the called function
for determining the value of a noexcept expression; we can't use

View File

@ -0,0 +1,5 @@
// PR c++/101087
// { dg-do compile { target c++11 } }
int f();
static_assert(noexcept(sizeof(f())), "");