public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc r12-6821] c++: constexpr and -fno-elide-constructors [PR101072]
@ 2022-01-23 3:19 Jason Merrill
0 siblings, 0 replies; only message in thread
From: Jason Merrill @ 2022-01-23 3:19 UTC (permalink / raw)
To: gcc-cvs
https://gcc.gnu.org/g:053bcc97f4a59e3f2811b8a1edf60fd733a580a0
commit r12-6821-g053bcc97f4a59e3f2811b8a1edf60fd733a580a0
Author: Jason Merrill <jason@redhat.com>
Date: Thu Jan 20 05:45:02 2022 -0500
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.
Diff:
---
gcc/cp/cp-tree.h | 1 +
gcc/cp/call.cc | 32 +++++++++++++++----------
gcc/cp/decl.cc | 7 +++++-
gcc/cp/pt.cc | 9 -------
gcc/cp/semantics.cc | 9 +++++--
gcc/testsuite/g++.dg/cpp0x/constexpr-empty14a.C | 11 +++++++++
6 files changed, 45 insertions(+), 24 deletions(-)
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 186c54424a6..b9eb71fbc3a 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/call.cc b/gcc/cp/call.cc
index d4a07a7a9b3..f7f861cd16e 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/decl.cc b/gcc/cp/decl.cc
index 8e5421848d1..c5d4f2f5369 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 5afcb41eccd..bba62a5800a 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 640b2d75471..07c2b3393be 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;
}
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-empty14a.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-empty14a.C
new file mode 100644
index 00000000000..df34cfcb8e7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-empty14a.C
@@ -0,0 +1,11 @@
+// PR c++/101072
+// { dg-do compile { target c++11 } }
+// { dg-additional-options -fno-elide-constructors }
+
+struct S {};
+
+template <class T> void
+foo (S s)
+{
+ constexpr S x = s;
+}
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2022-01-23 3:19 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-01-23 3:19 [gcc r12-6821] c++: constexpr and -fno-elide-constructors [PR101072] Jason Merrill
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).