https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86524
--- Comment #5 from Jakub Jelinek <jakub at gcc dot gnu.org> --- Similarly, when changing: - static_assert (!foo (&x, &x)); + constexpr bool y = foo (&x, &x); + static_assert (!y); I think the problem is that finish_static_assert evaluates the condition using fold_non_dependent_expr -> maybe_constant_value and that results in ctx->quiet being true while evaluating the expression (it wants to diagnose non-constant expression only later). But we have also: /* Don't fold __builtin_constant_p within a constexpr function. */ bool bi_const_p = (DECL_FUNCTION_CODE (fun) == BUILT_IN_CONSTANT_P); /* If we aren't requiring a constant expression, defer __builtin_constant_p in a constexpr function until we have values for the parameters. */ if (bi_const_p && ctx->quiet && current_function_decl && DECL_DECLARED_CONSTEXPR_P (current_function_decl)) { *non_constant_p = true; return t; } which means if ctx->quiet is true, we don't try at all to evaluate the builtin. That is reasonable while parsing the constexpr functions of cp_folding it, but we don't have a way right now to differentiate between that and the finish_static_assert which is try as hard as possible to evaluate it to a constant, just don't complain if that fails. So, do we need another constexpr context flag for this, or should we e.g. try to fold the __builtin_constant_p in any case and only set *non_constant_p if it evaluates to false, or something similar?