aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/semantics.c
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2020-12-03 15:46:54 +0100
committerJakub Jelinek <jakub@redhat.com>2020-12-03 15:46:54 +0100
commit896048cf43d5eb21ab7c16553bb9d13b0f890b81 (patch)
tree3d929f74e3ad0cd70a86d101744be4a961a57450 /gcc/cp/semantics.c
parent341035a54aa8954c66b0492f366b8c65fdb34299 (diff)
downloadgcc-896048cf43d5eb21ab7c16553bb9d13b0f890b81.zip
gcc-896048cf43d5eb21ab7c16553bb9d13b0f890b81.tar.gz
gcc-896048cf43d5eb21ab7c16553bb9d13b0f890b81.tar.bz2
c++: Add __builtin_bit_cast to implement std::bit_cast [PR93121]
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.
Diffstat (limited to 'gcc/cp/semantics.c')
-rw-r--r--gcc/cp/semantics.c71
1 files changed, 71 insertions, 0 deletions
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 5ff70ff..d33ef42 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -10679,4 +10679,75 @@ cp_build_vec_convert (tree arg, location_t loc, tree type,
return build_call_expr_internal_loc (loc, IFN_VEC_CONVERT, type, 1, arg);
}
+/* Finish __builtin_bit_cast (type, arg). */
+
+tree
+cp_build_bit_cast (location_t loc, tree type, tree arg,
+ tsubst_flags_t complain)
+{
+ if (error_operand_p (type))
+ return error_mark_node;
+ if (!dependent_type_p (type))
+ {
+ if (!complete_type_or_maybe_complain (type, NULL_TREE, complain))
+ return error_mark_node;
+ if (TREE_CODE (type) == ARRAY_TYPE)
+ {
+ /* std::bit_cast for destination ARRAY_TYPE is not possible,
+ as functions may not return an array, so don't bother trying
+ to support this (and then deal with VLAs etc.). */
+ error_at (loc, "%<__builtin_bit_cast%> destination type %qT "
+ "is an array type", type);
+ return error_mark_node;
+ }
+ if (!trivially_copyable_p (type))
+ {
+ error_at (loc, "%<__builtin_bit_cast%> destination type %qT "
+ "is not trivially copyable", type);
+ return error_mark_node;
+ }
+ }
+
+ if (error_operand_p (arg))
+ return error_mark_node;
+
+ if (!type_dependent_expression_p (arg))
+ {
+ if (TREE_CODE (TREE_TYPE (arg)) == ARRAY_TYPE)
+ {
+ /* Don't perform array-to-pointer conversion. */
+ arg = mark_rvalue_use (arg, loc, true);
+ if (!complete_type_or_maybe_complain (TREE_TYPE (arg), arg, complain))
+ return error_mark_node;
+ }
+ else
+ arg = decay_conversion (arg, complain);
+
+ if (error_operand_p (arg))
+ return error_mark_node;
+
+ if (!trivially_copyable_p (TREE_TYPE (arg)))
+ {
+ error_at (cp_expr_loc_or_loc (arg, loc),
+ "%<__builtin_bit_cast%> source type %qT "
+ "is not trivially copyable", TREE_TYPE (arg));
+ return error_mark_node;
+ }
+ if (!dependent_type_p (type)
+ && !cp_tree_equal (TYPE_SIZE_UNIT (type),
+ TYPE_SIZE_UNIT (TREE_TYPE (arg))))
+ {
+ error_at (loc, "%<__builtin_bit_cast%> source size %qE "
+ "not equal to destination type size %qE",
+ TYPE_SIZE_UNIT (TREE_TYPE (arg)),
+ TYPE_SIZE_UNIT (type));
+ return error_mark_node;
+ }
+ }
+
+ tree ret = build_min (BIT_CAST_EXPR, type, arg);
+ SET_EXPR_LOCATION (ret, loc);
+ return ret;
+}
+
#include "gt-cp-semantics.h"