On Tue, Nov 21, 2023 at 04:44:01PM -0500, Jason Merrill wrote: > > Or do you want to just use > > error_at (location, "%<static_assert%> message must be a " > > "unevaluated string literal or object with " > > "%<size%> and %<data%> members"); > > wording (even when it is in C++26 term) regardless of the -std= level? > > No, I think "unevaluated string literal" will be confusing to users. I > guess it's fine as it is, let's just print the type (as commented inline > below).
Ok. > > + error_at (location, "%<static_assert%> message must be a string " > > + "literal or object with %<size%> and " > > + "%<data%> members"); > > Let's print the type of the message as well. so add " while it has type %qT", TREE_TYPE (message) or something else? > > + releasing_vec size_args, data_args; > > + message_sz = finish_call_expr (message_sz, &size_args, false, false, > > + tf_warning_or_error); > > + message_data = finish_call_expr (message_data, &data_args, false, > > false, > > + tf_warning_or_error); > > + if (message_sz == error_mark_node || message_data == error_mark_node) > > + return; > > + if (tree s > > + = cp_get_callee_fndecl_nofold (extract_call_expr (message_sz))) > > + if (!DECL_DECLARED_CONSTEXPR_P (s)) > > + warning_at (location, 0, "%qD used in %<static_assert%> message " > > + "is not %<constexpr%>", s); > > I don't think we need this check, it should be covered by the later > constant-expression checks. If the static_assert condition is true, we won't diagnose anything then. clang++ there incorrectly errors, but I thought a warning could be useful to users. Perhaps it could warn only if the condition is true? > > + error_at (location, "%<static_assert%> message %<size()%> " > > + "must be implicitly convertible to " > > + "%<std::size_t%>"); > > Let's also print the type of size(). " while it has type %qT" ? > > @@ -11485,9 +11544,96 @@ finish_static_assert (tree condition, tr > > if (processing_template_decl) > > goto defer; > > - int sz = TREE_INT_CST_LOW (TYPE_SIZE_UNIT > > - (TREE_TYPE (TREE_TYPE (message)))); > > - int len = TREE_STRING_LENGTH (message) / sz - 1; > > + int len; > > + const char *msg = NULL; > > + char *buf = NULL; > > + if (message_sz && message_data) > > + { > > + tree msz > > + = fold_non_dependent_expr (message_sz, complain, > > + /*manifestly_const_eval=*/true); > > We can call cxx_constant_value here instead of fold_non_dependent_expr, > since we don't get here in a template. Ok. > > + t = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (t)), t); > > + tree t2 > > + = fold_non_dependent_expr (t, complain, > > + /*manifestly_const_eval=*/ > > + true); > > This can also be cxx_constant_value. > > > + if (!tree_fits_shwi_p (t2)) > > + { > > + cxx_constant_value (t); But in that case I don't have to call it again, right? > Let's add a comment here about how you're using (data(), 0) to test > core-constant. Ok. Jakub