aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/constexpr.cc
AgeCommit message (Collapse)AuthorFilesLines
2023-06-12c++: build initializer_list<string> in a loop [PR105838]Jason Merrill1-3/+3
I previously applied this change in r13-4565 but reverted it due to PR108071. That PR was then fixed by r13-4712, but I didn't re-apply this change then because we weren't making the array static; since r14-1500 for PR110070 we now make the initializer array static, so let's bring this back. In situations where the maybe_init_list_as_range optimization isn't viable, we can build an initializer_list<string> with a loop over a constant array of string literals. This is represented using a VEC_INIT_EXPR, which required adjusting a couple of places that expected the initializer array to have the same type as the target array and fixing build_vec_init not to undo our efforts. PR c++/105838 gcc/cp/ChangeLog: * call.cc (convert_like_internal) [ck_list]: Use maybe_init_list_as_array. * constexpr.cc (cxx_eval_vec_init_1): Init might have a different type. * tree.cc (build_vec_init_elt): Likewise. * init.cc (build_vec_init): Handle from_array from a TARGET_EXPR. Retain TARGET_EXPR of a different type. gcc/testsuite/ChangeLog: * g++.dg/tree-ssa/initlist-opt5.C: New test.
2023-06-11c++: unsynthesized defaulted constexpr fn [PR110122]Patrick Palka1-4/+10
In this other testcase from PR110122, during regeneration of the generic lambda with V=Bar{}, substitution followed by coerce_template_parms for A<V>'s template argument naturally yields a copy of V in terms of Bar's (implicitly) defaulted copy constructor. This however happens inside a template context so although we introduced a use of the copy constructor, mark_used didn't actually synthesize it, which causes subsequent constant evaluation of the template argument to fail with: nontype-class59.C: In instantiation of ‘void f() [with Bar V = Bar{Foo()}]’: nontype-class59.C:22:11: required from here nontype-class59.C:18:18: error: ‘constexpr Bar::Bar(const Bar&)’ used before its definition We already make sure to instantiate templated constexpr functions needed for constant evaluation (as per P0859R0). So this patch fixes this by making us synthesize defaulted constexpr functions needed for constant evaluation as well. PR c++/110122 gcc/cp/ChangeLog: * constexpr.cc (cxx_eval_call_expression): Synthesize defaulted functions needed for constant evaluation. (instantiate_cx_fn_r): Likewise. gcc/testsuite/ChangeLog: * g++.dg/cpp2a/nontype-class59.C: New test.
2023-05-10c++: be stricter about constinit [CWG2543]Jason Merrill1-0/+12
DR 2543 clarifies that constinit variables should follow the language, and diagnose non-constant initializers (according to [expr.const]) even if they can actually initialize the variables statically. DR 2543 gcc/cp/ChangeLog: * constexpr.cc (cxx_eval_outermost_constant_expr): Preserve TARGET_EXPR flags. (potential_constant_expression_1): Check TARGET_EXPR_ELIDING_P. * typeck2.cc (store_init_value): Diagnose constinit sooner. gcc/testsuite/ChangeLog: * g++.dg/DRs/dr2543.C: New test.
2023-05-10c++: always check consteval addressJason Merrill1-7/+15
The restriction on the "permitted result of a constant expression" to not refer to an immediate function applies regardless of context. The previous code tried to only check in cases where we wouldn't get the check in cp_fold_r, but with the next patch I would need to add another case and it shouldn't be a problem to always check. We also shouldn't talk about immediate evaluation when we aren't dealing with one. gcc/cp/ChangeLog: * constexpr.cc (cxx_eval_outermost_constant_expr): Always check for address of immediate fn. (maybe_constant_init_1): Evaluate PTRMEM_CST. gcc/testsuite/ChangeLog: * g++.dg/DRs/dr2478.C: Handle -fimplicit-constexpr. * g++.dg/cpp23/consteval-if12.C: Adjust diagnostics. * g++.dg/cpp2a/consteval20.C: Likewise. * g++.dg/cpp2a/consteval24.C: Likewise. * g++.dg/cpp2a/srcloc20.C: Likewise.
2023-05-07c++: potentiality of templated memfn call [PR109480]Patrick Palka1-26/+6
Here we're incorrectly deeming the templated call a.g() inside b's initializer as potentially constant, despite g being non-constexpr, which leads to us needlessly instantiating the initializer ahead of time and which subsequently triggers a bug in access checking deferral (to be fixed by the follow-up patch). This patch fixes this by calling get_fns earlier during CALL_EXPR potentiality checking so that when we extract a FUNCTION_DECL out of a templated member function call (whose overall callee is typically a COMPONENT_REF) we do the usual constexpr-eligibility checking for it. In passing, I noticed the nearby special handling of the object argument of a non-static member function call is effectively the same as the generic argument handling a few lines below. So this patch just gets rid of this special handling; otherwise we'd have to adapt it to handle templated versions of such calls. PR c++/109480 gcc/cp/ChangeLog: * constexpr.cc (potential_constant_expression_1) <case CALL_EXPR>: Reorganize to call get_fns sooner. Remove special handling of the object argument of a non-static member function call. Remove dead store to 'fun'. gcc/testsuite/ChangeLog: * g++.dg/cpp0x/noexcept59.C: Make e() constexpr so that the expected "without object" diagnostic isn't replaced by a "call to non-constexpr function" diagnostic. * g++.dg/template/non-dependent25.C: New test.
2023-05-02c++: look for empty base at specific offset [PR109678]Jason Merrill1-1/+1
While looking at the empty base handling for 109678, it occurred to me that we ought to be able to look for an empty base at a specific offset, not just in general. PR c++/109678 gcc/cp/ChangeLog: * cp-tree.h (lookup_base): Add offset parm. * constexpr.cc (cxx_fold_indirect_ref_1): Pass it. * search.cc (struct lookup_base_data_s): Add offset. (dfs_lookup_base): Handle it. (lookup_base): Pass it.
2023-05-02c++: std::variant slow to compile [PR109678]Jason Merrill1-10/+13
Here, when dealing with a class with a complex subobject structure, we would try and fail to find the relevant FIELD_DECL for an empty base before giving up. And we would do this at each level, in a combinatorially problematic way. Instead, we should check for an empty base first. PR c++/109678 gcc/cp/ChangeLog: * constexpr.cc (cxx_fold_indirect_ref_1): Handle empty base first. gcc/testsuite/ChangeLog: * g++.dg/cpp1z/variant1.C: New test.
2023-04-15c++: constexpr aggregate destruction [PR109357]Jason Merrill1-4/+11
We were assuming that the result of evaluation of TARGET_EXPR_INITIAL would always be the new value of the temporary, but that's not necessarily true when the initializer is complex (i.e. target_expr_needs_replace). In that case evaluating the initializer initializes the temporary as a side-effect. PR c++/109357 gcc/cp/ChangeLog: * constexpr.cc (cxx_eval_constant_expression) [TARGET_EXPR]: Check for complex initializer. gcc/testsuite/ChangeLog: * g++.dg/cpp2a/constexpr-dtor15.C: New test.
2023-03-16c++: maybe_constant_init and unevaluated operands [PR109030]Patrick Palka1-0/+4
This testcase in this PR (already fixed by r13-6526-ge4692319fd5fc7) demonstrates that maybe_constant_init can be called on an unevaluated operand (e.g. from massage_init_elt) so this entry point should also limit constant evaluation in that case, like maybe_constant_value does. PR c++/109030 gcc/cp/ChangeLog: * constexpr.cc (maybe_constant_init_1): For an unevaluated non-manifestly-constant operand, don't constant evaluate and instead call fold_to_constant as in maybe_constant_value. gcc/testsuite/ChangeLog: * g++.dg/cpp2a/constexpr-inst2.C: New test.
2023-03-15c++: ICE with constexpr lambda [PR107280]Marek Polacek1-1/+2
We crash here since r10-3661, the store_init_value hunk in particular. Before, we called cp_fully_fold_init, so e.g. {.str=VIEW_CONVERT_EXPR<char[8]>("")} was folded into {.str=""} but now we don't fold and keep the VCE around, and it causes trouble in cxx_eval_store_expression: in the !refs->is_empty () loop we descend on .str's initializer but since it's wrapped in a VCE, we skip the STRING_CST check and then crash on the CONSTRUCTOR_NO_CLEARING. PR c++/107280 gcc/cp/ChangeLog: * constexpr.cc (cxx_eval_store_expression): Strip location wrappers. gcc/testsuite/ChangeLog: * g++.dg/cpp1z/constexpr-lambda28.C: New test.
2023-03-07c++: noexcept and copy elision [PR109030]Marek Polacek1-1/+5
When processing a noexcept, constructors aren't elided: build_over_call has /* It's unsafe to elide the constructor when handling a noexcept-expression, it may evaluate to the wrong value (c++/53025). */ && (force_elide || cp_noexcept_operand == 0)) so the assert I added recently needs to be relaxed a little bit. PR c++/109030 gcc/cp/ChangeLog: * constexpr.cc (cxx_eval_call_expression): Relax assert. gcc/testsuite/ChangeLog: * g++.dg/cpp0x/noexcept77.C: New test.
2023-03-07c++: error with constexpr operator() [PR107939]Marek Polacek1-2/+6
Similarly to PR107938, this also started with r11-557, whereby cp_finish_decl can call check_initializer even in a template for a constexpr initializer. Here we are rejecting extern const Q q; template<int> constexpr auto p = q(0); even though q has a constexpr operator(). It's deemed non-const by decl_maybe_constant_var_p because even though 'q' is const it is not of integral/enum type. If fun is not a function pointer, we don't know if we're using it as an lvalue or rvalue, so with this patch we pass 'any' for want_rval. With that, p_c_e/VAR_DECL doesn't flat out reject the underlying VAR_DECL. PR c++/107939 gcc/cp/ChangeLog: * constexpr.cc (potential_constant_expression_1) <case CALL_EXPR>: Pass 'any' when recursing on a VAR_DECL and not a pointer to function. gcc/testsuite/ChangeLog: * g++.dg/cpp1y/var-templ74.C: Remove dg-error. * g++.dg/cpp1y/var-templ77.C: New test.
2023-03-04c++: Don't defer local statics initialized with constant expressions [PR108702]Jakub Jelinek1-0/+19
The stmtexpr19.C testcase used to be rejected as it has a static variable in statement expression in constexpr context, but as that static variable is initialized by constant expression, when P2647R1 was implemented we agreed to make it valid. Now, as reported, the testcase compiles fine, but doesn't actually link because the static variable isn't defined anywhere, and with -flto ICEs because of this problem. This is because we never varpool_node::finalize_decl those vars, the constant expression in which the DECL_EXPR is present for the static VAR_DECL is folded (constant evaluated) into just the address of the VAR_DECL. Now, similar testcase included below (do we want to include it in the testsuite too?) works fine, because in cp_finish_decl -> make_rtl_for_nonlocal_decl we have since PR70353 fix: /* We defer emission of local statics until the corresponding DECL_EXPR is expanded. But with constexpr its function might never be expanded, so go ahead and tell cgraph about the variable now. */ defer_p = ((DECL_FUNCTION_SCOPE_P (decl) && !var_in_maybe_constexpr_fn (decl)) || DECL_VIRTUAL_P (decl)); and so don't defer them in constexpr/consteval functions. The following patch calls rest_of_decl_compilation which make_rtl_for_nonlocal_decl didn't call when encountering DECL_EXPRs of such vars during constant evaluation if they weren't finalized yet. 2023-03-04 Jakub Jelinek <jakub@redhat.com> PR c++/108702 * constexpr.cc: Include toplev.h. (cxx_eval_constant_expression) <case DECL_EXPR>: When seeing a local static initialized by constant expression outside of a constexpr function which has been deferred by make_rtl_for_nonlocal_decl, call rest_of_decl_compilation on it. * g++.dg/ext/stmtexpr19.C: Use dg-do link rather than dg-do compile.
2023-03-02c++: constant non-copy-init is manifestly constant [PR108243]Patrick Palka1-0/+2
According to [basic.start.static]/2 and [expr.const]/2, a variable with static storage duration initialized with a constant initializer has constant initialization, and such an initializer is manifestly constant-evaluated. For copy initialization, we're already getting this right because in that case check_initializer would consistently call store_init_value, which for TREE_STATIC variables calls fold_non_dependent_init with m_c_e=true. But for direct (or default) initialization, check_initializer doesn't always call store_init_value. We instead however always call maybe_constant_init from expand_default_init[1], albeit with m_c_e=false which means we don't get the "manifestly constant-evaluated" part right for non-copy-init. This patch fixes this by setting m_c_e=true in maybe_constant_init for static storage duration variables, mainly for benefit of the call to maybe_constant_init from expand_default_init. [1]: this maybe_constant_init call isn't reached in the copy-init case because there init is a CONSTRUCTOR rather than a TREE_LIST, and so we exit early from expand_default_init, returning an INIT_EXPR. This INIT_EXPR is ultimately what causes us to consistently hit the store_init_value code path from check_initializer in the copy-init case. PR c++/108243 gcc/cp/ChangeLog: * constexpr.cc (maybe_constant_init_1): Override manifestly_const_eval to true if is_static. gcc/testsuite/ChangeLog: * g++.dg/cpp2a/is-constant-evaluated14.C: New test.
2023-03-01c++: can't eval PTRMEM_CST in incomplete class [PR107574]Marek Polacek1-1/+12
Here we're attempting to evaluate a PTRMEM_CST in a class that hasn't been completed yet, but that doesn't work: /* We can't lower this until the class is complete. */ if (!COMPLETE_TYPE_P (DECL_CONTEXT (member))) return cst; and then this unlowered PTRMEM_CST is used as EXPR in tree op1 = build_nop (ptrdiff_type_node, expr); and we crash in a subsequent cp_fold_convert which gets type=ptrdiff_type_node, expr=PTRMEM_CST and does else if (TREE_CODE (expr) == PTRMEM_CST && same_type_p (TYPE_PTRMEM_CLASS_TYPE (type), PTRMEM_CST_CLASS (expr))) where TYPE_PTRMEM_CLASS_TYPE (type) is going to crash since the type is ptrdiff_type_node. We could just add a TYPE_PTRMEM_P check before accessing TYPE_PTRMEM_CLASS_TYPE but I think it's nicer to explain why we couldn't evaluate the expression. PR c++/107574 gcc/cp/ChangeLog: * constexpr.cc (cxx_eval_constant_expression): Emit an error when a PTRMEM_CST cannot be evaluated. gcc/testsuite/ChangeLog: * g++.dg/cpp0x/ptrmem-cst1.C: New test.
2023-03-01c++: unevaluated array new-expr size constantness [PR108219]Patrick Palka1-5/+24
Here we're mishandling the unevaluated array new-expressions due to a supposed non-constant array size ever since r12-5253-g4df7f8c79835d569 made us no longer perform constant evaluation of non-manifestly-constant expressions within unevaluated contexts. This shouldn't make a difference here since the array sizes are constant literals, except they're expressed as NON_LVALUE_EXPR location wrappers around INTEGER_CST, wrappers which used to get stripped as part of constant evaluation and now no longer do. Moreover it means build_vec_init can't constant fold the MINUS_EXPR 'maxindex' passed from build_new_1 when in an unevaluated context (since it tries reducing it via maybe_constant_value called with mce_unknown). This patch fixes these issues by making maybe_constant_value (and fold_non_dependent_expr) try folding an unevaluated non-manifestly-constant operand via fold(), as long as it simplifies to a simple constant, rather than doing no simplification at all. This covers e.g. simple arithmetic and casts including stripping of location wrappers around INTEGER_CST. In passing, this patch also fixes maybe_constant_value to avoid constant evaluating an unevaluated operand when called with mce_false, by adjusting the early exit test appropriately. Co-authored-by: Jason Merrill <jason@redhat.com> PR c++/108219 PR c++/108218 gcc/cp/ChangeLog: * constexpr.cc (fold_to_constant): Define. (maybe_constant_value): Move up early exit test for unevaluated operands. Try reducing an unevaluated operand to a constant via fold_to_constant. (fold_non_dependent_expr_template): Add early exit test for CONSTANT_CLASS_P nodes. Try reducing an unevaluated operand to a constant via fold_to_constant. * cp-tree.h (fold_to_constant): Declare. gcc/testsuite/ChangeLog: * g++.dg/cpp0x/new6.C: New test. * g++.dg/cpp2a/concepts-new1.C: New test.
2023-03-01c++: Don't recurse on DECL_INITIAL for DECL_EXPR on non-VAR_DECLs [PR108606]Jakub Jelinek1-1/+3
The r13-2965-g73d9b0e5947e16 change changed the line touched in this patch from return RECUR (tmp, want_rval); to return RECUR (DECL_INITIAL (tmp), want_rval); This is on DECL_EXPR handling code, where tmp can be lots of different trees and DECL_INITIAL unfortunately also means different things on different trees. It is the initializer on VAR_DECL, DECL_ARG_TYPE on PARM_DECLs (though those are unlikely to have DECL_EXPRs), for FUNCTION_DECLs the body, ..., USING_DECL_DECLS on USING_DECLs and DECL_FRIENDLIST on TYPE_DECLs. The testcase below ICEs because we have a DECL_EXPR for TYPE_DECL which has non-NULL DECL_FRIENDLIST and we certainly can't recurse on the friend list. The following patch will RECUR on DECL_INITIAL only for VAR_DECLs and for anything else just return true. 2023-03-01 Jakub Jelinek <jakub@redhat.com> PR c++/108606 * constexpr.cc (potential_constant_expression_1) <case DECL_EXPR>: Only recurse on DECL_INITIAL (tmp) if tmp is a VAR_DECL, otherwise just return true. * g++.dg/cpp1y/pr108606.C: New test.
2023-02-20c++: ICE with -fno-elide-constructors and trivial fn [PR101073]Marek Polacek1-22/+3
In constexpr-nsdmi3.C, with -fno-elide-constructors, we don't elide the Y::Y(const Y&) call used to initialize o.c. So store_init_value -> cxx_constant_init must constexpr-evaluate the call to Y::Y(const Y&) in cxx_eval_call_expression. It's a trivial function, so we do the "Shortcut trivial constructor/op=" code and rather than evaluating the function, we just create an assignment o.c = *(const struct Y &) (const struct Y *) &(&<PLACEHOLDER_EXPR struct X>)->b which is a MODIFY_EXPR, so the preeval code in cxx_eval_store_expression clears .ctor and .object, therefore we can't replace the PLACEHOLDER_EXPR whereupon we crash at /* A placeholder without a referent. We can get here when checking whether NSDMIs are noexcept, or in massage_init_elt; just say it's non-constant for now. */ gcc_assert (ctx->quiet); The PLACEHOLDER_EXPR can also be on the LHS as in constexpr-nsdmi10.C. I don't think we can do much here, but I noticed that the whole trivial_fn_p (fun) block is only entered when -fno-elide-constructors. This is true since GCC 9; it wasn't easy to bisect what changes made it so, but r240845 is probably one of them. -fno-elide-constructors is an option for experiments only so it's not clear to me why we'd still want to shortcut trivial constructor/op=. I propose to remove the code and add a checking assert to make sure we're not getting a trivial_fn_p unless -fno-elide-constructors. PR c++/101073 gcc/cp/ChangeLog: * constexpr.cc (cxx_eval_call_expression): Replace shortcutting trivial constructor/op= with a checking assert. gcc/testsuite/ChangeLog: * g++.dg/cpp0x/constexpr-nsdmi3.C: New test. * g++.dg/cpp1y/constexpr-nsdmi10.C: New test.
2023-02-17c++: make manifestly_const_eval tri-statePatrick Palka1-27/+32
This patch converts the constexpr machinery's manifestly_const_eval flag into a tri-state enum to allow us to express wanting to fold __builtin_is_constant_evaluated to false via speculative constexpr evaluation. For now, only the maybe_constant_value entry point is changed to take this enum; the others continue to take bool. The subsequent patch will teach cp_fold (which uses maybe_constant_value) to fold the builtin to false when called from cp_fold_function and cp_fully_fold_init. gcc/cp/ChangeLog: * constexpr.cc (constexpr_call::manifestly_const_eval): Give it type int instead of bool. (constexpr_ctx::manifestly_const_eval): Give it type mce_value instead of bool. (cxx_eval_builtin_function_call): Adjust after making manifestly_const_eval tri-state. (cxx_eval_call_expression): Likewise. (cxx_eval_binary_expression): Likewise. (cxx_eval_conditional_expression): Likewise. (cxx_eval_constant_expression): Likewise. (cxx_eval_outermost_constant_expr): Likewise. (cxx_constant_value): Likewise. (cxx_constant_dtor): Likewise. (maybe_constant_value): Give manifestly_const_eval parameter type mce_value instead of bool and adjust accordingly. (fold_non_dependent_expr_template): Adjust call to cxx_eval_outermost_constant_expr. (fold_non_dependent_expr): Likewise. (maybe_constant_init_1): Likewise. * constraint.cc (satisfy_atom): Adjust call to maybe_constant_value. * cp-tree.h (enum class mce_value): Define. (maybe_constant_value): Adjust manifestly_const_eval parameter type and default argument. * decl.cc (compute_array_index_type_loc): Adjust call to maybe_constant_value. * pt.cc (convert_nontype_argument): Likewise.
2023-02-03c++: wrong error with constexpr array and value-init [PR108158]Marek Polacek1-4/+0
In this test case, we find ourselves evaluating 't' which is ((const struct carray *) this)->data_[VIEW_CONVERT_EXPR<long int>(index)] in cxx_eval_array_reference. ctx->object is non-null, a RESULT_DECL, so we replace it with 't': new_ctx.object = t; // result_decl replaced and then we go to cxx_eval_constant_expression to evaluate an AGGR_INIT_EXPR, where we end up evaluating an INIT_EXPR (which is in the body of the constructor for seed_or_index): ((struct seed_or_index *) this)->value_ = NON_LVALUE_EXPR <0> whereupon in cxx_eval_store_expression we go to the probe loop where the 'this' is evaluated to ze_set.tables_.first_table_.data_[0] so the 'object' is ze_set, but that isn't in ctx->global->get_value_ptr so we fail with a bogus error. ze_set is not there because it comes from a different constexpr context (it's not in cv_cache either). The problem started with r12-2304 where I added the new_ctx.object replacement. That was to prevent a type mismatch: the type of 't' and ctx.object were different. It seems clear that we shouldn't have replaced ctx.object here. The cxx_eval_array_reference I mentioned earlier is called from cxx_eval_store_expression: 6257 init = cxx_eval_constant_expression (&new_ctx, init, vc_prvalue, 6258 non_constant_p, overflow_p); which already created a new context, whose .object we should be using unless, for instance, INIT contained a.b and we're evaluating the 'a' part, which I think was the case for r12-2304; in that case ctx.object has to be something different. It no longer seems necessary to replace new_ctx.object (likely due to changes in empty class handling). PR c++/108158 gcc/cp/ChangeLog: * constexpr.cc (cxx_eval_array_reference): Don't replace new_ctx.object. gcc/testsuite/ChangeLog: * g++.dg/cpp1y/constexpr-108158.C: New test.
2023-02-01c++, openmp: Handle some OMP_*/OACC_* constructs during constant expression ↵Jakub Jelinek1-0/+47
evaluation [PR108607] While potential_constant_expression_1 handled most of OMP_* codes (by saying that they aren't potential constant expressions), OMP_SCOPE was missing in that list. I've also added OMP_SCAN, though that is less important (similarly to OMP_SECTION it ought to appear solely inside of OMP_{FOR,SIMD} resp. OMP_SECTIONS). As the testcase shows, it isn't enough, potential_constant_expression_1 can catch only some cases, as soon as one uses switch or ifs where at least one of the possible paths could be constant expression, we can run into the same codes during cxx_eval_constant_expression, so this patch handles those there as well. 2023-02-01 Jakub Jelinek <jakub@redhat.com> PR c++/108607 * constexpr.cc (cxx_eval_constant_expression): Handle OMP_* and OACC_* constructs as non-constant. (potential_constant_expression_1): Handle OMP_SCAN and OMP_SCOPE. * g++.dg/gomp/pr108607.C: New test.
2023-01-16Update copyright years.Jakub Jelinek1-1/+1
2022-12-29[C++] constexpr: request insert iff depth is okAlexandre Oliva1-3/+5
cxx_eval_call_expression requests an INSERT even in cases when it would later decide not to insert. This could break double-hashing chains. Arrange for it to use NO_INSERT when the insertion would not be completed. for gcc/cp/ChangeLog * constexpr.cc (cxx_eval_call_expression): Do not request an INSERT that would not be completed.
2022-12-23c++: get_nsdmi in template context [PR108116]Patrick Palka1-0/+4
Here during ahead of time checking of C{}, we indirectly call get_nsdmi for C::m from finish_compound_literal, which in turn calls break_out_target_exprs for C::m's (non-templated) initializer, during which we build a call to A::~A and check expr_noexcept_p for it (from build_vec_delete_1). But this is all done with processing_template_decl set, so the built A::~A call is templated (whose form was recently changed by r12-6897-gdec8d0e5fa00ceb2) which expr_noexcept_p doesn't expect, and we crash. This patch fixes this by clearing processing_template_decl before the call to break_out_target_exprs from get_nsdmi. And since it more generally seems we shouldn't be seeing (or producing) non-templated trees in break_out_target_exprs, this patch also adds an assert to that effect. PR c++/108116 gcc/cp/ChangeLog: * constexpr.cc (maybe_constant_value): Clear processing_template_decl before calling break_out_target_exprs. * init.cc (get_nsdmi): Likewise. * tree.cc (break_out_target_exprs): Assert processing_template_decl is cleared. gcc/testsuite/ChangeLog: * g++.dg/cpp0x/nsdmi-template24.C: New test.
2022-12-19c++: modules and std::source_location::current() def arg [PR100881]Patrick Palka1-1/+1
We currently declare __builtin_source_location with a const void* return type instead of the actual type const std::source_location::__impl*, and later when folding this builtin we obtain the actual type via name lookup. But the below testcase demonstrates this approach seems to interact poorly with modules, since we may import an entity that uses std::source_location::current() in its default argument (or DMI) without necessarily importing <source_location>, and thus the name lookup for std::source_location will fail at the call site (when using the default argument) unless we also import <source_location>. This patch fixes this by instead initially declaring the builtin with an auto return type and updating it appropriately upon its first use (in standard code the first/only use would be in the definition of std::source_location). Thus when folding calls to this builtin we can get at its return type through the type of the CALL_EXPR and avoid needing to do a name lookup. PR c++/100881 gcc/cp/ChangeLog: * constexpr.cc (cxx_eval_builtin_function_call): Adjust calls to fold_builtin_source_location. * cp-gimplify.cc (cp_gimplify_expr): Likewise. (cp_fold): Likewise. (get_source_location_impl_type): Remove location_t parameter and adjust accordingly. No longer static. (fold_builtin_source_location): Take a CALL_EXPR tree instead of a location and obtain the impl type from its return type. * cp-tree.h (enum cp_tree_index): Remove CPTI_SOURCE_LOCATION_IMPL enumerator. (source_location_impl): Remove. (fold_builtin_source_location): Adjust parameter type. (get_source_location_impl_type): Declare. * decl.cc (cxx_init_decl_processing): Declare __builtin_source_location with auto return type instead of const void*. (require_deduced_type): Update the return type of __builtin_source_location. gcc/testsuite/ChangeLog: * g++.dg/cpp2a/srcloc3.C: Adjust expected note s/evaluating/using. * g++.dg/cpp2a/srcloc4.C: Likewise. * g++.dg/cpp2a/srcloc5.C: Likewise. * g++.dg/cpp2a/srcloc6.C: Likewise. * g++.dg/cpp2a/srcloc7.C: Likewise. * g++.dg/cpp2a/srcloc8.C: Likewise. * g++.dg/cpp2a/srcloc9.C: Likewise. * g++.dg/cpp2a/srcloc10.C: Likewise. * g++.dg/cpp2a/srcloc11.C: Likewise. * g++.dg/cpp2a/srcloc12.C: Likewise. * g++.dg/cpp2a/srcloc13.C: Likewise. * g++.dg/modules/pr100881_a.C: New test. * g++.dg/modules/pr100881_b.C: New test.
2022-12-12Revert "c++: build initializer_list<string> in a loop [PR105838]"Jason Merrill1-3/+3
This patch broke a couple of different patterns; reverting while I work on a fix. PR c++/108701 This reverts commit bd0485f20f4794f9787237706a6308473a8e9415.
2022-12-08c++: build initializer_list<string> in a loop [PR105838]Jason Merrill1-3/+3
The previous patch avoided building an initializer_list<string> at all when building a vector<string>, but in situations where that isn't possible, we could still build the initializer_list with a loop over a constant array. This is represented using a VEC_INIT_EXPR, which required adjusting a couple of places that expected the initializer array to have the same type as the target array and fixing build_vec_init not to undo our efforts. PR c++/105838 gcc/cp/ChangeLog: * call.cc (convert_like_internal) [ck_list]: Use maybe_init_list_as_array. * constexpr.cc (cxx_eval_vec_init_1): Init might have a different type. * tree.cc (build_vec_init_elt): Likewise. * init.cc (build_vec_init): Handle from_array from a TARGET_EXPR. Retain TARGET_EXPR of a different type. gcc/testsuite/ChangeLog: * g++.dg/tree-ssa/initlist-opt2.C: New test.
2022-12-08c++: fewer allocator temps [PR105838]Jason Merrill1-10/+17
In this PR, initializing the array of std::string to pass to the vector initializer_list constructor gets very confusing to the optimizers as the number of elements increases, primarily because of all the std::allocator temporaries passed to all the string constructors. Instead of creating one for each string, let's share an allocator between all the strings; we can do this safely because we know that std::allocator is stateless and that string doesn't care about the object identity of its allocator parameter. PR c++/105838 gcc/cp/ChangeLog: * cp-tree.h (is_std_allocator): Declare. * constexpr.cc (is_std_allocator): Split out from... (is_std_allocator_allocate): ...here. * init.cc (find_temps_r): New. (find_allocator_temp): New. (build_vec_init): Use it. gcc/testsuite/ChangeLog: * g++.dg/tree-ssa/allocator-opt1.C: New test.
2022-12-08c++: commentJason Merrill1-1/+2
gcc/cp/ChangeLog: * constexpr.cc (maybe_constant_value): Add default arg comments.
2022-11-19c++: Implement C++23 P2647R1 - Permitting static constexpr variables in ↵Jakub Jelinek1-2/+6
constexpr functions The following patch implements this paper. Per further discussions it is implemented for C++23 only, so isn't treated as a DR, e.g. because the part of the standard the paper is changing didn't even exist in C++20. And we gave up on trying to implement it as a pedwarn rather than error for C++20 and older, because of implicit constexpr lambdas or -fimplicit-constexpr reasons. For C++20 and older, the only change is that passing through definitions of static or thread_local vars usable in constant expressions is now accepted in statement expressions if they aren't inside of constexpr or consteval functions. 2022-11-19 Jakub Jelinek <jakub@redhat.com> gcc/c-family/ * c-cppbuiltin.cc (c_cpp_builtins): Bump __cpp_constexpr value from 202207L to 202211L. gcc/cp/ * constexpr.cc (cxx_eval_constant_expression): Implement C++23 P2647R1 - Permitting static constexpr variables in constexpr functions. Allow DECL_EXPRs of decl_constant_var_p static or thread_local vars. (potential_constant_expression_1): Similarly, except use decl_maybe_constant_var_p instead of decl_constant_var_p if processing_template_decl. gcc/testsuite/ * g++.dg/cpp23/constexpr-nonlit17.C: New test. * g++.dg/cpp23/constexpr-nonlit18.C: New test. * g++.dg/cpp23/feat-cxx2b.C: Adjust expected __cpp_constexpr value. * g++.dg/ext/stmtexpr19.C: Don't expect an error. * g++.dg/ext/stmtexpr25.C: New test.
2022-11-18c++: implement P1492 contractsJeff Chapman II1-35/+86
Implement the P1492 versions of contracts, along with extensions that support the emulation of N4820 and other proposals. This implementation assigns a concrete semantic (one of: ignore, assume, enforce, or observe) to each contract attribute depending on its labels and configuration options. Co-authored-by: Andrew Sutton <asutton@lock3software.com> Co-authored-by: Andrew Marmaduke <amarmaduke@lock3software.com> Co-authored-by: Michael Lopez <mlopez@lock3software.com> Co-authored-by: Jason Merrill <jason@redhat.com> gcc/ChangeLog: * doc/invoke.texi: Document contracts flags. gcc/c-family/ChangeLog: * c.opt: Add contracts flags. * c-cppbuiltin.cc (c_cpp_builtins): Add contracts feature-test macros. gcc/cp/ChangeLog: * cp-tree.h (enum cp_tree_index): Add CPTI_PSEUDO_CONTRACT_VIOLATION. (pseudo_contract_violation_type): New macro. (struct saved_scope): Add x_processing_contract_condition. (processing_contract_condition): New macro. (comparing_override_contracts): New variable decl. (find_contract): New inline. (set_decl_contracts): New inline. (get_contract_semantic): New inline. (set_contract_semantic): New inline. * constexpr.cc (cxx_eval_assert): Split out from... (cxx_eval_internal_function): ...here. (cxx_eval_constant_expression): Use it for contracts. (potential_constant_expression_1): Handle contracts. * cp-gimplify.cc (cp_genericize_r): Handle contracts. * cp-objcp-common.cc (cp_tree_size): Handle contracts. (cp_common_init_ts): Handle contracts. (cp_handle_option): Handle contracts. * decl.cc (duplicate_decls): Handle contracts. (check_tag_decl): Check for bogus contracts. (start_decl): Check flag_contracts. (grokfndecl): Call rebuild_postconditions. (grokdeclarator): Handle contract attributes. (start_preparsed_function): Call start_function_contracts. (finish_function): Call finish_function_contracts. * decl2.cc (cp_check_const_attributes): Skip contracts. (comdat_linkage): Handle outlined contracts. * error.cc (dump_type): Handle null TYPE_IDENTIFIER. * g++spec.cc (EXPERIMENTAL): New macro. (lang_specific_driver): Add -lstdc++exp if -fcontracts. * mangle.cc (write_encoding): Handle outlined contracts. * module.cc (trees_out::fn_parms_init): Handle outlined contracts. (trees_in::fn_parms_init): Likewise. (check_mergeable_decl): Likewise. (module_state_config::get_dialect): Record -fcontracts. * parser.h (struct cp_unparsed_functions_entry): Add contracts. * parser.cc (unparsed_contracts): New macro. (push_unparsed_function_queues): Adjust. (contract_attribute_p): New. (cp_parser_statement): Check contracts. (cp_parser_decl_specifier_seq): Handle contracts. (cp_parser_skip_to_closing_square_bracket): Split out... (cp_parser_skip_up_to_closing_square_bracket): ...this fn. (cp_parser_class_specifier): Do contract late parsing. (cp_parser_class_head): Check contracts. (cp_parser_contract_role): New. (cp_parser_contract_mode_opt): New. (find_error, contains_error_p): New. (cp_parser_contract_attribute_spec): New. (cp_parser_late_contract_condition): New. (cp_parser_std_attribute_spec): Handle contracts. (cp_parser_save_default_args): Also save contracts. * pt.cc (register_parameter_specializations): No longer static. (register_local_identity): New. (check_explicit_specialization): Call remove_contract_attributes. (tsubst_contract, tsubst_contract_attribute): New. (tsubst_contract_attributes): New. (tsubst_attribute): Add comment. (tsubst_copy): Also allow parm when processing_contract_condition. (tsubst_expr): Handle contracts. (regenerate_decl_from_template): Handle contracts. * search.cc (check_final_overrider): Compare contracts. * semantics.cc (set_cleanup_locs): Skip POSTCONDITION_STMT. (finish_non_static_data_member): Check contracts. (finish_this_expr): Check contracts. (process_outer_var_ref): Handle contracts. (finish_id_expression_1): Handle contracts. (apply_deduced_return_type): Adjust contracts. * tree.cc (handle_contract_attribute): New. (get_innermost_component, is_this_expression): New. (comparing_this_references): New. (equivalent_member_references): New. (cp_tree_equal): Check it. * typeck.cc (check_return_expr): Apply contracts. * Make-lang.in: Add contracts.o. * config-lang.in: Add contracts.cc. * cp-tree.def (ASSERTION_STMT, PRECONDITION_STMT) (POSTCONDITION_STMT): New. * contracts.h: New file. * contracts.cc: New file. gcc/testsuite/ChangeLog: * g++.dg/modules/modules.exp: Pass dg-options to link command. * lib/g++.exp: Add -L for libstdc++exp.a. * g++.dg/contracts/backtrace_handler/assert_fail.cpp: New test. * g++.dg/contracts/backtrace_handler/handle_contract_violation.cpp: New test. * g++.dg/contracts/contracts-access1.C: New test. * g++.dg/contracts/contracts-assume1.C: New test. * g++.dg/contracts/contracts-assume2.C: New test. * g++.dg/contracts/contracts-assume3.C: New test. * g++.dg/contracts/contracts-assume4.C: New test. * g++.dg/contracts/contracts-assume5.C: New test. * g++.dg/contracts/contracts-assume6.C: New test. * g++.dg/contracts/contracts-comdat1.C: New test. * g++.dg/contracts/contracts-config1.C: New test. * g++.dg/contracts/contracts-constexpr1.C: New test. * g++.dg/contracts/contracts-constexpr2.C: New test. * g++.dg/contracts/contracts-constexpr3.C: New test. * g++.dg/contracts/contracts-conversion1.C: New test. * g++.dg/contracts/contracts-ctor-dtor1.C: New test. * g++.dg/contracts/contracts-ctor-dtor2.C: New test. * g++.dg/contracts/contracts-cv1.C: New test. * g++.dg/contracts/contracts-deduced1.C: New test. * g++.dg/contracts/contracts-deduced2.C: New test. * g++.dg/contracts/contracts-friend1.C: New test. * g++.dg/contracts/contracts-ft1.C: New test. * g++.dg/contracts/contracts-ignore1.C: New test. * g++.dg/contracts/contracts-ignore2.C: New test. * g++.dg/contracts/contracts-large-return.C: New test. * g++.dg/contracts/contracts-multiline1.C: New test. * g++.dg/contracts/contracts-multiple-inheritance1.C: New test. * g++.dg/contracts/contracts-multiple-inheritance2.C: New test. * g++.dg/contracts/contracts-nested-class1.C: New test. * g++.dg/contracts/contracts-nested-class2.C: New test. * g++.dg/contracts/contracts-nocopy1.C: New test. * g++.dg/contracts/contracts-override.C: New test. * g++.dg/contracts/contracts-post1.C: New test. * g++.dg/contracts/contracts-post2.C: New test. * g++.dg/contracts/contracts-post3.C: New test. * g++.dg/contracts/contracts-post4.C: New test. * g++.dg/contracts/contracts-post5.C: New test. * g++.dg/contracts/contracts-post6.C: New test. * g++.dg/contracts/contracts-pre1.C: New test. * g++.dg/contracts/contracts-pre10.C: New test. * g++.dg/contracts/contracts-pre2.C: New test. * g++.dg/contracts/contracts-pre2a1.C: New test. * g++.dg/contracts/contracts-pre2a2.C: New test. * g++.dg/contracts/contracts-pre3.C: New test. * g++.dg/contracts/contracts-pre4.C: New test. * g++.dg/contracts/contracts-pre5.C: New test. * g++.dg/contracts/contracts-pre6.C: New test. * g++.dg/contracts/contracts-pre7.C: New test. * g++.dg/contracts/contracts-pre9.C: New test. * g++.dg/contracts/contracts-redecl1.C: New test. * g++.dg/contracts/contracts-redecl2.C: New test. * g++.dg/contracts/contracts-redecl3.C: New test. * g++.dg/contracts/contracts-redecl4.C: New test. * g++.dg/contracts/contracts-redecl5.C: New test. * g++.dg/contracts/contracts-redecl6.C: New test. * g++.dg/contracts/contracts-redecl7.C: New test. * g++.dg/contracts/contracts-redecl8.C: New test. * g++.dg/contracts/contracts-tmpl-attr1.C: New test. * g++.dg/contracts/contracts-tmpl-spec1.C: New test. * g++.dg/contracts/contracts-tmpl-spec2.C: New test. * g++.dg/contracts/contracts-tmpl-spec3.C: New test. * g++.dg/contracts/contracts1.C: New test. * g++.dg/contracts/contracts10.C: New test. * g++.dg/contracts/contracts11.C: New test. * g++.dg/contracts/contracts12.C: New test. * g++.dg/contracts/contracts13.C: New test. * g++.dg/contracts/contracts14.C: New test. * g++.dg/contracts/contracts15.C: New test. * g++.dg/contracts/contracts16.C: New test. * g++.dg/contracts/contracts17.C: New test. * g++.dg/contracts/contracts18.C: New test. * g++.dg/contracts/contracts19.C: New test. * g++.dg/contracts/contracts2.C: New test. * g++.dg/contracts/contracts20.C: New test. * g++.dg/contracts/contracts22.C: New test. * g++.dg/contracts/contracts24.C: New test. * g++.dg/contracts/contracts25.C: New test. * g++.dg/contracts/contracts3.C: New test. * g++.dg/contracts/contracts35.C: New test. * g++.dg/contracts/contracts4.C: New test. * g++.dg/contracts/contracts5.C: New test. * g++.dg/contracts/contracts6.C: New test. * g++.dg/contracts/contracts7.C: New test. * g++.dg/contracts/contracts8.C: New test. * g++.dg/contracts/contracts9.C: New test. * g++.dg/modules/contracts-1_a.C: New test. * g++.dg/modules/contracts-1_b.C: New test. * g++.dg/modules/contracts-2_a.C: New test. * g++.dg/modules/contracts-2_b.C: New test. * g++.dg/modules/contracts-2_c.C: New test. * g++.dg/modules/contracts-3_a.C: New test. * g++.dg/modules/contracts-3_b.C: New test. * g++.dg/modules/contracts-4_a.C: New test. * g++.dg/modules/contracts-4_b.C: New test. * g++.dg/modules/contracts-4_c.C: New test. * g++.dg/modules/contracts-4_d.C: New test. * g++.dg/modules/contracts-tpl-friend-1_a.C: New test. * g++.dg/modules/contracts-tpl-friend-1_b.C: New test. * g++.dg/contracts/backtrace_handler/Makefile: New test. * g++.dg/contracts/backtrace_handler/README: New test. * g++.dg/contracts/backtrace_handler/example_out.txt: New test. * g++.dg/contracts/backtrace_handler/example_pretty.txt: New test. * g++.dg/contracts/backtrace_handler/prettytrace.sh: New test. * g++.dg/contracts/except_preload_handler/Makefile: New test. * g++.dg/contracts/except_preload_handler/README: New test. * g++.dg/contracts/except_preload_handler/assert_fail.cpp: New test. * g++.dg/contracts/except_preload_handler/handle_contract_violation.cpp: New test. * g++.dg/contracts/noexcept_preload_handler/Makefile: New test. * g++.dg/contracts/noexcept_preload_handler/README: New test. * g++.dg/contracts/noexcept_preload_handler/assert_fail.cpp: New test. * g++.dg/contracts/noexcept_preload_handler/handle_contract_violation.cpp: New test. * g++.dg/contracts/preload_handler/Makefile: New test. * g++.dg/contracts/preload_handler/README: New test. * g++.dg/contracts/preload_handler/assert_fail.cpp: New test. * g++.dg/contracts/preload_handler/handle_contract_violation.cpp: New test. * g++.dg/contracts/preload_nocontinue_handler/Makefile: New test. * g++.dg/contracts/preload_nocontinue_handler/README: New test. * g++.dg/contracts/preload_nocontinue_handler/assert_fail.cpp: New test. * g++.dg/contracts/preload_nocontinue_handler/handle_contract_violation.cpp: New test. * g++.dg/contracts/preload_nocontinue_handler/nocontinue.cpp: New test.
2022-11-16c++: P2448 - Relaxing some constexpr restrictions [PR106649]Marek Polacek1-98/+201
This patch implements C++23 P2448, which lifts more restrictions on the constexpr keyword. It's effectively going the way of being just a hint (hello, inline!). This gist is relatively simple: in C++23, a constexpr function's return type/parameter type doesn't have to be a literal type; and you can have a constexpr function for which no invocation satisfies the requirements of a core constant expression. For example, void f(int& i); // not constexpr constexpr void g(int& i) { f(i); // unconditionally calls a non-constexpr function } is now OK, even though there isn't an invocation of 'g' that would be a constant expression. Maybe 'f' will be made constexpr soon, or maybe this depends on the version of C++ used, and similar. The patch is unfortunately not that trivial. The important bit is to use the new require_potential_rvalue_constant_expression_fncheck in maybe_save_constexpr_fundef (and where appropriate). It has a new flag that says that we're checking the body of a constexpr function, and in that case it's OK to find constructs that aren't a constant expression. Since it's useful to be able to check for problematic constructs even in C++23, this patch implements a new warning, -Winvalid-constexpr, which is a pedwarn turned on by default in C++20 and earlier, and which can be turned on in C++23 as well, in which case it's an ordinary warning. This I implemented by using the new function constexpr_error, used in p_c_e_1 and friends. (In some cases I believe fundef_p will be always false (= hard error), but it made sense to me to be consistent and use constexpr_error throughout p_c_e_1.) While working on this I think I found a bug, see constexpr-nonlit15.C and <https://gcc.gnu.org/PR107598>. This patch doesn't address that. This patch includes changes to diagnose the problem if the user doesn't use -Winvalid-constexpr and calls a constexpr function that in fact isn't constexpr-ready yet: maybe_save_constexpr_fundef registers the function if warn_invalid_constexpr is 0 and explain_invalid_constexpr_fn then gives the diagnostic. PR c++/106649 gcc/c-family/ChangeLog: * c-cppbuiltin.cc (c_cpp_builtins): Update value of __cpp_constexpr for C++23. * c-opts.cc (c_common_post_options): Set warn_invalid_constexpr depending on cxx_dialect. * c.opt (Winvalid-constexpr): New option. gcc/cp/ChangeLog: * constexpr.cc (constexpr_error): New function. (is_valid_constexpr_fn): Use constexpr_error. (maybe_save_constexpr_fundef): Call require_potential_rvalue_constant_expression_fncheck rather than require_potential_rvalue_constant_expression. Register the function if -Wno-invalid-constexpr was specified. (explain_invalid_constexpr_fn): Don't return early if a function marked 'constexpr' that isn't actually a constant expression was called. (non_const_var_error): Add a bool parameter. Use constexpr_error. (inline_asm_in_constexpr_error): Likewise. (cxx_eval_constant_expression): Adjust calls to non_const_var_error and inline_asm_in_constexpr_error. (potential_constant_expression_1): Add a bool parameter. Use constexpr_error. (require_potential_rvalue_constant_expression_fncheck): New function. * cp-tree.h (require_potential_rvalue_constant_expression_fncheck): Declare. * method.cc (struct comp_info): Call require_potential_rvalue_constant_expression_fncheck rather than require_potential_rvalue_constant_expression. gcc/ChangeLog: * doc/invoke.texi: Document -Winvalid-constexpr. gcc/testsuite/ChangeLog: * g++.dg/cpp0x/constexpr-ctor2.C: Expect an error in c++20_down only. * g++.dg/cpp0x/constexpr-default-ctor.C: Likewise. * g++.dg/cpp0x/constexpr-diag3.C: Likewise. * g++.dg/cpp0x/constexpr-ex1.C: Likewise. * g++.dg/cpp0x/constexpr-friend.C: Likewise. * g++.dg/cpp0x/constexpr-generated1.C: Likewise. * g++.dg/cpp0x/constexpr-ice5.C: Likewise. * g++.dg/cpp0x/constexpr-ice6.C: Likewise. * g++.dg/cpp0x/constexpr-memfn1.C: Likewise. * g++.dg/cpp0x/constexpr-neg2.C: Likewise. * g++.dg/cpp0x/constexpr-non-const-arg.C: Likewise. * g++.dg/cpp0x/constexpr-reinterpret1.C: Likewise. * g++.dg/cpp0x/pr65327.C: Likewise. * g++.dg/cpp1y/constexpr-105050.C: Likewise. * g++.dg/cpp1y/constexpr-89285-2.C: Likewise. * g++.dg/cpp1y/constexpr-89285.C: Likewise. * g++.dg/cpp1y/constexpr-89785-2.C: Likewise. * g++.dg/cpp1y/constexpr-neg1.C: Likewise. * g++.dg/cpp1y/constexpr-nsdmi7b.C: Likewise. * g++.dg/cpp1y/constexpr-throw.C: Likewise. * g++.dg/cpp23/constexpr-nonlit3.C: Remove dg-error. * g++.dg/cpp23/constexpr-nonlit6.C: Call the test functions. * g++.dg/cpp23/feat-cxx2b.C: Adjust the expected value of __cpp_constexpr. * g++.dg/cpp2a/consteval3.C: Remove dg-error. * g++.dg/cpp2a/constexpr-new7.C: Expect an error in c++20_down only. * g++.dg/cpp2a/constexpr-try5.C: Remove dg-error. * g++.dg/cpp2a/spaceship-constexpr1.C: Expect an error in c++20_down only. * g++.dg/cpp2a/spaceship-eq3.C: Likewise. * g++.dg/diagnostic/constexpr1.C: Remove dg-error. * g++.dg/gomp/pr79664.C: Use -Winvalid-constexpr -pedantic-errors. * g++.dg/ubsan/vptr-4.C: Likewise. * g++.dg/cpp23/constexpr-nonlit10.C: New test. * g++.dg/cpp23/constexpr-nonlit11.C: New test. * g++.dg/cpp23/constexpr-nonlit12.C: New test. * g++.dg/cpp23/constexpr-nonlit13.C: New test. * g++.dg/cpp23/constexpr-nonlit14.C: New test. * g++.dg/cpp23/constexpr-nonlit15.C: New test. * g++.dg/cpp23/constexpr-nonlit16.C: New test. * g++.dg/cpp23/constexpr-nonlit8.C: New test. * g++.dg/cpp23/constexpr-nonlit9.C: New test.
2022-11-15c++: remove i_c_e_p parm from tsubst_copy_and_buildPatrick Palka1-3/+1
It seems the only and original purpose of tsubst_copy_and_build's integral_constant_expression_p boolean parameter (added in r116276, which predates the constexpr machinery) is to diagnose certain constructs that aren't allowed to appear in a C++98 integral constant expression context, specifically casts to a non-integral type (diagnosed from the *_CAST_EXPR case of tsubst_copy_and_build) or dependent names that resolve to a non-constant decl (diagnosed from the IDENTIFIER_NODE case of tsubst_copy_and_build). The parameter has no effect outside of C++98 AFAICT. But diagnosing such constructs should arguably be the job of the constexpr machinery (e.g. is_constant_expression) after substitution, and doing it during substitution by way of an additional parameter complicates the API of this workhorse function for what amounts to a couple of archaic C++98 restrictions. And it seems is_constant_expression already does a good job of diagnosing the aforementioned two constructs in C++98 mode, at least as far as our testsuite is concerned. So this patch removes this parameter from tsubst_copy_and_build, tsubst_expr and tsubst_copy_and_build_call_args. The only interesting changes are to potential_constant_expression_1 and the IDENTIFIER_NODE and *_CAST_EXPR cases of tsubst_copy_and_build; the rest are mechanical adjustments to the functions' signatures and their call sites. gcc/cp/ChangeLog: * constexpr.cc (potential_constant_expression_1) <case *_CAST_EXPR>: Use cast_valid_in_integral_constant_expression_p instead of open coding it. * constraint.cc (tsubst_valid_expression_requirement): Adjust calls to tsubst_copy_and_build and tsubst_expr. (tsubst_constraint): Likewise. (satisfy_atom): Likewise. (diagnose_trait_expr): Likewise. * cp-tree.h (tsubst_copy_and_build): Remove i_c_e_p parameter. (tsubst_expr): Likewise. * init.cc (get_nsdmi): Adjust calls to tsubst_copy_and_build and tsubst_expr. * pt.cc (expand_integer_pack): Likewise. (instantiate_non_dependent_expr_internal): Likewise. (tsubst_friend_function): Likewise. (tsubst_attribute): Likewise. (instantiate_class_template): Likewise. (tsubst_template_arg): Likewise. (gen_elem_of_pack_expansion_instantiation): Likewise. (tsubst_fold_expr_init): Likewise. (tsubst_pack_expansion): Likewise. (tsubst_default_argument): Likewise. (tsubst_function_decl): Likewise. (tsubst_decl): Likewise. (tsubst_arg_types): Likewise. (tsubst_exception_specification): Likewise. (tsubst): Likewise. (tsubst_init): Likewise. (tsubst_copy): Likewise. (tsubst_omp_clause_decl): Likewise. (tsubst_omp_clauses): Likewise. (tsubst_copy_asm_operands): Likewise. (tsubst_omp_for_iterator): Likewise. (tsubst_expr): Likewise. Remove i_c_e_p parameter. (tsubst_omp_udr): Likewise. (tsubst_non_call_postfix_expression): Likewise. Remove i_c_e_p parameter. (tsubst_lambda_expr): Likewise. (tsubst_copy_and_build_call_args): Likewise. (tsubst_copy_and_build): Likewise. Remove i_c_e_p parameter. <case IDENTIFIER_NODE>: Adjust call to finish_id_expression following removal of i_c_e_p. <case *_CAST_EXPR>: Remove C++98-specific cast validity check guarded by i_c_e_p. (maybe_instantiate_noexcept): Adjust calls to tsubst_copy_and_build and tsubst_expr. (instantiate_body): Likewise. (instantiate_decl): Likewise. (tsubst_initializer_list): Likewise. (tsubst_enum): Likewise. gcc/objcp/ChangeLog: * objcp-lang.cc (objcp_tsubst_copy_and_build): Adjust calls to tsubst_copy_and_build and tsubst_expr. gcc/testsuite/ChangeLog: * g++.dg/template/crash55.C: Don't expect additional C++98-specific diagnostics. * g++.dg/template/ref3.C: Remove C++98-specific xfail.
2022-10-25c++: correct fold_operand changeJason Merrill1-1/+2
Still want the conversion to bool. gcc/cp/ChangeLog: * constexpr.cc (find_failing_clause_r): Re-add the call to contextual_conv_bool.
2022-10-25c++: constexpr-evaluate more assumesJason Merrill1-44/+92
The initial [[assume]] support avoided evaluating assumes with TREE_SIDE_EFFECTS set, such as calls, because we don't want any side-effects that change the constexpr state. This patch allows us to evaluate expressions with that flag set by tracking which variables the evaluation is allowed to modify, and giving up if it tries to touch any others. I considered allowing changes to other variables and then rolling them back, but that seems like a rare enough situation that it doesn't seem worth working to handle nicely at this point. gcc/cp/ChangeLog: * constexpr.cc (class constexpr_global_ctx): Add modifiable field, get_value, get_value_ptr, put_value, remove_value, flush_modifiable member functions. (class modifiable_tracker): New. (cxx_eval_internal_function): Use it. (diagnose_failing_condition): Strip CLEANUP_POINT_EXPR. gcc/testsuite/ChangeLog: * g++.dg/cpp23/attr-assume9.C: New test. * g++.dg/cpp23/attr-assume10.C: New test.
2022-10-25c++: improve failed constexpr assume diagnosticJason Merrill1-13/+50
I noticed that we were printing "the comparison reduces to (x == 42)" when we should be able to give the value of x. Fixed by doing the same evaluation in diagnose_failing_condition that we already do in find_failing_clause. gcc/cp/ChangeLog: * constexpr.cc (fold_operand): New function. (find_failing_clause_r): Add const. (find_failing_clause): Add const. (diagnose_failing_condition): Add ctx parameter. (cxx_eval_internal_function): Pass it. * semantics.cc (diagnose_failing_condition): Move to constexpr.cc. * cp-tree.h: Adjust. gcc/testsuite/ChangeLog: * g++.dg/cpp23/attr-assume2.C: Expect constant values.
2022-10-24c++: Fix up constexpr handling of char/signed char/short pre/post ↵Jakub Jelinek1-0/+12
inc/decrement [PR105774] signed char, char or short int pre/post inc/decrement are represented by normal {PRE,POST}_{INC,DEC}REMENT_EXPRs in the FE and only gimplification ensures that the {PLUS,MINUS}_EXPR is done in unsigned version of those types: case PREINCREMENT_EXPR: case PREDECREMENT_EXPR: case POSTINCREMENT_EXPR: case POSTDECREMENT_EXPR: { tree type = TREE_TYPE (TREE_OPERAND (*expr_p, 0)); if (INTEGRAL_TYPE_P (type) && c_promoting_integer_type_p (type)) { if (!TYPE_OVERFLOW_WRAPS (type)) type = unsigned_type_for (type); return gimplify_self_mod_expr (expr_p, pre_p, post_p, 1, type); } break; } This means during constant evaluation we need to do it similarly (either using unsigned_type_for or using widening to integer_type_node). The following patch does the latter. 2022-10-24 Jakub Jelinek <jakub@redhat.com> PR c++/105774 * constexpr.cc (cxx_eval_increment_expression): For signed types that promote to int, evaluate PLUS_EXPR or MINUS_EXPR in int type. * g++.dg/cpp1y/constexpr-105774.C: New test.
2022-10-21c++: Don't shortcut TREE_CONSTANT vector type CONSTRUCTORs in ↵Jakub Jelinek1-8/+13
cxx_eval_constant_expression [PR107295] The excess precision support broke building skia (dependency of firefox) on ia32 (it has something like the a constexpr variable), but as the other cases show, it is actually a preexisting problem if one uses casts from constants with wider floating point types. The problem is that cxx_eval_constant_expression tries to short-cut processing of TREE_CONSTANT CONSTRUCTORs if they satisfy reduced_constant_expression_p - instead of calling cxx_eval_bare_aggregate on them it just verifies flags and if they are TREE_CONSTANT even after that, just fold. Now, on the testcase we have a TREE_CONSTANT CONSTRUCTOR containing TREE_CONSTANT NOP_EXPR of REAL_CST. And, fold, which isn't recursive, doesn't optimize that into VECTOR_CST, while later on we are only able to optimize VECTOR_CST arithmetics, not arithmetics with vector CONSTRUCTORs. The following patch fixes that by rejecting CONSTRUCTORs with vector type in reduced_constant_expression_p regardless of whether they have CONSTRUCTOR_NO_CLEARING set or not, folding result in cxx_eval_bare_aggregate even if nothing has changed but it wasn't non-constant and removing folding from the TREE_CONSTANT reduced_constant_expression_p short-cut. 2022-10-21 Jakub Jelinek <jakub@redhat.com> PR c++/107295 * constexpr.cc (reduced_constant_expression_p) <case CONSTRUCTOR>: Return false for VECTOR_TYPE CONSTRUCTORs even without CONSTRUCTOR_NO_CLEARING set on them. (cxx_eval_bare_aggregate): If constant but !changed, fold before returning VECTOR_TYPE_P CONSTRUCTOR. (cxx_eval_constant_expression) <case CONSTRUCTOR>: Don't fold TREE_CONSTANT CONSTRUCTOR, just return it. * g++.dg/ext/vector42.C: New test.
2022-10-14c++ modules: ICE with dynamic_cast [PR106304]Patrick Palka1-1/+1
The FUNCTION_DECL we build for __dynamic_cast has an empty DECL_CONTEXT but trees_out::tree_node expects FUNCTION_DECLs to have non-empty DECL_CONTEXT, thus we crash when streaming out the dynamic_cast in the below testcase. This patch naively fixes this by setting DECL_CONTEXT for __dynamic_cast appropriately. I suppose we should push it into the namespace too, like we do for __cxa_atexit which is similarly lazily declared. PR c++/106304 gcc/cp/ChangeLog: * constexpr.cc (cxx_dynamic_cast_fn_p): Check for abi_node instead of global_namespace. * rtti.cc (build_dynamic_cast_1): Set DECL_CONTEXT and DECL_SOURCE_LOCATION when building dynamic_cast_node. Push it into the namespace. gcc/testsuite/ChangeLog: * g++.dg/modules/pr106304_a.C: New test. * g++.dg/modules/pr106304_b.C: New test.
2022-10-14c++: Implement excess precision support for C++ [PR107097, PR323]Jakub Jelinek1-0/+16
The following patch implements excess precision support for C++. Like for C, it uses EXCESS_PRECISION_EXPR tree to say that its operand is evaluated in excess precision and what the semantic type of the expression is. In most places I've followed what the C FE does in similar spots, so e.g. for binary ops if one or both operands are already EXCESS_PRECISION_EXPR, strip those away or for operations that might need excess precision (+, -, *, /) check if the operands should use excess precision and convert to that type and at the end wrap into EXCESS_PRECISION_EXPR with the common semantic type. This patch follows the C99 handling where it differs from C11 handling. There are some cases which needed to be handled differently, the C FE can just strip EXCESS_PRECISION_EXPR (replace it with its operand) when handling explicit cast, but that IMHO isn't right for C++ - the discovery what exact conversion should be used (e.g. if user conversion or standard or their sequence) should be decided based on the semantic type (i.e. type of EXCESS_PRECISION_EXPR), and that decision continues in convert_like* where we pick the right user conversion, again, if say some class has ctor from double and long double and we are on ia32 with standard excess precision promoting float/double to long double, then we should pick the ctor from double. Or when some other class has ctor from just double, and EXCESS_PRECISION_EXPR semantic type is float, we should choose the user ctor from double, but actually just convert the long double excess precision to double and not to float first. We need to make sure even identity conversion converts from excess precision to the semantic one though, but if identity is chained with other conversions, we don't want the identity next_conversion to drop to semantic precision only to widen afterwards. The existing testcases tweaks were for cases on i686-linux where excess precision breaks those tests, e.g. if we have double d = 4.2; if (d == 4.2) then it does the expected thing only with -fexcess-precision=fast, because with -fexcess-precision=standard it is actually double d = 4.2; if ((long double) d == 4.2L) where 4.2L is different from 4.2. I've added -fexcess-precision=fast to some tests and changed other tests to use constants that are exactly representable and don't suffer from these excess precision issues. There is one exception, pr68180.C looks like a bug in the patch which is also present in the C FE (so I'd like to get it resolved incrementally in both). Reduced testcase: typedef float __attribute__((vector_size (16))) float32x4_t; float32x4_t foo(float32x4_t x, float y) { return x + y; } with -m32 -std=c11 -Wno-psabi or -m32 -std=c++17 -Wno-psabi it is rejected with: pr68180.c:2:52: error: conversion of scalar ‘long double’ to vector ‘float32x4_t’ {aka ‘__vector(4) float’} involves truncation but without excess precision (say just -std=c11 -Wno-psabi or -std=c++17 -Wno-psabi) it is accepted. Perhaps we should pass down the semantic type to scalar_to_vector and use the semantic type rather than excess precision type in the diagnostics. 2022-10-14 Jakub Jelinek <jakub@redhat.com> PR middle-end/323 PR c++/107097 gcc/ * doc/invoke.texi (-fexcess-precision=standard): Mention that the option now also works in C++. gcc/c-family/ * c-common.def (EXCESS_PRECISION_EXPR): Remove comment part about the tree being specific to C/ObjC. * c-opts.cc (c_common_post_options): Handle flag_excess_precision in C++ the same as in C. * c-lex.cc (interpret_float): Set const_type to excess_precision () even for C++. gcc/cp/ * parser.cc (cp_parser_primary_expression): Handle EXCESS_PRECISION_EXPR with REAL_CST operand the same as REAL_CST. * cvt.cc (cp_ep_convert_and_check): New function. * call.cc (build_conditional_expr): Add excess precision support. When type_after_usual_arithmetic_conversions returns error_mark_node, use gcc_checking_assert that it is because of uncomparable floating point ranks instead of checking all those conditions and make it work also with complex types. (convert_like_internal): Likewise. Add NESTED_P argument, pass true to recursive calls to convert_like. (convert_like): Add NESTED_P argument, pass it through to convert_like_internal. For other overload pass false to it. (convert_like_with_context): Pass false to NESTED_P. (convert_arg_to_ellipsis): Add excess precision support. (magic_varargs_p): For __builtin_is{finite,inf,inf_sign,nan,normal} and __builtin_fpclassify return 2 instead of 1, document what it means. (build_over_call): Don't handle former magic 2 which is no longer used, instead for magic 1 remove EXCESS_PRECISION_EXPR. (perform_direct_initialization_if_possible): Pass false to NESTED_P convert_like argument. * constexpr.cc (cxx_eval_constant_expression): Handle EXCESS_PRECISION_EXPR. (potential_constant_expression_1): Likewise. * pt.cc (tsubst_copy, tsubst_copy_and_build): Likewise. * cp-tree.h (cp_ep_convert_and_check): Declare. * cp-gimplify.cc (cp_fold): Handle EXCESS_PRECISION_EXPR. * typeck.cc (cp_common_type): For COMPLEX_TYPEs, return error_mark_node if recursive call returned it. (convert_arguments): For magic 1 remove EXCESS_PRECISION_EXPR. (cp_build_binary_op): Add excess precision support. When cp_common_type returns error_mark_node, use gcc_checking_assert that it is because of uncomparable floating point ranks instead of checking all those conditions and make it work also with complex types. (cp_build_unary_op): Likewise. (cp_build_compound_expr): Likewise. (build_static_cast_1): Remove EXCESS_PRECISION_EXPR. gcc/testsuite/ * gcc.target/i386/excess-precision-1.c: For C++ wrap abort and exit declarations into extern "C" block. * gcc.target/i386/excess-precision-2.c: Likewise. * gcc.target/i386/excess-precision-3.c: Likewise. Remove check_float_nonproto and check_double_nonproto tests for C++. * gcc.target/i386/excess-precision-7.c: For C++ wrap abort and exit declarations into extern "C" block. * gcc.target/i386/excess-precision-9.c: Likewise. * g++.target/i386/excess-precision-1.C: New test. * g++.target/i386/excess-precision-2.C: New test. * g++.target/i386/excess-precision-3.C: New test. * g++.target/i386/excess-precision-4.C: New test. * g++.target/i386/excess-precision-5.C: New test. * g++.target/i386/excess-precision-6.C: New test. * g++.target/i386/excess-precision-7.C: New test. * g++.target/i386/excess-precision-9.C: New test. * g++.target/i386/excess-precision-11.C: New test. * c-c++-common/dfp/convert-bfp-10.c: Add -fexcess-precision=fast as dg-additional-options. * c-c++-common/dfp/compare-eq-const.c: Likewise. * g++.dg/cpp1z/constexpr-96862.C: Likewise. * g++.dg/cpp1z/decomp12.C (main): Use 2.25 instead of 2.3 to avoid excess precision differences. * g++.dg/other/thunk1.C: Add -fexcess-precision=fast as dg-additional-options. * g++.dg/vect/pr64410.cc: Likewise. * g++.dg/cpp1y/pr68180.C: Likewise. * g++.dg/vect/pr89653.cc: Likewise. * g++.dg/cpp0x/variadic-tuple.C: Likewise. * g++.dg/cpp0x/nsdmi-union1.C: Use 4.25 instead of 4.2 to avoid excess precision differences. * g++.old-deja/g++.brendan/copy9.C: Add -fexcess-precision=fast as dg-additional-options. * g++.old-deja/g++.brendan/overload7.C: Likewise.
2022-10-12c++: defer all consteval in default args [DR2631]Jason Merrill1-20/+0
The proposed resolution of CWG2631 extends our current handling of source_location::current to all consteval functions: default arguments are not evaluated until they're used in a call, the same should apply to evaluation of immediate invocations. And similarly for default member initializers. Previously we folded source_location::current in cp_fold_r; now we fold all consteval calls in default arguments/member initializers in bot_replace. DR 2631 gcc/cp/ChangeLog: * cp-tree.h (source_location_current_p): Remove. * name-lookup.h (struct cp_binding_level): Remove immediate_fn_ctx_p. * call.cc (in_immediate_context): All default args and DMI are potentially immediate context. (immediate_invocation_p): Don't treat source_location specially. (struct in_consteval_if_p_temp_override): Move to cp-tree.h. * constexpr.cc (get_nth_callarg): Move to cp-tree.h. * cp-gimplify.cc (cp_fold_r): Don't fold consteval. * name-lookup.cc (begin_scope): Don't set immediate_fn_ctx_p. * parser.cc (cp_parser_lambda_declarator_opt): Likewise. (cp_parser_direct_declarator): Likewise. * pt.cc (tsubst_default_argument): Open sk_function_parms level. * tree.cc (source_location_current_p): Remove. (bot_replace): Fold consteval here. (break_out_target_exprs): Handle errors. gcc/testsuite/ChangeLog: * g++.dg/cpp2a/consteval-defarg3.C: New test.
2022-10-06c++, c: Implement C++23 P1774R8 - Portable assumptions [PR106654]Jakub Jelinek1-0/+90
The following patch implements C++23 P1774R8 - Portable assumptions paper, by introducing support for [[assume (cond)]]; attribute for C++. In addition to that the patch adds [[gnu::assume (cond)]]; and __attribute__((assume (cond))); support to both C and C++. As described in C++23, the attribute argument is conditional-expression rather than the usual assignment-expression for attribute arguments, the condition is contextually converted to bool (for C truthvalue conversion is done on it) and is never evaluated at runtime. For C++ constant expression evaluation, I only check the simplest conditions for undefined behavior, because otherwise I'd need to undo changes to *ctx->global which happened during the evaluation (but I believe the spec allows that and we can further improve later). The patch uses a new internal function, .ASSUME, to hold the condition in the FEs. At gimplification time, if the condition is simple/without side-effects, it is gimplified as if (cond) ; else __builtin_unreachable (); and otherwise for now dropped on the floor. The intent is to incrementally outline the conditions into separate artificial functions and use .ASSUME further to tell the ranger and perhaps other optimization passes about the assumptions, as detailed in the PR. When implementing it, I found that assume entry hasn't been added to https://eel.is/c++draft/cpp.cond#6 Jonathan said he'll file a NB comment about it, this patch assumes it has been added into the table as 202207L when the paper has been voted in. With the attributes for both C/C++, I'd say we don't need to add __builtin_assume with similar purpose, especially when __builtin_assume in LLVM is just weird. It is strange for side-effects in function call's argument not to be evaluated, and LLVM in that case (annoyingly) warns and ignores the side-effects (but doesn't do then anything with it), if there are no side-effects, it will work like our if (!cond) __builtin_unreachable (); 2022-10-06 Jakub Jelinek <jakub@redhat.com> PR c++/106654 gcc/ * internal-fn.def (ASSUME): New internal function. * internal-fn.h (expand_ASSUME): Declare. * internal-fn.cc (expand_ASSUME): Define. * gimplify.cc (gimplify_call_expr): Gimplify IFN_ASSUME. * fold-const.h (simple_condition_p): Declare. * fold-const.cc (simple_operand_p_2): Rename to ... (simple_condition_p): ... this. Remove forward declaration. No longer static. Adjust function comment and fix a typo in it. Adjust recursive call. (simple_operand_p): Adjust function comment. (fold_truth_andor): Adjust simple_operand_p_2 callers to call simple_condition_p. * doc/extend.texi: Document assume attribute. Move fallthrough attribute example to its section. gcc/c-family/ * c-attribs.cc (handle_assume_attribute): New function. (c_common_attribute_table): Add entry for assume attribute. * c-lex.cc (c_common_has_attribute): Handle __have_cpp_attribute (assume). gcc/c/ * c-parser.cc (handle_assume_attribute): New function. (c_parser_declaration_or_fndef): Handle assume attribute. (c_parser_attribute_arguments): Add assume_attr argument, if true, parse first argument as conditional expression. (c_parser_gnu_attribute, c_parser_std_attribute): Adjust c_parser_attribute_arguments callers. (c_parser_statement_after_labels) <case RID_ATTRIBUTE>: Handle assume attribute. gcc/cp/ * cp-tree.h (process_stmt_assume_attribute): Implement C++23 P1774R8 - Portable assumptions. Declare. (diagnose_failing_condition): Declare. (find_failing_clause): Likewise. * parser.cc (assume_attr): New enumerator. (cp_parser_parenthesized_expression_list): Handle assume_attr. Remove identifier variable, for id_attr push the identifier into expression_list right away instead of inserting it before all the others at the end. (cp_parser_conditional_expression): New function. (cp_parser_constant_expression): Use it. (cp_parser_statement): Handle assume attribute. (cp_parser_expression_statement): Likewise. (cp_parser_gnu_attribute_list): Use assume_attr for assume attribute. (cp_parser_std_attribute): Likewise. Handle standard assume attribute like gnu::assume. * cp-gimplify.cc (process_stmt_assume_attribute): New function. * constexpr.cc: Include fold-const.h. (find_failing_clause_r, find_failing_clause): New functions, moved from semantics.cc with ctx argument added and if non-NULL, call cxx_eval_constant_expression rather than fold_non_dependent_expr. (cxx_eval_internal_function): Handle IFN_ASSUME. (potential_constant_expression_1): Likewise. * pt.cc (tsubst_copy_and_build): Likewise. * semantics.cc (diagnose_failing_condition): New function. (find_failing_clause_r, find_failing_clause): Moved to constexpr.cc. (finish_static_assert): Use it. Add auto_diagnostic_group. gcc/testsuite/ * gcc.dg/attr-assume-1.c: New test. * gcc.dg/attr-assume-2.c: New test. * gcc.dg/attr-assume-3.c: New test. * g++.dg/cpp2a/feat-cxx2a.C: Add colon to C++20 features comment, add C++20 attributes comment and move C++20 new features after the attributes before them. * g++.dg/cpp23/feat-cxx2b.C: Likewise. Test __has_cpp_attribute(assume). * g++.dg/cpp23/attr-assume1.C: New test. * g++.dg/cpp23/attr-assume2.C: New test. * g++.dg/cpp23/attr-assume3.C: New test. * g++.dg/cpp23/attr-assume4.C: New test.
2022-09-29c++: reduce redundant TARGET_EXPRJason Merrill1-2/+2
An experiment led me to notice that in some cases we were ending up with TARGET_EXPR initialized by TARGET_EXPR, which isn't useful. The target_expr_needs_replace change won't make a difference in most cases, since cp_genericize_init will have already expanded VEC_INIT_EXPR by the time we consider it, but it is correct. gcc/cp/ChangeLog: * cp-gimplify.cc (cp_fold_r) [TARGET_EXPR]: Collapse TARGET_EXPR within TARGET_EXPR. * constexpr.cc (cxx_eval_outermost_constant_expr): Avoid adding redundant TARGET_EXPR. * cp-tree.h (target_expr_needs_replace): VEC_INIT_EXPR doesn't.
2022-09-29c++: check DECL_INITIAL for constexprJason Merrill1-2/+5
We were overlooking non-potentially-constant bits in variable initializer because we didn't walk into DECL_INITIAL. gcc/cp/ChangeLog: * constexpr.cc (potential_constant_expression_1): Look into DECL_INITIAL. Use location wrappers. gcc/testsuite/ChangeLog: * g++.dg/cpp1y/constexpr-local4.C: Expect error sooner. * g++.dg/cpp2a/consteval24.C: Likewise. * g++.dg/cpp2a/consteval7.C: Likewise. * g++.dg/cpp2a/inline-asm3.C: Likewise.
2022-09-16c++: 'mutable' member within constexpr [PR92505]Patrick Palka1-4/+7
This patch permits accessing 'mutable' members of local objects during constexpr evaluation, while continuing to reject it for global objects (as in the last line of cpp0x/constexpr-mutable1.C). To distinguish between the two cases, it looks like it suffices to just check CONSTRUCTOR_MUTABLE_POSION in cxx_eval_component_reference before deciding to reject a DECL_MUTABLE_P member access. PR c++/92505 gcc/cp/ChangeLog: * constexpr.cc (cxx_eval_component_reference): Check non_constant_p sooner. In C++14 or later, reject a DECL_MUTABLE_P member access only if CONSTRUCTOR_MUTABLE_POISION is also set. gcc/testsuite/ChangeLog: * g++.dg/cpp0x/constexpr-mutable3.C: New test. * g++.dg/cpp1y/constexpr-mutable1.C: New test.
2022-09-12c++: remove '_sfinae' suffix from functionsPatrick Palka1-14/+6
The functions abstract_virtuals_error cxx_constant_value get_target_expr instantiate_non_dependent_expr require_complete_type are each just a non-SFINAE-enabled wrapper for the corresponding SFINAE-enabled version that's suffixed by '_sfinae'. But this suffix is at best redundant since a 'complain' parameter already broadly conveys that a function is SFINAE-enabled, and having two such versions of a function is less concise than just using a default argument for 'complain' (and arguably no less mistake prone). So this patch squashes the two versions of each of the above functions by adding a default 'complain' argument to the SFINAE-enabled version whose '_sfinae' suffix we then remove. gcc/cp/ChangeLog: * call.cc (build_conditional_expr): Adjust calls to '_sfinae'-suffixed functions. (build_temp): Likewise. (convert_like_internal): Likewise. (convert_arg_to_ellipsis): Likewise. (build_over_call): Likewise. (build_cxx_call): Likewise. (build_new_method_call): Likewise. * constexpr.cc (cxx_eval_outermost_constant_expr): Likewise. (cxx_constant_value_sfinae): Rename to ... (cxx_constant_value): ... this. Document its default arguments. (fold_non_dependent_expr): Adjust function comment. * cp-tree.h (instantiate_non_dependent_expr_sfinae): Rename to ... (instantiate_non_dependent_expr): ... this. Give its 'complain' parameter a default argument. (get_target_expr_sfinae, get_target_expr): Likewise. (require_complete_type_sfinae, require_complete_type): Likewise. (abstract_virtuals_error_sfinae, abstract_virtuals_error): Likewise. (cxx_constant_value_sfinae, cxx_constant_value): Likewise. * cvt.cc (build_up_reference): Adjust calls to '_sfinae'-suffixed functions. (ocp_convert): Likewise. * decl.cc (build_explicit_specifier): Likewise. * except.cc (build_noexcept_spec): Likewise. * init.cc (build_new_1): Likewise. * pt.cc (expand_integer_pack): Likewise. (instantiate_non_dependent_expr_internal): Adjust function comment. (instantiate_non_dependent_expr): Rename to ... (instantiate_non_dependent_expr_sfinae): ... this. Document its default argument. (tsubst_init): Adjust calls to '_sfinae'-suffixed functions. (fold_targs_r): Likewise. * semantics.cc (finish_compound_literal): Likewise. (finish_decltype_type): Likewise. (cp_build_bit_cast): Likewise. * tree.cc (build_cplus_new): Likewise. (get_target_expr): Rename to ... (get_target_expr_sfinae): ... this. Document its default argument. * typeck.cc (require_complete_type): Rename to ... (require_complete_type_sfinae): ... this. Document its default argument. (cp_build_array_ref): Adjust calls to '_sfinae'-suffixed functions. (convert_arguments): Likewise. (cp_build_binary_op): Likewise. (build_static_cast_1): Likewise. (cp_build_modify_expr): Likewise. (convert_for_initialization): Likewise. * typeck2.cc (abstract_virtuals_error): Rename to ... (abstract_virtuals_error_sfinae): ... this. Document its default argument. (build_functional_cast_1): Adjust calls to '_sfinae'-suffixed functions.
2022-08-07c++: Add support for __real__/__imag__ modifications in constant expressions ↵Jakub Jelinek1-14/+80
[PR88174] We claim we support P0415R1 (constexpr complex), but e.g. #include <complex> constexpr bool foo () { std::complex<double> a (1.0, 2.0); a += 3.0; a.real (6.0); return a.real () == 6.0 && a.imag () == 2.0; } static_assert (foo ()); fails with test.C:12:20: error: non-constant condition for static assertion 12 | static_assert (foo ()); | ~~~~^~ test.C:12:20: in ‘constexpr’ expansion of ‘foo()’ test.C:8:10: in ‘constexpr’ expansion of ‘a.std::complex<double>::real(6.0e+0)’ test.C:12:20: error: modification of ‘__real__ a.std::complex<double>::_M_value’ is not a constant expression The problem is we don't handle REALPART_EXPR and IMAGPART_EXPR in cxx_eval_store_expression. The following patch attempts to support it (with a requirement that those are the outermost expressions, ARRAY_REF/COMPONENT_REF etc. are just not possible on the result of these, BIT_FIELD_REF would be theoretically possible if trying to extract some bits from one part of a complex int, but I don't see how it could appear in the FE trees. For these references, the code handles value being COMPLEX_CST, COMPLEX_EXPR or CONSTRUCTOR_NO_CLEARING empty CONSTRUCTOR (what we use to represent uninitialized values for C++20 and later) and the code starts by rewriting it to COMPLEX_EXPR, so that we can freely adjust the individual parts and later on possibly optimize it back to COMPLEX_CST if both halves are constant. 2022-08-07 Jakub Jelinek <jakub@redhat.com> PR c++/88174 * constexpr.cc (cxx_eval_store_expression): Handle REALPART_EXPR and IMAGPART_EXPR. Change ctors from releasing_vec to auto_vec<tree *>, adjust all uses. For !preeval, update ctors vector. * g++.dg/cpp1y/constexpr-complex1.C: New test.
2022-07-30c++: constexpr, empty base after non-empty [PR106369]Jason Merrill1-1/+7
Here the CONSTRUCTOR we were providing for D{} had an entry for the B base subobject at offset 0 following the entry for the C base, causing output_constructor_regular_field to ICE due to going backwards. It might be nice for that function to be more tolerant of empty fields, but it also seems reasonable for the front end to prune the useless entry. PR c++/106369 gcc/cp/ChangeLog: * constexpr.cc (reduced_constant_expression_p): Return false if a CONSTRUCTOR initializes an empty field. gcc/testsuite/ChangeLog: * g++.dg/cpp1z/constexpr-lambda27.C: New test.
2022-07-01c++: fix broken copy elision with nested TARGET_EXPRs [PR105550]Marek Polacek1-0/+7
In this problem, we are failing to properly perform copy elision with a conditional operator, so this: constexpr A a = true ? A{} : A{}; fails with: error: 'A{((const A*)(&<anonymous>))}' is not a constant expression The whole initializer is TARGET_EXPR <D.2395, 1 ? TARGET_EXPR <D.2393, {.p=(const struct A *) &<PLACEHOLDER_EXPR struct A>}> : TARGET_EXPR <D.2394, {.p=(const struct A *) &<PLACEHOLDER_EXPR struct A>}>> where the outermost TARGET_EXPR is elided, but not the nested ones. Then we end up replacing the PLACEHOLDER_EXPRs with the temporaries the TARGET_EXPRs represent, which is precisely what should *not* happen with copy elision. I've tried the approach of tweaking ctx->object, but I ran into gazillion problems with that. I thought that I would let cxx_eval_constant_expression /TARGET_EXPR create a new object only when ctx->object was null, then adjust setting of ctx->object in places like cxx_bind_parameters_in_call and cxx_eval_component_reference but that failed completely. Sometimes ctx->object has to be reset, sometimes it cannot be reset, 'this' needed special handling, etc. I gave up. Instead, this patch strips TARGET_EXPRs from the operands of ?: like we do in various other places in constexpr.c. PR c++/105550 gcc/cp/ChangeLog: * constexpr.cc (cxx_eval_conditional_expression): Strip TARGET_EXPRs. gcc/testsuite/ChangeLog: * g++.dg/cpp1y/nsdmi-aggr16.C: Remove FIXME. * g++.dg/cpp1y/nsdmi-aggr17.C: Remove FIXME. * g++.dg/cpp0x/constexpr-elision1.C: New test. * g++.dg/cpp1y/constexpr-elision1.C: New test.
2022-06-22ubsan: default to trap on unreachable at -O0 and -Og [PR104642]Jason Merrill1-12/+17
When not optimizing, we can't do anything useful with unreachability in terms of code performance, so we might as well improve debugging by turning __builtin_unreachable into a trap. I think it also makes sense to do this when we're explicitly optimizing for the debugging experience. In the PR richi suggested introducing an -funreachable-traps flag for this. This functionality is already implemented as -fsanitize=unreachable -fsanitize-trap=unreachable, and we want to share the implementation, but it does seem useful to have a separate flag that isn't affected by the various sanitization controls. -fsanitize=unreachable takes priority over -funreachable-traps if both are enabled. Jakub observed that this would slow down -O0 by default from running the sanopt pass, so this revision avoids the need for sanopt by rewriting calls introduced by the compiler immediately, and calls written by the user at fold time. Many of the calls introduced by the compiler are also rewritten immediately to ubsan calls when not trapping, which fixes ubsan-8b.C; previously the call to f() was optimized away before sanopt. But this early rewriting isn't practical for uses of __builtin_unreachable in devirtualization and such, so sanopt rewriting is still done for non-trapping sanitize. PR c++/104642 gcc/ChangeLog: * common.opt: Add -funreachable-traps. * doc/invoke.texi (-funreachable-traps): Document it. * opts.cc (finish_options): Enable at -O0 or -Og. * tree.cc (build_common_builtin_nodes): Add __builtin_trap. (builtin_decl_unreachable, build_builtin_unreachable): New. * tree.h: Declare them. * ubsan.cc (sanitize_unreachable_fn): Factor out. (ubsan_instrument_unreachable): Use gimple_build_builtin_unreachable. * ubsan.h (sanitize_unreachable_fn): Declare. * gimple.cc (gimple_build_builtin_unreachable): New. * gimple.h: Declare it. * builtins.cc (expand_builtin_unreachable): Add assert. (fold_builtin_0): Call build_builtin_unreachable. * sanopt.cc: Don't run for just SANITIZE_RETURN or SANITIZE_UNREACHABLE when trapping. * cgraphunit.cc (walk_polymorphic_call_targets): Use new unreachable functions. * gimple-fold.cc (gimple_fold_call) (gimple_get_virt_method_for_vtable) * ipa-fnsummary.cc (redirect_to_unreachable) * ipa-prop.cc (ipa_make_edge_direct_to_target) (ipa_impossible_devirt_target) * ipa.cc (walk_polymorphic_call_targets) * tree-cfg.cc (pass_warn_function_return::execute) (execute_fixup_cfg) * tree-ssa-loop-ivcanon.cc (remove_exits_and_undefined_stmts) (unloop_loops) * tree-ssa-sccvn.cc (eliminate_dom_walker::eliminate_stmt): Likewise. gcc/cp/ChangeLog: * constexpr.cc (cxx_eval_builtin_function_call): Handle unreachable/trap earlier. * cp-gimplify.cc (cp_maybe_instrument_return): Use build_builtin_unreachable. gcc/testsuite/ChangeLog: * g++.dg/ubsan/return-8a.C: New test. * g++.dg/ubsan/return-8b.C: New test. * g++.dg/ubsan/return-8d.C: New test. * g++.dg/ubsan/return-8e.C: New test.