diff options
author | Jason Merrill <jason@redhat.com> | 2022-01-20 05:45:02 -0500 |
---|---|---|
committer | Jason Merrill <jason@redhat.com> | 2022-01-22 22:18:02 -0500 |
commit | 053bcc97f4a59e3f2811b8a1edf60fd733a580a0 (patch) | |
tree | 67c0720cf64acec9f7a48c8e0f16b3e9936dc2b5 /gcc/cp | |
parent | d43be9dcc1bef95d70fb411d98b4de0d83c6b85d (diff) | |
download | gcc-053bcc97f4a59e3f2811b8a1edf60fd733a580a0.zip gcc-053bcc97f4a59e3f2811b8a1edf60fd733a580a0.tar.gz gcc-053bcc97f4a59e3f2811b8a1edf60fd733a580a0.tar.bz2 |
c++: constexpr and -fno-elide-constructors [PR101072]
We've been trying for a while to avoid TARGET_EXPRs in template code, but
there were still a few that snuck through, and the one in this case broke
the code that tried to handle it. Fixed by using IMPLICIT_CONV_EXPR, as we
have done elsewhere.
I also noticed that finish_compound_literal was assuming that all T{init}
were for aggregate T, and we got a few more TARGET_EXPRs from that. Fixed
by only messing with TARGET_EXPR if we actually have an aggregate init.
PR c++/101072
gcc/cp/ChangeLog:
* cp-tree.h (build_implicit_conv_flags): Declare.
* call.cc (build_implicit_conv_flags): Split out from...
(perform_implicit_conversion_flags): ...here.
* decl.cc (check_initializer): Use it.
* pt.cc (tsubst_copy_and_build): Remove TARGET_EXPR handling.
* semantics.cc (finish_compound_literal): Don't treat
scalar values like CONSTRUCTORs.
gcc/testsuite/ChangeLog:
* g++.dg/cpp0x/constexpr-empty14a.C: New test.
Diffstat (limited to 'gcc/cp')
-rw-r--r-- | gcc/cp/call.cc | 32 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 1 | ||||
-rw-r--r-- | gcc/cp/decl.cc | 7 | ||||
-rw-r--r-- | gcc/cp/pt.cc | 9 | ||||
-rw-r--r-- | gcc/cp/semantics.cc | 9 |
5 files changed, 34 insertions, 24 deletions
diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc index d4a07a7..f7f861c 100644 --- a/gcc/cp/call.cc +++ b/gcc/cp/call.cc @@ -12638,6 +12638,25 @@ can_convert_arg_bad (tree to, tree from, tree arg, int flags, return t != NULL; } +/* Return an IMPLICIT_CONV_EXPR from EXPR to TYPE with bits set from overload + resolution FLAGS. */ + +tree +build_implicit_conv_flags (tree type, tree expr, int flags) +{ + /* In a template, we are only concerned about determining the + type of non-dependent expressions, so we do not have to + perform the actual conversion. But for initializers, we + need to be able to perform it at instantiation + (or instantiate_non_dependent_expr) time. */ + expr = build1 (IMPLICIT_CONV_EXPR, type, expr); + if (!(flags & LOOKUP_ONLYCONVERTING)) + IMPLICIT_CONV_EXPR_DIRECT_INIT (expr) = true; + if (flags & LOOKUP_NO_NARROWING) + IMPLICIT_CONV_EXPR_BRACED_INIT (expr) = true; + return expr; +} + /* Convert EXPR to TYPE. Return the converted expression. Note that we allow bad conversions here because by the time we get to @@ -12674,18 +12693,7 @@ perform_implicit_conversion_flags (tree type, tree expr, expr = error_mark_node; } else if (processing_template_decl && conv->kind != ck_identity) - { - /* In a template, we are only concerned about determining the - type of non-dependent expressions, so we do not have to - perform the actual conversion. But for initializers, we - need to be able to perform it at instantiation - (or instantiate_non_dependent_expr) time. */ - expr = build1 (IMPLICIT_CONV_EXPR, type, expr); - if (!(flags & LOOKUP_ONLYCONVERTING)) - IMPLICIT_CONV_EXPR_DIRECT_INIT (expr) = true; - if (flags & LOOKUP_NO_NARROWING) - IMPLICIT_CONV_EXPR_BRACED_INIT (expr) = true; - } + expr = build_implicit_conv_flags (type, expr, flags); else { /* Give a conversion call the same location as expr. */ diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 186c544..b9eb71f 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -6599,6 +6599,7 @@ extern tree strip_top_quals (tree); extern bool reference_related_p (tree, tree); extern bool reference_compatible_p (tree, tree); extern int remaining_arguments (tree); +extern tree build_implicit_conv_flags (tree, tree, int); extern tree perform_implicit_conversion (tree, tree, tsubst_flags_t); extern tree perform_implicit_conversion_flags (tree, tree, tsubst_flags_t, int); extern tree build_converted_constant_expr (tree, tree, tsubst_flags_t); diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc index 8e54218..c5d4f2f 100644 --- a/gcc/cp/decl.cc +++ b/gcc/cp/decl.cc @@ -7235,7 +7235,12 @@ check_initializer (tree decl, tree init, int flags, vec<tree, va_gc> **cleanups) /* In C++20, the call to build_aggr_init could have created an INIT_EXPR with a CONSTRUCTOR as the RHS to handle A(1, 2). */ - init = TREE_OPERAND (init_code, 1); + tree rhs = TREE_OPERAND (init_code, 1); + if (processing_template_decl && TREE_CODE (rhs) == TARGET_EXPR) + /* Avoid leaking TARGET_EXPR into template trees. */ + rhs = build_implicit_conv_flags (type, init, flags); + init = rhs; + init_code = NULL_TREE; /* Don't call digest_init; it's unnecessary and will complain about aggregate initialization of non-aggregate classes. */ diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc index 5afcb41..bba62a5 100644 --- a/gcc/cp/pt.cc +++ b/gcc/cp/pt.cc @@ -21151,15 +21151,6 @@ tsubst_copy_and_build (tree t, RETURN (build_lambda_object (r)); } - case TARGET_EXPR: - /* We can get here for a constant initializer of non-dependent type. - FIXME stop folding in cp_parser_initializer_clause. */ - { - tree r = get_target_expr_sfinae (RECUR (TARGET_EXPR_INITIAL (t)), - complain); - RETURN (r); - } - case TRANSACTION_EXPR: RETURN (tsubst_expr(t, args, complain, in_decl, integral_constant_expression_p)); diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc index 640b2d7..07c2b33 100644 --- a/gcc/cp/semantics.cc +++ b/gcc/cp/semantics.cc @@ -3272,12 +3272,17 @@ finish_compound_literal (tree type, tree compound_literal, /* Represent other compound literals with TARGET_EXPR so we produce a prvalue, and can elide copies. */ - if (!VECTOR_TYPE_P (type)) + if (TREE_CODE (compound_literal) == CONSTRUCTOR + || TREE_CODE (compound_literal) == VEC_INIT_EXPR) { /* The CONSTRUCTOR is now an initializer, not a compound literal. */ - TREE_HAS_CONSTRUCTOR (compound_literal) = false; + if (TREE_CODE (compound_literal) == CONSTRUCTOR) + TREE_HAS_CONSTRUCTOR (compound_literal) = false; compound_literal = get_target_expr_sfinae (compound_literal, complain); } + else + /* For e.g. int{42} just make sure it's a prvalue. */ + compound_literal = rvalue (compound_literal); return compound_literal; } |