Age | Commit message (Collapse) | Author | Files | Lines |
|
|
|
The element initializer was non-constant, so its CONSTRUCTOR element ended
up NULL, so unshare_constructor crashed trying to look at it. This patch
fixes this in two places: First, by returning when we see a non-constant
initializer; second, by not crashing on NULL.
gcc/cp/ChangeLog:
PR c++/98332
* constexpr.c (unshare_constructor): Check for NULL.
(cxx_eval_vec_init_1): Always exit early if non-constant.
gcc/testsuite/ChangeLog:
PR c++/98332
* g++.dg/cpp0x/constexpr-overflow3.C: New test.
|
|
-fsanitize=vptr initializes all vtable pointers to null so that it can
catch invalid calls; see cp_ubsan_maybe_initialize_vtbl_ptrs. That
means that evaluating a vtable reference can produce a null pointer
in this mode, so cxx_eval_dynamic_cast_fn should check that and give
and error.
gcc/cp/ChangeLog:
PR c++/98103
* constexpr.c (cxx_eval_dynamic_cast_fn): If the evaluating of vtable
yields a null pointer, give an error and return. Use objtype.
gcc/testsuite/ChangeLog:
PR c++/98103
* g++.dg/ubsan/vptr-18.C: New test.
|
|
I thought I had implemented P1186R3, but apparently I didn't read it closely
enough to understand the point of the paper, namely that for a defaulted
operator<=>, if a member type doesn't have a viable operator<=>, we will use
its operator< and operator== if the defaulted operator has an specific
comparison category as its return type; the compiler can't guess if it
should be strong_ordering or something else, but the user can make that
choice explicit.
The libstdc++ test change was necessary because of the change in
genericize_spaceship from op0 > op1 to op1 < op0; this should be equivalent,
but isn't because of PR88173.
gcc/cp/ChangeLog:
PR c++/96299
* cp-tree.h (build_new_op): Add overload that omits some parms.
(genericize_spaceship): Add location_t parm.
* constexpr.c (cxx_eval_binary_expression): Pass it.
* cp-gimplify.c (genericize_spaceship): Pass it.
* method.c (genericize_spaceship): Handle class-type arguments.
(build_comparison_op): Fall back to op</== when appropriate.
gcc/testsuite/ChangeLog:
PR c++/96299
* g++.dg/cpp2a/spaceship-synth-neg2.C: Move error.
* g++.dg/cpp2a/spaceship-p1186.C: New test.
libstdc++-v3/ChangeLog:
PR c++/96299
* testsuite/18_support/comparisons/algorithms/partial_order.cc:
One more line needs to use VERIFY instead of static_assert.
|
|
We currently incorrectly reject the first testcase, because
cxx_fold_indirect_ref_1 doesn't attempt to handle UNION_TYPEs.
As the second testcase shows, it isn't that easy, because I believe we need
to take into account the active member and prefer that active member over
other members, because if we pick a non-active one, we might reject valid
programs.
2020-12-05 Jakub Jelinek <jakub@redhat.com>
PR c++/98122
* constexpr.c (cxx_union_active_member): New function.
(cxx_fold_indirect_ref_1): Add ctx argument, pass it through to
recursive call. Handle UNION_TYPE.
(cxx_fold_indirect_ref): Add ctx argument, pass it to recursive calls
and cxx_fold_indirect_ref_1.
(cxx_eval_indirect_ref): Adjust cxx_fold_indirect_ref calls.
* g++.dg/cpp1y/constexpr-98122.C: New test.
* g++.dg/cpp2a/constexpr-98122.C: New test.
|
|
The following patch adds __builtin_bit_cast builtin, similarly to
clang or MSVC which implement std::bit_cast using such an builtin too.
It checks the various std::bit_cast requirements, when not constexpr
evaluated acts pretty much like VIEW_CONVERT_EXPR of the source argument
to the destination type and the hardest part is obviously the constexpr
evaluation.
I've left out PDP11 handling of those, couldn't figure out how exactly are
bitfields laid out there
2020-12-03 Jakub Jelinek <jakub@redhat.com>
PR libstdc++/93121
* fold-const.h (native_encode_initializer): Add mask argument
defaulted to nullptr.
(find_bitfield_repr_type): Declare.
(native_interpret_aggregate): Declare.
* fold-const.c (find_bitfield_repr_type): New function.
(native_encode_initializer): Add mask argument and support for
filling it. Handle also some bitfields without integral
DECL_BIT_FIELD_REPRESENTATIVE.
(native_interpret_aggregate): New function.
* gimple-fold.h (clear_type_padding_in_mask): Declare.
* gimple-fold.c (struct clear_padding_struct): Add clear_in_mask
member.
(clear_padding_flush): Handle buf->clear_in_mask.
(clear_padding_union): Copy clear_in_mask. Don't error if
buf->clear_in_mask is set.
(clear_padding_type): Don't error if buf->clear_in_mask is set.
(clear_type_padding_in_mask): New function.
(gimple_fold_builtin_clear_padding): Set buf.clear_in_mask to false.
* doc/extend.texi (__builtin_bit_cast): Document.
* c-common.h (enum rid): Add RID_BUILTIN_BIT_CAST.
* c-common.c (c_common_reswords): Add __builtin_bit_cast.
* cp-tree.h (cp_build_bit_cast): Declare.
* cp-tree.def (BIT_CAST_EXPR): New tree code.
* cp-objcp-common.c (names_builtin_p): Handle RID_BUILTIN_BIT_CAST.
(cp_common_init_ts): Handle BIT_CAST_EXPR.
* cxx-pretty-print.c (cxx_pretty_printer::postfix_expression):
Likewise.
* parser.c (cp_parser_postfix_expression): Handle
RID_BUILTIN_BIT_CAST.
* semantics.c (cp_build_bit_cast): New function.
* tree.c (cp_tree_equal): Handle BIT_CAST_EXPR.
(cp_walk_subtrees): Likewise.
* pt.c (tsubst_copy): Likewise.
* constexpr.c (check_bit_cast_type, cxx_eval_bit_cast): New functions.
(cxx_eval_constant_expression): Handle BIT_CAST_EXPR.
(potential_constant_expression_1): Likewise.
* cp-gimplify.c (cp_genericize_r): Likewise.
* g++.dg/cpp2a/bit-cast1.C: New test.
* g++.dg/cpp2a/bit-cast2.C: New test.
* g++.dg/cpp2a/bit-cast3.C: New test.
* g++.dg/cpp2a/bit-cast4.C: New test.
* g++.dg/cpp2a/bit-cast5.C: New test.
|
|
source_location::current() [PR80780, PR93093]
While std::source_location::current () is static consteval source_location
current() noexcept; in the standard, it also says with LWG3396:
"Any call to current that appears as a default member initializer
([class.mem]), or as a subexpression thereof, should correspond to the
location of the constructor definition or aggregate initialization that uses
the default member initializer. Any call to current that appears as a
default argument ([dcl.fct.default]), or as a subexpression thereof, should
correspond to the location of the invocation of the function that uses the
default argument ([expr.call])."
so it must work as compiler magic rather than normal immediate functions,
in particular we need to defer its evaluation when parsing default arguments
or nsdmis.
This patch actually defers evaluation of all the calls to
std::source_location::current () until genericization (or constant expression
evaluation when called from constant expression contexts).
I had to change constexpr.c too so that it temporarily adjusts
current_function_decl from the constexpr evaluation context, but we do the
same already from __builtin_FUNCTION ().
2020-12-03 Jakub Jelinek <jakub@redhat.com>
PR c++/80780
PR c++/93093
* cp-tree.h (source_location_current_p): Declare.
* tree.c (source_location_current_p): New function.
* call.c (immediate_invocation_p): New function.
(build_over_call): Use it to resolve LWG3396.
* constexpr.c (cxx_eval_builtin_function_call): Temporarily set
current_function_decl from ctx->call->fundef->decl if any.
* cp-gimplify.c (cp_genericize_r) <case CALL_EXPR>: Fold calls
to immediate function std::source_location::current ().
* g++.dg/cpp2a/srcloc15.C: New test.
* g++.dg/cpp2a/srcloc16.C: New test.
* g++.dg/cpp2a/srcloc17.C: New test.
* g++.dg/cpp2a/srcloc18.C: New test.
|
|
In this test, we have
static inline const int c = b;
in a class template, and we call store_init_value as usual. There, the
value is
IMPLICIT_CONV_EXPR<const float>(b)
which is is_nondependent_static_init_expression but isn't
is_nondependent_constant_expression (they only differ in STRICT).
We call fold_non_dependent_expr, but that just returns the expression
because it only instantiates is_nondependent_constant_expression
expressions. Since we're not checking the initializer of a constexpr
variable, we go on to call maybe_constant_init, whereupon we crash
because it tries to evaluate all is_nondependent_static_init_expression
expressions, which our value is, but it still contains a template code.
I think the fix is to call fold_non_dependent_init instead of
maybe_constant_init, and only call fold_non_dependent_expr on the
"this is a constexpr variable" path so as to avoid instantiating twice
in a row. Outside a template this should also avoid evaluating the
value twice.
gcc/cp/ChangeLog:
PR c++/97975
* constexpr.c (fold_non_dependent_init): Add a tree parameter.
Use it.
* cp-tree.h (fold_non_dependent_init): Add a tree parameter with
a default value.
* typeck2.c (store_init_value): Call fold_non_dependent_expr
only when checking the initializer for constexpr variables.
Call fold_non_dependent_init instead of maybe_constant_init.
gcc/testsuite/ChangeLog:
PR c++/97975
* g++.dg/cpp1z/inline-var8.C: New test.
|
|
The PR38359 change made the -1 >> x to -1 optimization less useful by
requiring that the x must be non-negative.
Shifts by negative amount are UB, but we for historic reasons had in some
(but not all) places some hack to treat shifts by negative value as the
other direction shifts by the negated amount.
The following patch just removes that special handling, instead we punt on
optimizing those (and ideally path isolation should catch that up and turn
those into __builtin_unreachable, perhaps with __builtin_warning next to
it). Folding the shifts in some places as if they were rotates and in other
as if they were saturating just leads to inconsistencies.
For C++ constexpr diagnostics and -fpermissive, I've added code to pretend
fold-const.c has not changed, without -fpermissive it will be an error
anyway and I think it is better not to change all the diagnostics.
During x86_64-linux and i686-linux bootstrap/regtest, my statistics
gathering patch noted 185 unique -m32/-m64 x TU x function_name x shift_kind
x fold-const/tree-ssa-ccp cases. I have investigated the
64 ../../gcc/config/i386/i386.c x86_output_aligned_bss LSHIFT_EXPR wide_int_bitop
64 ../../gcc/config/i386/i386-expand.c emit_memmov LSHIFT_EXPR wide_int_bitop
64 ../../gcc/config/i386/i386-expand.c ix86_expand_carry_flag_compare LSHIFT_EXPR wide_int_bitop
64 ../../gcc/expmed.c expand_divmod LSHIFT_EXPR wide_int_bitop
64 ../../gcc/lra-lives.c process_bb_lives LSHIFT_EXPR wide_int_bitop
64 ../../gcc/rtlanal.c nonzero_bits1 LSHIFT_EXPR wide_int_bitop
64 ../../gcc/varasm.c optimize_constant_pool.isra LSHIFT_EXPR wide_int_bitop
cases and all of them are either during jump threading (dom) or during PRE.
For jump threading, the most common case is 1 << floor_log2 (whatever) where
floor_log2 is return HOST_BITS_PER_WIDE_INT - 1 - clz_hwi (x);
and clz_hwi is if (x == 0) return HOST_BITS_PER_WIDE_INT; return __builtin_clz* (x);
and so has range [-1, 63] and a comparison against == 0 which makes the
threader think it might be nice to jump thread the case leading to 1 << -1.
I think it is better to keep the 1 << -1 s in the IL for this and let path
isolation turn that into __builtin_unreachable () if the user wishes so.
2020-11-24 Jakub Jelinek <jakub@redhat.com>
PR tree-optimization/96929
* fold-const.c (wide_int_binop) <case LSHIFT_EXPR, case RSHIFT_EXPR>:
Return false on negative second argument rather than trying to handle
it as shift in the other direction.
* tree-ssa-ccp.c (bit_value_binop) <case LSHIFT_EXPR,
case RSHIFT_EXPR>: Punt on negative shift count rather than trying
to handle it as shift in the other direction.
* match.pd (-1 >> x to -1): Remove tree_expr_nonnegative_p check.
* constexpr.c (cxx_eval_binary_expression): For shifts by constant
with MSB set, emulate older wide_int_binop behavior to preserve
diagnostics and -fpermissive behavior.
* gcc.dg/tree-ssa/pr96929.c: New test.
|
|
[dcl.constexpr]/3 says that the function-body of a constexpr function
shall not contain an identifier label, but we aren't enforcing that.
This patch implements that. Of course, we can't reject artificial
labels.
gcc/cp/ChangeLog:
PR c++/97846
* constexpr.c (potential_constant_expression_1): Reject
LABEL_EXPRs that use non-artifical LABEL_DECLs.
gcc/testsuite/ChangeLog:
PR c++/97846
* g++.dg/cpp1y/constexpr-label.C: New test.
|
|
When I implemented the code to detect modifying const objects in
constexpr contexts, we couldn't have constexpr destructors, so I didn't
consider them. But now we can and that caused a bogus error in this
testcase: [class.dtor]p5 says that "const and volatile semantics are not
applied on an object under destruction. They stop being in effect when
the destructor for the most derived object starts." so we have to clear
the TREE_READONLY flag we set on the object after the constructors have
been called to mark it as no-longer-under-construction. In the ~Foo
call it's now an object under destruction, so don't report those errors.
gcc/cp/ChangeLog:
PR c++/97427
* constexpr.c (cxx_set_object_constness): New function.
(cxx_eval_call_expression): Set new_obj for destructors too.
Call cxx_set_object_constness to set/unset TREE_READONLY of
the object under construction/destruction.
gcc/testsuite/ChangeLog:
PR c++/97427
* g++.dg/cpp2a/constexpr-dtor10.C: New test.
|
|
This patch exposes the constexpr hash table so that the modules
machinery can save and load constexpr bodies. While there I noticed
that we could do a little constification of the hasher and comparator
functions. Also combine the saving machinery to a single function
returning void -- nothing ever looked at its return value.
gcc/cp/
* cp-tree.h (struct constexpr_fundef): Moved from constexpr.c.
(maybe_save_constexpr_fundef): Declare.
(register_constexpr_fundef): Take constexpr_fundef object, return
void.
* decl.c (mabe_save_function_definition): Delete, functionality
moved to maybe_save_constexpr_fundef.
(emit_coro_helper, finish_function): Adjust.
* constexpr.c (struct constexpr_fundef): Moved to cp-tree.h.
(constexpr_fundef_hasher::equal): Constify.
(constexpr_fundef_hasher::hash): Constify.
(retrieve_constexpr_fundef): Make non-static.
(maybe_save_constexpr_fundef): Break out checking and duplication
from ...
(register_constexpr_fundef): ... here. Just register the constexpr.
|
|
As the testcase shows, CLEANUP_POINT_EXPR (and I think TRY_FINALLY_EXPR too)
suffer from the same problem that I was trying to fix in
r10-3597-g1006c9d4395a939820df76f37c7b085a4a1a003f
for CLEANUP_STMT, namely that if in the middle of the body expression of
those stmts is e.g. return stmt, goto, break or continue (something that
changes *jump_target and makes it start skipping stmts), we then skip the
cleanups too, which is not appropriate - the cleanups were either queued up
during the non-skipping execution of the body (for CLEANUP_POINT_EXPR), or
for TRY_FINALLY_EXPR are relevant already after entering the body block.
> Would it make sense to always use a NULL jump_target when evaluating
> cleanups?
I was afraid of that, especially for TRY_FINALLY_EXPR, but it seems that
during constexpr evaluation the cleanups will most often be just very simple
destructor calls (or calls to cleanup attribute functions).
Furthermore, for neither of these 3 tree codes we'll reach that code if
jump_target && *jump_target initially (there is a return NULL_TREE much
earlier for those except for trees that could embed labels etc. in it and
clearly these 3 don't count in that).
2020-11-12 Jakub Jelinek <jakub@redhat.com>
PR c++/97790
* constexpr.c (cxx_eval_constant_expression) <case CLEANUP_POINT_EXPR,
case TRY_FINALLY_EXPR, case CLEANUP_STMT>: Don't pass jump_target to
cxx_eval_constant_expression when evaluating the cleanups.
* g++.dg/cpp2a/constexpr-dtor9.C: New test.
|
|
We cannot, as things stand, handle Objective-C tree codes in
the switch and deal with this by calling out to a function that
has a dummy version when Objective-C is not enabled.
Because of the way the logic works (with a fall through to a
'sorry' in case of unhandled expressions), the function reports
cases that are known to be unsuitable for constant exprs. The
dummy function always reports 'false' and thus will fall through
to the 'sorry'.
gcc/c-family/ChangeLog:
* c-objc.h (objc_non_constant_expr_p): New.
* stub-objc.c (objc_non_constant_expr_p): New.
gcc/cp/ChangeLog:
* constexpr.c (potential_constant_expression_1): Handle
expressions known to be non-constant for Objective-C.
gcc/objc/ChangeLog:
* objc-act.c (objc_non_constant_expr_p): New.
|
|
We may not call value_dependent_expression_p on expressions that are
not potential constant expressions, otherwise value_d could crash,
as I saw recently (in C++98). So beef up the checking in i_d_e_p.
This revealed a curious issue: when we have __PRETTY_FUNCTION__ in
a template function, we set its DECL_VALUE_EXPR to error_mark_node
(cp_make_fname_decl), so potential_c_e returns false when it gets it,
but value_dependent_expression_p handles it specially and says true.
This broke lambda-generic-pretty1.C. So take care of that.
And then also tweak uses_template_parms.
gcc/cp/ChangeLog:
* constexpr.c (potential_constant_expression_1): Treat
__PRETTY_FUNCTION__ inside a template function as
potentially-constant.
* pt.c (uses_template_parms): Call
instantiation_dependent_expression_p instead of
value_dependent_expression_p.
(instantiation_dependent_expression_p): Check
potential_constant_expression before calling
value_dependent_expression_p.
|
|
The adoption of P2104 ("Disallow changing concept values") means we can
memoize the result of satisfaction indefinitely and no longer have to
clear the satisfaction caches on various events that would affect
satisfaction. To that end, this patch removes the invalidation routine
clear_satisfaction_cache and adjusts its callers appropriately.
This provides a large reduction in compile time and memory use in some
cases. For example, on the libstdc++ test std/ranges/adaptor/join.cc,
compile time and memory usage drops nearly 75%, from 7.5s/770MB to
2s/230MB, with a --enable-checking=release compiler.
gcc/cp/ChangeLog:
* class.c (finish_struct_1): Don't call clear_satisfaction_cache.
* constexpr.c (clear_cv_and_fold_caches): Likewise. Remove bool
parameter.
* constraint.cc (clear_satisfaction_cache): Remove definition.
* cp-tree.h (clear_satisfaction_cache): Remove declaration.
(clear_cv_and_fold_caches): Remove bool parameter.
* typeck2.c (store_init_value): Remove argument to
clear_cv_and_fold_caches.
gcc/testsuite/ChangeLog:
* g++.dg/cpp2a/concepts-complete1.C: Delete test that became
ill-formed after P2104.
|
|
In this testcase, the primary evaluation successfully produces 'true', and
then running one of the cleanups hits a double delete, making the whole
thing not a valid constant expression. So we were returning 'true' wrapped
in a NOP_EXPR to indicate its non-constancy, but evaluating that again is a
perfectly acceptable constant expression, so we weren't getting the verbose
diagnostic we were looking for.
So if non_constant_p gets set other than for overflow, go back to the
original expression.
With this change, we should never hit the manifestly_const_eval test, and
the is-constant-evaluated1.C test passes without it.
gcc/cp/ChangeLog:
PR c++/97388
* constexpr.c (cxx_eval_outermost_constant_expr): Revert to
original expression if evaluation sets non_constant_p.
gcc/testsuite/ChangeLog:
PR c++/97388
* g++.dg/cpp2a/constexpr-dtor8.C: New test.
|
|
For arguments passed by invisible reference, in the IL until genericization
we have the source types on the callee side and while on the caller side
we already pass references to the actual argument slot in the caller, we
undo that in cxx_bind_parameters_in_call's
if (TREE_ADDRESSABLE (type))
/* Undo convert_for_arg_passing work here. */
x = convert_from_reference (x);
This works fine most of the time, except when the type also has constexpr
destructor; in that case the destructor is invoked in the caller and thus
the unsharing we do to make sure that the callee doesn't modify caller's
values is in that case undesirable, it prevents the changes done in the
callee propagating to the caller which should see them for the constexpr
dtor evaluation.
The following patch fixes that. While it could be perhaps done for all
TREE_ADDRESSABLE types, I don't see the need to change the behavior
if there is no constexpr non-trivial dtor.
Jason: And we need to avoid memoizing the call, because a later equivalent
call also needs to modify its argument. And we don't need to unshare
constructors when we aren't memoizing the call, because we already unshared
them when evaluating the TARGET_EXPR representing the copy-initialization of
the argument.
2020-10-20 Jakub Jelinek <jakub@redhat.com>
Jason Merrill <jason@redhat.com>
PR c++/97388
* constexpr.c (cxx_bind_parameters_in_call): Set non_constant_args
if the parameter type has a non-trivial destructor.
(cxx_eval_call_expression): Only unshare arguments if we're
memoizing this evaluation.
* g++.dg/cpp2a/constexpr-dtor5.C: New test.
* g++.dg/cpp2a/constexpr-dtor6.C: New test.
* g++.dg/cpp2a/constexpr-dtor7.C: New test.
|
|
This patch diagnoses delete [] new int; and delete new int[1]; in constexpr
contexts by remembering
IDENTIFIER_OVL_OP_FLAGS (DECL_NAME (fun)) & OVL_OP_FLAG_VEC
from the operator new and checking it at operator delete time.
2020-10-29 Jakub Jelinek <jakub@redhat.com>
PR c++/95808
* cp-tree.h (enum cp_tree_index): Add CPTI_HEAP_VEC_UNINIT_IDENTIFIER
and CPTI_HEAP_VEC_IDENTIFIER.
(heap_vec_uninit_identifier, heap_vec_identifier): Define.
* decl.c (initialize_predefined_identifiers): Initialize those
identifiers.
* constexpr.c (cxx_eval_call_expression): Reject array allocations
deallocated with non-array deallocation or non-array allocations
deallocated with array deallocation.
(non_const_var_error): Handle heap_vec_uninit_identifier and
heap_vec_identifier too.
(cxx_eval_constant_expression): Handle also heap_vec_uninit_identifier
and in that case during initialization replace it with
heap_vec_identifier.
(find_heap_var_refs): Handle heap_vec_uninit_identifier and
heap_vec_identifier too.
* g++.dg/cpp2a/constexpr-new15.C: New test.
|
|
The code added in r10-6437 caused us to create a CONSTRUCTOR when we're
{}-initializing an aggregate. Then we pass this new CONSTRUCTOR down to
cxx_eval_constant_expression which, if the CONSTRUCTOR isn't TREE_CONSTANT
or reduced_constant_expression_p, calls cxx_eval_bare_aggregate. In
this case the CONSTRUCTOR wasn't reduced_constant_expression_p because
for r_c_e_p a CONST_DECL isn't good enough so it returns false. So we
go to cxx_eval_bare_aggregate where we crash, because ctx->ctor wasn't
set up properly. So my fix is to do so. Since we're value-initializing,
I'm not setting CONSTRUCTOR_NO_CLEARING. To avoid keeping a garbage
constructor around, I call free_constructor in case the evaluation did
not use it.
gcc/cp/ChangeLog:
PR c++/96241
* constexpr.c (cxx_eval_array_reference): Set up ctx->ctor if we
are initializing an aggregate. Call free_constructor on the new
CONSTRUCTOR if it isn't returned from cxx_eval_constant_expression.
gcc/testsuite/ChangeLog:
PR c++/96241
* g++.dg/cpp0x/constexpr-96241.C: New test.
* g++.dg/cpp1y/constexpr-96241.C: New test.
|
|
In the testcase below, we're ICEing during constexpr evaluation of the
CONSTRUCTOR {.data={{}, [1 ... 7]={}}} of type 'vector'. The interesting
thing about this CONSTRUCTOR is that it has a RANGE_EXPR index for an
element initializer which doesn't satisfy reduced_constant_expression_p
(because the field 't' is uninitialized).
This is a problem because init_subob_ctx currently punts on setting up a
sub-aggregate initialization context when given a RANGE_EXPR index, so
we later trip over the asserts in verify_ctor_sanity when recursing into
cxx_eval_bare_aggregate on this element initializer.
Fix this by making init_subob_ctx set up an appropriate initialization
context when supplied a RANGE_EXPR index.
gcc/cp/ChangeLog:
PR c++/97328
* constexpr.c (init_subob_ctx): Don't punt on RANGE_EXPR
indexes, instead build a sub-aggregate initialization context
with no subobject.
gcc/testsuite/ChangeLog:
PR c++/97328
* g++.dg/cpp2a/constexpr-init19.C: New test.
* g++.dg/cpp2a/constexpr-init20.C: New test.
|
|
In the testcase below, folding of the initializer for 'ret' inside the
instantiated f<lambda>::lambda ends up yielding an initializer for which
potential_constant_expression returns false. This causes finish_function
to mark the lambda as non-constexpr, which ultimately causes us to reject
'f(g)' as a call to a non-constexpr function.
The initializer for 'ret' inside f<lambda>::lambda, prior to folding, is
the CALL_EXPR
<lambda(S)>::operator() (&cb, ({}, <<< Unknown tree: empty_class_expr >>>;))
where the second argument is a COMPOUND_EXPR whose second operand is an
EMPTY_CLASS_EXPR that was formed by build_class_a. cp_fully_fold_init
is able to only partially fold this initializer: it gets rid of the
side-effectless COMPOUND_EXPR to obtain
<lambda(S)>::operator() (&cb, <<< Unknown tree: empty_class_expr >>>)
as the final initializer for 'ret'. This initializer no longer satifies
potential_constant_expression due to the bare EMPTY_CLASS_EXPR which is
not wrapped in a COMPOUND_EXPR.
(cp_fully_fold_init first tries maybe_constant_value on the original
CALL_EXPR, but constexpr evaluation punts upon seeing
__builtin_is_constant_evaluated, since manifestly_const_eval is false.)
To fix this, it seems we could either make cp_fold preserve the
COMPOUND_EXPR trees produced by build_call_a, or we could improve
the constexpr machinery to treat EMPTY_CLASS_EXPR trees as first-class
citizens. Assuming it's safe to continue folding away these
COMPOUND_EXPRs, the second approach seems cleaner, so this patch
implements the second approach.
gcc/cp/ChangeLog:
PR c++/96575
* constexpr.c (cxx_eval_constant_expression)
<case EMPTY_CLASS_EXPR>: Lower it to a CONSTRUCTOR.
(potential_constant_expression_1) <case COMPOUND_EXPR>: Remove
now-redundant handling of COMPOUND_EXPR with EMPTY_CLASS_EXPR
second operand.
<case EMPTY_CLASS_EXPR>: Return true instead of false.
gcc/testsuite/ChangeLog:
PR c++/96575
* g++.dg/cpp1z/constexpr-96575.C: New test.
|
|
[PR97195]
As mentioned in the PR, we only support due to a bug in constant expressions
std::construct_at on non-automatic variables, because we VERIFY_CONSTANT the
second argument of placement new, which fails verification if it is an
address of an automatic variable.
The following patch fixes it by not performing that verification, the
placement new evaluation later on will verify it after it is dereferenced.
2020-10-01 Jakub Jelinek <jakub@redhat.com>
PR c++/97195
* constexpr.c (cxx_eval_call_expression): Don't VERIFY_CONSTANT the
second argument.
* g++.dg/cpp2a/constexpr-new14.C: New test.
|
|
expression evaluation [PR97145]
These two builtin calls are added already during parsing before pointer
subtractions or comparisons, normally they perform runtime verification
of whether the pointers point to the same object or different objects,
but during constant expressione valuation we don't really need those
builtins for anything.
2020-09-22 Jakub Jelinek <jakub@redhat.com>
PR c++/97145
* constexpr.c (cxx_eval_builtin_function_call): Return void_node for
calls to __sanitize_ptr_{sub,cmp} builtins.
* g++.dg/asan/pr97145.C: New test.
|
|
The recent libstdc++ changes caused lots of libstdc++-v3 tests FAILs
on i686-linux, all of them in the same spot during constexpr evaluation
of a recursive _S_gcd call.
The problem is yet another hash_map that used the default hasing of
tree keys through pointer hashing which is preserved across PCH write/read.
During PCH handling, the addresses of GC objects are changed, which means
that the hash values of the keys in such hash tables change without those
hash tables being rehashed. Which in the fundef_copies_table case usually
means we just don't find a copy of a FUNCTION_DECL body for recursive uses
and start from scratch. But when the hash table keeps growing, the "dead"
elements in the hash table can sometimes reappear and break things.
In particular what I saw under the debugger is when the fundef_copies_table
hash map has been used on the outer _S_gcd call, it didn't find an entry for
it, so returned a slot with *slot == NULL, which is treated as that the
function itself is used directly (i.e. no recursion), but that addition of
a hash table slot caused the recursive _S_gcd call to actually find
something in the hash table, unfortunately not the new *slot == NULL spot,
but a different one from the pre-PCH streaming which contained the returned
toplevel (non-recursive) call entry for it, which means that for the
recursive _S_gcd call we actually used the same trees as for the outer ones
rather than a copy of those, which breaks constexpr evaluation.
2020-09-03 Jakub Jelinek <jakub@redhat.com>
PR c++/96901
* tree.h (struct decl_tree_traits): New type.
(decl_tree_map): New typedef.
* constexpr.c (fundef_copies_table): Change type from
hash_map<tree, tree> * to decl_tree_map *.
|
|
As discussed in the PR, fold-const.c punts on floating point constant
evaluation if the result is inexact and -frounding-math is turned on.
/* Don't constant fold this floating point operation if the
result may dependent upon the run-time rounding mode and
flag_rounding_math is set, or if GCC's software emulation
is unable to accurately represent the result. */
if ((flag_rounding_math
|| (MODE_COMPOSITE_P (mode) && !flag_unsafe_math_optimizations))
&& (inexact || !real_identical (&result, &value)))
return NULL_TREE;
Jonathan said that we should be evaluating them anyway, e.g. conceptually
as if they are done with the default rounding mode before user had a chance
to change that, and e.g. in C in initializers it is also ignored.
In fact, fold-const.c for C initializers turns off various other options:
/* Perform constant folding and related simplification of initializer
expression EXPR. These behave identically to "fold_buildN" but ignore
potential run-time traps and exceptions that fold must preserve. */
int saved_signaling_nans = flag_signaling_nans;\
int saved_trapping_math = flag_trapping_math;\
int saved_rounding_math = flag_rounding_math;\
int saved_trapv = flag_trapv;\
int saved_folding_initializer = folding_initializer;\
flag_signaling_nans = 0;\
flag_trapping_math = 0;\
flag_rounding_math = 0;\
flag_trapv = 0;\
folding_initializer = 1;
flag_signaling_nans = saved_signaling_nans;\
flag_trapping_math = saved_trapping_math;\
flag_rounding_math = saved_rounding_math;\
flag_trapv = saved_trapv;\
folding_initializer = saved_folding_initializer;
So, shall cxx_eval_outermost_constant_expr instead turn off all those
options (then warning_sentinel wouldn't be the right thing to use, but given
the 8 or how many return stmts in cxx_eval_outermost_constant_expr, we'd
need a RAII class for this. Not sure about the folding_initializer, that
one is affecting complex multiplication and division constant evaluation
somehow.
2020-09-03 Jakub Jelinek <jakub@redhat.com>
PR c++/96862
* constexpr.c (cxx_eval_outermost_constant_expr): Temporarily disable
flag_rounding_math during manifestly constant evaluation.
* g++.dg/cpp1z/constexpr-96862.C: New test.
|
|
The following valid testcase is rejected, because cxx_eval_binary_expression
is called on the SPACESHIP_EXPR with lval = true, as the address of the
spaceship needs to be passed to a method call.
After recursing on the operands and calling genericize_spaceship which turns
it into a TARGET_EXPR with initialization, we call cxx_eval_constant_expression
on it which succeeds, but then we fall through into code that will
VERIFY_CONSTANT (r) which FAILs because it is an address of a variable. Rather
than avoiding that for lval = true and SPACESHIP_EXPR, the patch just tail
calls cxx_eval_constant_expression - I believe that call should perform all
the needed verifications.
2020-08-10 Jakub Jelinek <jakub@redhat.com>
PR c++/96497
* constexpr.c (cxx_eval_binary_expression): For SPACESHIP_EXPR, tail
call cxx_eval_constant_expression after genericize_spaceship to avoid
undesirable further VERIFY_CONSTANT.
* g++.dg/cpp2a/spaceship-constexpr3.C: New test.
|
|
In the first testcase below, expand_aggr_init_1 sets up t's default
constructor such that the ctor first zero-initializes the entire base b,
followed by calling b's default constructor, the latter of which just
default-initializes the array member b::m via a VEC_INIT_EXPR.
So upon constexpr evaluation of this latter VEC_INIT_EXPR, ctx->ctor is
nonempty due to the prior zero-initialization, and we proceed in
cxx_eval_vec_init to append new constructor_elts to the end of ctx->ctor
without first checking if a matching constructor_elt already exists.
This leads to ctx->ctor having two matching constructor_elts for each
index.
This patch fixes this issue by truncating a zero-initialized array
CONSTRUCTOR in cxx_eval_vec_init_1 before we begin appending array
elements to it. We propagate its zeroed out state during evaluation by
clearing CONSTRUCTOR_NO_CLEARING on each new appended aggregate element.
gcc/cp/ChangeLog:
PR c++/96282
* constexpr.c (cxx_eval_vec_init_1): Truncate ctx->ctor and
then clear CONSTRUCTOR_NO_CLEARING on each appended element
initializer if we're initializing a previously zero-initialized
array object.
gcc/testsuite/ChangeLog:
PR c++/96282
* g++.dg/cpp0x/constexpr-array26.C: New test.
* g++.dg/cpp0x/constexpr-array27.C: New test.
* g++.dg/cpp2a/constexpr-init18.C: New test.
Co-authored-by: Jason Merrill <jason@redhat.com>
|
|
In the testcase from the PR we're seeing excessive memory use (> 5GB)
during constexpr evaluation, almost all of which is due to the call to
decl_constant_value in the VAR_DECL/CONST_DECL branch of
cxx_eval_constant_expression. We reach here every time we evaluate an
ARRAY_REF of a constexpr VAR_DECL, and from there decl_constant_value
makes an unshared copy of the VAR_DECL's initializer. But unsharing
here is unnecessary because callers of cxx_eval_constant_expression
already unshare its result when necessary.
To fix this excessive unsharing, this patch adds a new defaulted
parameter unshare_p to decl_really_constant_value and
decl_constant_value so that callers can control whether to unshare.
As a simplification, we can also move the call to unshare_expr in
constant_value_1 outside of the loop, since doing unshare_expr on a
DECL_P is a no-op.
Now that we no longer unshare the result of decl_constant_value and
decl_really_constant_value from cxx_eval_constant_expression, memory use
during constexpr evaluation for the testcase from the PR falls from ~5GB
to 15MB according to -ftime-report.
gcc/cp/ChangeLog:
PR c++/96197
* constexpr.c (cxx_eval_constant_expression) <case CONST_DECL>:
Pass false to decl_constant_value and decl_really_constant_value
so that they don't unshare their result.
* cp-tree.h (decl_constant_value): New declaration with an added
bool parameter.
(decl_really_constant_value): Add bool parameter defaulting to
true to existing declaration.
* init.c (constant_value_1): Add bool parameter which controls
whether to unshare the initializer before returning. Call
unshare_expr at most once.
(scalar_constant_value): Pass true to constant_value_1's new
bool parameter.
(decl_really_constant_value): Add bool parameter and forward it
to constant_value_1.
(decl_constant_value): Likewise, but instead define a new
overload with an added bool parameter.
gcc/testsuite/ChangeLog:
PR c++/96197
* g++.dg/cpp1y/constexpr-array8.C: New test.
|
|
I was mistaken to assume that a dependent type is necessarily
incomplete, and indeed there are multiple places in the frontend where
we check a type for both dependency and completeness. So this patch
partially reverts the fix for PR95497, restoring the dependent_type_p
check that guarded the call to is_really_empty_class below.
gcc/cp/ChangeLog:
PR c++/96132
* constexpr.c (potential_constant_expression_1) <case PARM_DECL>:
Restore dependent_type_p check that guarded the call to
is_really_empty_class.
gcc/testsuite/ChangeLog:
PR c++/96132
* g++.dg/template/incomplete12.C: New test.
|
|
We are ICEing in the testcase below because we pass the
yet-uninstantiated class type A<int> of the PARM_DECL b to
is_really_empty_class from is_rvalue_constant_expression when parsing
the requirement t += b.
This patch fixes the ICE by guarding the problematic call to
is_really_empty_class with a COMPLETE_TYPE_P check, which should also
subsume the existing dependent_type_p check.
gcc/cp/ChangeLog:
PR c++/95497
* constexpr.c (potential_constant_expression_1) <case PARM_DECL>:
When processing_template_decl, check COMPLETE_TYPE_P before
calling is_really_empty_class. Don't check dependent_type_p.
gcc/testsuite/ChangeLog:
PR c++/95497
* g++.dg/cpp2a/concepts-pr95497.C: New test.
|
|
Jakub's partial implementation of consteval virtual had trouble with the
current ABI requirement that we omit the vtable slot for a consteval virtual
function; it's difficult to use the normal code for constant evaluation and
also magically make the slots disappear if the vtables get written out. I
notice that Clang trunk also doesn't implement that requirement, and it
seems unnecessary to me; I expect consteval virtual functions to be
extremely rare, so it should be fine to just give them a vtable slot as
normal but put zero in it if the vtable gets emitted. I've commented as
much to the ABI committee.
One of Jakub's testcases points out that we weren't handling thunks in
our constexpr virtual handling; that is fixed here as well.
Incidentally, being able to use C++11 range-for definitely simplified
clear_consteval_vfns.
gcc/c-family/ChangeLog:
* c-cppbuiltin.c (c_cpp_builtins): Define __cpp_consteval.
gcc/cp/ChangeLog:
* decl.c (grokfndecl): Allow consteval virtual.
* search.c (check_final_overrider): Check consteval mismatch.
* constexpr.c (cxx_eval_thunk_call): New.
(cxx_eval_call_expression): Call it.
* cvt.c (cp_get_fndecl_from_callee): Handle FDESC_EXPR.
* decl2.c (mark_vtable_entries): Track vtables with consteval.
(maybe_emit_vtables): Pass consteval_vtables through.
(clear_consteval_vfns): Replace consteval with nullptr.
(c_parse_final_cleanups): Call it.
gcc/testsuite/ChangeLog:
* g++.dg/cpp2a/consteval-virtual1.C: New test.
* g++.dg/cpp2a/consteval-virtual2.C: New test.
* g++.dg/cpp2a/consteval-virtual3.C: New test.
* g++.dg/cpp2a/consteval-virtual4.C: New test.
* g++.dg/cpp2a/consteval-virtual5.C: New test.
Co-authored-by: Jakub Jelinek <jakub@redhat.com>
|
|
Since r10-7096 convert_like, when called in a template, creates an
IMPLICIT_CONV_EXPR when we're converting to/from array type.
In this test, we have e[f], and we're converting f (of type class A) to
int, so convert_like in build_new_op_1 created the IMPLICIT_CONV_EXPR
that got into cp_build_array_ref which calls maybe_constant_value. My
patch above failed to adjust this spot to call fold_non_dependent_expr
instead, which can handle codes like I_C_E in a template. Fixed by
using a new function maybe_fold_non_dependent_expr, which, if the expr
can't be evaluated to a constant, returns the original expression.
gcc/cp/ChangeLog:
PR c++/95508
* constexpr.c (maybe_fold_non_dependent_expr): New.
* cp-tree.h (maybe_fold_non_dependent_expr): Declare.
* typeck.c (cp_build_array_ref): Call maybe_fold_non_dependent_expr
instead of maybe_constant_value.
gcc/testsuite/ChangeLog:
PR c++/95508
* g++.dg/template/conv16.C: New test.
|
|
The code in constexpr for looking up the actual type of the object and then
getting the virtual function from there broke for both of these tests: for
16, it assumed incorrectly that the DECL_VINDEX would apply to the most
derived type's vtable; for 17, it failed to consider that during
construction the base subobject is treated as being of the base type.
Fixed by just doing constant evaluation of the expression that looks up the
function in the vtable. This means that a virtual call will involve loading
the vptr, so we will reject some calls through non-constexpr variables that
we previously accepted, but this seems appropriate to me. None of our
testcases were affected.
gcc/cp/ChangeLog:
PR c++/93310
* constexpr.c (cxx_eval_constant_expression) [OBJ_TYPE_REF]:
Evaluate OBJ_TYPE_REF_EXPR.
gcc/testsuite/ChangeLog:
PR c++/93310
* g++.dg/cpp2a/constexpr-virtual16.C: New test.
* g++.dg/cpp2a/constexpr-virtual17.C: New test.
* g++.dg/cpp2a/constexpr-new12.C: Adjust diagnostic.
|
|
cxx_eval_outermost_constant_expr had a check for reinterpret_casts from
pointers (well, it checked from ADDR_EXPRs) to integral type, but that
only caught such cases at the toplevel of expressions.
As the comment said, it should be done even inside of the expressions,
but at the point of the writing e.g. pointer differences used to be a
problem. We now have POINTER_DIFF_EXPR, so this is no longer an issue.
Had to do it just for CONVERT_EXPR, because the FE emits NOP_EXPR casts
from pointers to integrals in various spots, e.g. for the PMR & 1 tests,
though on NOP_EXPR we have the REINTERPRET_CAST_P bit that we do check,
while on CONVERT_EXPR we don't.
2020-06-04 Jakub Jelinek <jakub@redhat.com>
PR c++/82304
PR c++/95307
* constexpr.c (cxx_eval_constant_expression): Diagnose CONVERT_EXPR
conversions from pointer types to arithmetic types here...
(cxx_eval_outermost_constant_expr): ... instead of here.
* g++.dg/template/pr79650.C: Expect different diagnostics and expect
it on all lines that do pointer to integer casts.
* g++.dg/cpp1y/constexpr-shift1.C: Expect different diagnostics.
* g++.dg/cpp1y/constexpr-82304.C: New test.
* g++.dg/cpp0x/constexpr-95307.C: New test.
|
|
In the testcase below, the CONSTRUCTOR for 'field' contains a RANGE_EXPR
index:
{{aggr_init_expr<...>, [1...2]={.off=1}}}
but get_or_insert_ctor_field isn't prepared to handle looking up a
RANGE_EXPR index.
This patch adds limited support to get_or_insert_ctor_field for looking
up a RANGE_EXPR index. The limited scope of this patch should make it
more suitable for backporting, and more extensive support would be
needed only to handle self-modifying CONSTRUCTORs that contain a
RANGE_EXPR index, but I haven't yet been able to come up with a testcase
that actually creates such a CONSTRUCTOR.
gcc/cp/ChangeLog:
PR c++/95241
* constexpr.c (get_or_insert_ctor_field): Add limited support
for RANGE_EXPR index lookups.
gcc/testsuite/ChangeLog:
PR c++/95241
* g++.dg/cpp0x/constexpr-array25.C: New test.
|
|
In r9-297 I was trying to be more flexible and treat static data members of
class templates more like variable templates, where the type need not be
determined until the variable is instantiated, but I suppose that in a class
the types of all the non-template members need to be determined at the time
of class instantiation.
gcc/cp/ChangeLog:
PR c++/94926
* decl.c (cp_finish_decl): Revert r9-297 change.
(check_static_variable_definition): Likewise.
* constexpr.c (ensure_literal_type_for_constexpr_object): Likewise.
* pt.c (instantiate_decl): Return early on type error.
gcc/testsuite/ChangeLog:
* g++.dg/cpp1z/pr86648.C: Expect error.
* g++.dg/cpp1z/static2.C: Expect error.
* g++.dg/cpp0x/nsdmi16.C: New test.
|
|
Concept evaluation may entail DECL_UID generation and/or template
instantiation, so in general we can't perform it during uid-sensitive
constexpr evaluation.
gcc/cp/ChangeLog:
PR c++/94038
* constexpr.c (cxx_eval_constant_expression)
<case TEMPLATE_ID_EXPR>: Don't evaluate the concept when
constexpr evaluation is uid-sensitive.
gcc/testsuite/ChangeLog:
PR c++/94038
* g++.dg/warn/pr94038-3.C: New test.
|
|
The difference between a "potential" constant-expression and a regular
constant-expression is the treatment of parameters; in a constexpr function,
a parameter is potentially constant when evaluating a call to that function,
but it is not constant during parsing of the function.
cp_parser_constant_expression should check the latter rather than the
former.
gcc/cp/ChangeLog:
* cp-tree.h (is_rvalue_constant_expression): Declare.
* constexpr.c (is_rvalue_constant_expression): New.
* parser.c (cp_parser_constant_expression): Use it.
* decl.c (cp_finish_decl): Try to treat a constexpr initializer in a
template as constant.
|
|
Unfortunately, the previous fix to PR94038 is fragile. When the
argument to fold_for_warn is a bare CALL_EXPR, then all is well: the
result of maybe_constant_value from fold_for_warn (with
uid_sensitive=true) is reused via the cv_cache in the subsequent call to
maybe_constant_value from cp_fold (with uid_sensitive=false), so we
avoid instantiating bar<int>.
But when the argument to fold_for_warn is more complex, e.g. an
INDIRECT_REF of a CALL_EXPR, as in the testcase below (due to bar<int>()
returning const int& which we need to decay to int) then from
fold_for_warn we call maybe_constant_value on the INDIRECT_REF, and from
cp_fold we call it on the CALL_EXPR, so there is no reuse via the
cv_cache and we therefore end up instantiating bar<int>.
So for a more robust solution to this general issue of warning flags
affecting code generation, it seems that we need a way to globally avoid
template instantiation during constexpr evaluation whenever we're
performing warning-dependent folding.
To that end, this patch replaces the flag constexpr_ctx::uid_sensitive
with a global flag uid_sensitive_constexpr_evaluation_p, and enables it
during fold_for_warn using an RAII helper.
The patch also adds a counter that keeps track of the number of times
uid_sensitive_constexpr_evaluation_p is called and returned true, and we
use this to determine whether the result of constexpr evaluation
was restricted by the flag. This lets us safely update the cv_cache and
fold_cache from fold_for_warn in the most common case where the flag
did not restrict constexpr evaluation.
gcc/cp/ChangeLog:
PR c++/94038
* constexpr.c (constexpr_ctx::uid_sensitive): Remove field.
(uid_sensitive_constexpr_evaluation_value): Define.
(uid_sensitive_constexpr_evaluation_true_counter): Define.
(uid_sensitive_constexpr_evaluation_p): Define.
(uid_sensitive_constexpr_evaluation_sentinel): Define its
constructor.
(uid_sensitive_constexpr_evaluation_checker): Define its
constructor and its evaluation_restricted_p method.
(get_fundef_copy): Remove 'ctx' parameter. Use u_s_c_e_p
instead of constexpr_ctx::uid_sensitive.
(cxx_eval_call_expression): Use u_s_c_e_p instead, and test it
last. Adjust call to get_fundef_copy.
(instantiate_cx_fn_r): Test u_s_c_e_p so that we increment the
counter if necessary.
(cxx_eval_outermost_constant_expr): Remove 'uid_sensitive'
parameter. Adjust function body accordingly.
(maybe_constant_value): Remove 'uid_sensitive' parameter and
adjust function body accordingly. Set up a
uid_sensitive_constexpr_evaluation_checker, and use it to
conditionally update the cv_cache.
* cp-gimplify.c (cp_fold): Set up a
uid_sensitive_constexpr_evaluation_checker, and use it to
conditionally update the fold_cache.
* cp-tree.h (maybe_constant_value): Update declaration.
(struct uid_sensitive_constexpr_evaluation_sentinel): Define.
(struct sensitive_constexpr_evaluation_checker): Define.
* expr.c (fold_for_warn): Set up a
uid_sensitive_constexpr_evaluation_sentinel before calling
the folding subroutines. Drop all but the first argument to
maybe_constant_value.
gcc/testsuite/ChangeLog:
PR c++/94038
* g++.dg/warn/pr94038-2.C: New test.
|
|
C++20 isn't final quite yet, but all that remains is formalities, so let's
go ahead and change all the references.
I think for the next C++ standard we can just call it C++23 rather than
C++2b, since the committee has been consistent about time-based releases
rather than feature-based.
gcc/c-family/ChangeLog
2020-05-13 Jason Merrill <jason@redhat.com>
* c.opt (std=c++20): Make c++2a the alias.
(std=gnu++20): Likewise.
* c-common.h (cxx_dialect): Change cxx2a to cxx20.
* c-opts.c: Adjust.
* c-cppbuiltin.c: Adjust.
* c-ubsan.c: Adjust.
* c-warn.c: Adjust.
gcc/cp/ChangeLog
2020-05-13 Jason Merrill <jason@redhat.com>
* call.c, class.c, constexpr.c, constraint.cc, decl.c, init.c,
lambda.c, lex.c, method.c, name-lookup.c, parser.c, pt.c, tree.c,
typeck2.c: Change cxx2a to cxx20.
libcpp/ChangeLog
2020-05-13 Jason Merrill <jason@redhat.com>
* include/cpplib.h (enum c_lang): Change CXX2A to CXX20.
* init.c, lex.c: Adjust.
|
|
This is the same issue as PR86429, just in potential_constant_expression_1
rather than cxx_eval_constant_expression. As in that case, when we're
trying to evaluate a constant expression within a lambda, we don't have a
constant closure object to refer to, but we can try to refer directly to the
captured variable.
gcc/cp/ChangeLog
2020-05-05 Jason Merrill <jason@redhat.com>
PR c++/90212
* constexpr.c (potential_constant_expression_1): In a lambda
function, consider a captured variable directly.
|
|
In the first testcase below, the call to the target constructor foo{} from foo's
delegating constructor is encoded as the INIT_EXPR
*(struct foo *) this = AGGR_INIT_EXPR <4, __ct_comp, D.2140, ...>;
During initialization of the variable 'bar', we prematurely set TREE_READONLY on
bar's CONSTRUCTOR in two places before the outer delegating constructor has
returned: first, at the end of cxx_eval_call_expression after evaluating the RHS
of the above INIT_EXPR, and second, at the end of cxx_eval_store_expression
after having finished evaluating the above INIT_EXPR. This then prevents the
rest of the outer delegating constructor from mutating 'bar'.
This (hopefully minimally risky) patch makes cxx_eval_call_expression refrain
from setting TREE_READONLY when evaluating the target constructor of a
delegating constructor. It also makes cxx_eval_store_expression refrain from
setting TREE_READONLY when the object being initialized is "*this', on the basis
that it should be the responsibility of the routine that set 'this' in the first
place to set the object's TREE_READONLY appropriately.
gcc/cp/ChangeLog:
PR c++/94772
* constexpr.c (cxx_eval_call_expression): Don't set new_obj if we're
evaluating the target constructor of a delegating constructor.
(cxx_eval_store_expression): Don't set TREE_READONLY if the LHS of the
INIT_EXPR is '*this'.
gcc/testsuite/ChangeLog:
PR c++/94772
* g++.dg/cpp1y/constexpr-tracking-const23.C: New test.
* g++.dg/cpp1y/constexpr-tracking-const24.C: New test.
* g++.dg/cpp1y/constexpr-tracking-const25.C: New test.
|
|
As an extension (there should be a CWG about this though), we support
braced-init-list as a template argument, but convert_nontype_argument
had trouble digesting them. We ICEd because of the double coercion we
perform for template arguments: convert_nontype_argument called from
finish_template_type got a { }, and since a class type was involved and
we were in a template, convert_like created an IMPLICIT_CONV_EXPR. Then
the second conversion of the same argument crashed in constexpr.c
because the IMPLICIT_CONV_EXPR had gotten wrapped in a TARGET_EXPR.
Another issue was that an IMPLICIT_CONV_EXPR leaked to constexpr.c when
building an aggregate init.
We should have instantiated the IMPLICIT_CONV_EXPR in the first call to
convert_nontype_argument, but we didn't, because the call to
is_nondependent_constant_expression returned false because it checks
!BRACE_ENCLOSED_INITIALIZER_P. Then non_dep was false even though the
expression didn't contain anything dependent and we didn't instantiate
it in convert_nontype_argument. To fix this, check
BRACE_ENCLOSED_INITIALIZER_P in cxx_eval_outermost_constant_expr rather
than in is_nondependent_*.
PR c++/94592
* constexpr.c (cxx_eval_outermost_constant_expr): Return when T is
a BRACE_ENCLOSED_INITIALIZER_P.
(is_nondependent_constant_expression): Don't check
BRACE_ENCLOSED_INITIALIZER_P.
(is_nondependent_static_init_expression): Likewise.
* g++.dg/cpp2a/nontype-class34.C: New test.
* g++.dg/cpp2a/nontype-class35.C: New test.
|
|
When evaluating the initializer of 'a' in the following example
struct A {
A() = default; A(const A&);
A *p = this;
};
constexpr A foo() { return {}; }
constexpr A a = foo();
the PLACEHOLDER_EXPR for 'this' in the aggregate initializer returned by foo
gets resolved to the RESULT_DECL of foo. But due to guaranteed RVO, the 'this'
should really be resolved to '&a'.
Fixing this properly by immediately resolving 'this' and PLACEHOLDER_EXPRs to
the ultimate object under construction would in general mean that we would no
longer be able to cache constexpr calls for which RVO possibly applies, because
the result of the call may now depend on the ultimate object under construction.
So as a mostly correct stopgap solution that retains cachability of RVO'd
constexpr calls, this patch fixes this issue by rewriting all occurrences of the
RESULT_DECL in the result of a constexpr function call with the current object
under construction, after the call returns. This means the 'this' pointer
during construction of the temporary will still point to the temporary object
instead of the ultimate object, but besides that this approach seems
functionally equivalent to the proper approach.
gcc/cp/ChangeLog:
PR c++/94034
* constexpr.c (replace_result_decl_data): New struct.
(replace_result_decl_data_r): New function.
(replace_result_decl): New function.
(cxx_eval_call_expression): Use it.
* tree.c (build_aggr_init_expr): Set the location of the AGGR_INIT_EXPR
to that of its initializer.
gcc/testsuite/ChangeLog:
PR c++/94034
* g++.dg/cpp0x/constexpr-empty15.C: New test.
* g++.dg/cpp1y/constexpr-nsdmi6a.C: New test.
* g++.dg/cpp1y/constexpr-nsdmi6b.C: New test.
* g++.dg/cpp1y/constexpr-nsdmi7a.C: New test.
* g++.dg/cpp1y/constexpr-nsdmi7b.C: New test.
|
|
In this PR we're incorrectly rejecting a self-modifying constexpr initializer as
a consequence of the fix for PR78572.
It looks like however that the fix for PR78572 is obsoleted by the fix for
PR89336: the testcase from the former PR successfully compiles even with its fix
reverted.
But then further testing showed that the analogous testcase of PR78572 where the
array has an aggregate element type is still problematic (i.e. we ICE) even with
the fix for PR78572 applied. The reason is that in cxx_eval_bare_aggregate we
attach a constructor_elt of aggregate type always to the end of the new
CONSTRUCTOR, but that's not necessarily correct if the CONSTRUCTOR is
self-modifying. We should instead be using get_or_insert_ctor_field to insert
the constructor_elt in the right place.
So this patch reverts the PR78572 fix and makes the appropriate changes to
cxx_eval_bare_aggregate. This fixes PR94470, and we now are also able to fully
reduce the initializers of 'arr' and 'arr2' in the new test array57.C to
constant initializers.
gcc/cp/ChangeLog:
PR c++/94470
* constexpr.c (get_or_insert_ctor_field): Set default value of parameter
'pos_hint' to -1.
(cxx_eval_bare_aggregate): Use get_or_insert_ctor_field instead of
assuming the the next index belongs at the end of the new CONSTRUCTOR.
(cxx_eval_store_expression): Revert PR c++/78572 fix.
gcc/testsuite/ChangeLog:
PR c++/94470
* g++.dg/cpp1y/constexpr-nsdmi8.C: New test.
* g++.dg/cpp1y/constexpr-nsdmi9.C: New test.
* g++.dg/init/array57.C: New test.
|
|
Here due to my recent change to store_init_value we were expanding the
initializer of aw knowing that we were initializing aw. When
cxx_eval_call_expression finished the constructor, it wanted to look up the
value of aw to set TREE_READONLY on it, but we haven't set DECL_INITIAL yet,
so decl_constant_value tried to instantiate the initializer again. And
infinite recursion. Stopped by optimizing the case of asking for the value
of ctx->object, which is ctx->value. It also would have worked to look in
the values hash table, so let's move that up before decl_constant_value as
well.
gcc/cp/ChangeLog
2020-04-09 Jason Merrill <jason@redhat.com>
PR c++/94523
* constexpr.c (cxx_eval_constant_expression) [VAR_DECL]: Look at
ctx->object and ctx->global->values first.
|
|
This removes the use of replace_placeholders in cxx_eval_constant_expression
(which is causing the new test lambda-this6.C to ICE due to replace_placeholders
mutating the shared TARGET_EXPR_INITIAL tree which then trips up the
gimplifier).
In its place, this patch adds a 'parent' field to constexpr_ctx which is used to
store a pointer to an outer constexpr_ctx that refers to another object under
construction. With this new field, we can beef up lookup_placeholder to resolve
PLACEHOLDER_EXPRs which refer to former objects under construction, which fixes
PR94205 without needing to do replace_placeholders. Also we can now respect the
CONSTRUCTOR_PLACEHOLDER_BOUNDARY flag when resolving PLACEHOLDER_EXPRs, and
doing so fixes the constexpr analogue of PR79937.
gcc/cp/ChangeLog:
PR c++/94205
PR c++/79937
* constexpr.c (struct constexpr_ctx): New field 'parent'.
(cxx_eval_bare_aggregate): Propagate CONSTRUCTOR_PLACEHOLDER_BOUNDARY
flag from the original constructor to the reduced constructor.
(lookup_placeholder): Prefer to return the outermost matching object
by recursively calling lookup_placeholder on the 'parent' context,
but don't cross CONSTRUCTOR_PLACEHOLDER_BOUNDARY constructors.
(cxx_eval_constant_expression): Link the 'ctx' context to the 'new_ctx'
context via 'new_ctx.parent' when being expanded without an explicit
target. Don't call replace_placeholders.
(cxx_eval_outermost_constant_expr): Initialize 'ctx.parent' to NULL.
gcc/testsuite/ChangeLog:
PR c++/94205
PR c++/79937
* g++.dg/cpp1y/pr79937-5.C: New test.
* g++.dg/cpp1z/lambda-this6.C: New test.
|
|
This PR reveals that cxx_eval_bare_aggregate and cxx_eval_store_expression do
not anticipate that a constructor element's initializer could mutate the
underlying CONSTRUCTOR. Evaluation of the initializer could add new elements to
the underlying CONSTRUCTOR, thereby potentially invalidating any pointers to
or assumptions about the CONSTRUCTOR's elements, and so these routines should be
prepared for that.
To fix this problem, this patch makes cxx_eval_bare_aggregate and
cxx_eval_store_expression recompute the constructor_elt pointers through which
we're assigning, after it evaluates the initializer. Care is taken to to not
slow down the common case where the initializer does not modify the underlying
CONSTRUCTOR.
gcc/cp/ChangeLog:
PR c++/94219
PR c++/94205
* constexpr.c (get_or_insert_ctor_field): Split out (while adding
support for VECTOR_TYPEs, and optimizations for the common case)
from ...
(cxx_eval_store_expression): ... here. Rename local variable
'changed_active_union_member_p' to 'activated_union_member_p'. Record
the sequence of indexes into 'indexes' that yields the subobject we're
assigning to. Record the integer offsets of the constructor indexes
we're assigning through into 'index_pos_hints'. After evaluating the
initializer of the store expression, recompute 'valp' using 'indexes'
and using 'index_pos_hints' as hints.
(cxx_eval_bare_aggregate): Tweak comments. Use get_or_insert_ctor_field
to recompute the constructor_elt pointer we're assigning through after
evaluating each initializer.
gcc/testsuite/ChangeLog:
PR c++/94219
PR c++/94205
* g++.dg/cpp1y/constexpr-nsdmi3.C: New test.
* g++.dg/cpp1y/constexpr-nsdmi4.C: New test.
* g++.dg/cpp1y/constexpr-nsdmi5.C: New test.
* g++.dg/cpp1z/lambda-this5.C: New test.
|
|
The testcase hit an ICE trying to expand a TARGET_EXPR temporary cached from
the other lambda-expression. This patch fixes this in two ways:
1) Avoid reusing a TARGET_EXPR from another function.
2) Avoid ending up with a TARGET_EXPR at all; the use of 'p' had become
<TARGET_EXPR<NON_LVALUE_EXPR<TARGET_EXPR ...>>>, which doesn't make any
sense.
gcc/cp/ChangeLog
2020-04-04 Jason Merrill <jason@redhat.com>
PR c++/94453
* constexpr.c (maybe_constant_value): Use break_out_target_exprs.
* expr.c (mark_use) [VIEW_CONVERT_EXPR]: Don't wrap a TARGET_EXPR in
NON_LVALUE_EXPR.
|