aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2021-01-25 17:02:57 -0500
committerJason Merrill <jason@redhat.com>2021-04-29 14:41:45 -0400
commitbc99c54de5a262ffc5f7801e16d919d335a53a8b (patch)
tree2feef056d55d6a95faa2e9ee5437e03e64448f3c
parenta0fdff3cf33f72848d3f894272431a5d49fe6a16 (diff)
downloadgcc-bc99c54de5a262ffc5f7801e16d919d335a53a8b.zip
gcc-bc99c54de5a262ffc5f7801e16d919d335a53a8b.tar.gz
gcc-bc99c54de5a262ffc5f7801e16d919d335a53a8b.tar.bz2
c++: Use empty field in constexpr eval.
In discussion of PR98463, Jakub noted that cxx_fold_indirect_ref_1 was bailing out early for empty bases even when we do have fields for them (in C++17 mode or later). This corrects that. gcc/cp/ChangeLog: * constexpr.c (cxx_fold_indirect_ref_1): Only set *empty_base if we don't find a field.
-rw-r--r--gcc/cp/constexpr.c36
1 files changed, 17 insertions, 19 deletions
diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
index fa7eaed..9481a5b 100644
--- a/gcc/cp/constexpr.c
+++ b/gcc/cp/constexpr.c
@@ -4734,28 +4734,17 @@ cxx_fold_indirect_ref_1 (const constexpr_ctx *ctx, location_t loc, tree type,
{
tree optype = TREE_TYPE (op);
unsigned HOST_WIDE_INT const_nunits;
- if (off == 0)
+ if (off == 0 && similar_type_p (optype, type))
+ return op;
+ else if (TREE_CODE (optype) == COMPLEX_TYPE
+ && similar_type_p (type, TREE_TYPE (optype)))
{
- if (similar_type_p (optype, type))
- return op;
- /* Also handle conversion to an empty base class, which
- is represented with a NOP_EXPR. */
/* *(foo *)&complexfoo => __real__ complexfoo */
- else if (TREE_CODE (optype) == COMPLEX_TYPE
- && similar_type_p (type, TREE_TYPE (optype)))
+ if (off == 0)
return build1_loc (loc, REALPART_EXPR, type, op);
- }
- /* ((foo*)&complexfoo)[1] => __imag__ complexfoo */
- else if (TREE_CODE (optype) == COMPLEX_TYPE
- && similar_type_p (type, TREE_TYPE (optype))
- && tree_to_uhwi (TYPE_SIZE_UNIT (type)) == off)
- return build1_loc (loc, IMAGPART_EXPR, type, op);
- if (is_empty_class (type)
- && CLASS_TYPE_P (optype)
- && DERIVED_FROM_P (type, optype))
- {
- *empty_base = true;
- return op;
+ /* ((foo*)&complexfoo)[1] => __imag__ complexfoo */
+ else if (tree_to_uhwi (TYPE_SIZE_UNIT (type)) == off)
+ return build1_loc (loc, IMAGPART_EXPR, type, op);
}
/* ((foo*)&vectorfoo)[x] => BIT_FIELD_REF<vectorfoo,...> */
else if (VECTOR_TYPE_P (optype)
@@ -4834,6 +4823,15 @@ cxx_fold_indirect_ref_1 (const constexpr_ctx *ctx, location_t loc, tree type,
return ret;
}
}
+ /* Also handle conversion to an empty base class, which
+ is represented with a NOP_EXPR. */
+ if (is_empty_class (type)
+ && CLASS_TYPE_P (optype)
+ && DERIVED_FROM_P (type, optype))
+ {
+ *empty_base = true;
+ return op;
+ }
}
return NULL_TREE;