diff options
author | Marek Polacek <polacek@redhat.com> | 2019-09-23 17:37:54 +0000 |
---|---|---|
committer | Marek Polacek <mpolacek@gcc.gnu.org> | 2019-09-23 17:37:54 +0000 |
commit | 1a09197cb1bc05a71d1866d1220937289da02c5e (patch) | |
tree | aefb9cfa8c4542ee2235dc93fa2107880eaf40b1 /gcc/cp | |
parent | ba2b30dc9fa9190101b3eb7ae10415b54ca25e7a (diff) | |
download | gcc-1a09197cb1bc05a71d1866d1220937289da02c5e.zip gcc-1a09197cb1bc05a71d1866d1220937289da02c5e.tar.gz gcc-1a09197cb1bc05a71d1866d1220937289da02c5e.tar.bz2 |
PR c++/91844 - Implement CWG 2352, Similar types and reference binding.
* call.c (reference_related_p): Use similar_type_p instead of
same_type_p.
(reference_compatible_p): Update implementation to match CWG 2352.
* cp-tree.h (similar_type_p): Declare.
* typeck.c (similar_type_p): New.
* g++.dg/cpp0x/pr33930.C: Add dg-error.
* g++.dg/cpp0x/ref-bind1.C: New test.
* g++.dg/cpp0x/ref-bind2.C: New test.
* g++.dg/cpp0x/ref-bind3.C: New test.
* g++.old-deja/g++.pt/spec35.C: Remove dg-error.
From-SVN: r276058
Diffstat (limited to 'gcc/cp')
-rw-r--r-- | gcc/cp/ChangeLog | 9 | ||||
-rw-r--r-- | gcc/cp/call.c | 22 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 1 | ||||
-rw-r--r-- | gcc/cp/typeck.c | 27 |
4 files changed, 48 insertions, 11 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 4420d8f..7ccc7cd 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,12 @@ +2019-09-23 Marek Polacek <polacek@redhat.com> + + PR c++/91844 - Implement CWG 2352, Similar types and reference binding. + * call.c (reference_related_p): Use similar_type_p instead of + same_type_p. + (reference_compatible_p): Update implementation to match CWG 2352. + * cp-tree.h (similar_type_p): Declare. + * typeck.c (similar_type_p): New. + 2019-09-22 Marek Polacek <polacek@redhat.com> PR c++/91819 - ICE with operator++ and enum. diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 2dad699..28b3f33 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -1530,9 +1530,8 @@ reference_related_p (tree t1, tree t2) /* [dcl.init.ref] Given types "cv1 T1" and "cv2 T2," "cv1 T1" is reference-related - to "cv2 T2" if T1 is the same type as T2, or T1 is a base class - of T2. */ - return (same_type_p (t1, t2) + to "cv2 T2" if T1 is similar to T2, or T1 is a base class of T2. */ + return (similar_type_p (t1, t2) || (CLASS_TYPE_P (t1) && CLASS_TYPE_P (t2) && DERIVED_FROM_P (t1, t2))); } @@ -1545,14 +1544,15 @@ reference_compatible_p (tree t1, tree t2) /* [dcl.init.ref] "cv1 T1" is reference compatible with "cv2 T2" if - * T1 is reference-related to T2 or - * T2 is "noexcept function" and T1 is "function", where the - function types are otherwise the same, - and cv1 is the same cv-qualification as, or greater cv-qualification - than, cv2. */ - return ((reference_related_p (t1, t2) - || fnptr_conv_p (t1, t2)) - && at_least_as_qualified_p (t1, t2)); + a prvalue of type "pointer to cv2 T2" can be converted to the type + "pointer to cv1 T1" via a standard conversion sequence. */ + tree ptype1 = build_pointer_type (t1); + tree ptype2 = build_pointer_type (t2); + conversion *conv = standard_conversion (ptype1, ptype2, NULL_TREE, + /*c_cast_p=*/false, 0, tf_none); + if (!conv || conv->bad_p) + return false; + return true; } /* A reference of the indicated TYPE is being bound directly to the diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 6d217fc..9c0f394 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -7361,6 +7361,7 @@ enum { ce_derived, ce_type, ce_normal, ce_exact }; extern bool comp_except_specs (const_tree, const_tree, int); extern bool comptypes (tree, tree, int); extern bool same_type_ignoring_top_level_qualifiers_p (tree, tree); +extern bool similar_type_p (tree, tree); extern bool compparms (const_tree, const_tree); extern int comp_cv_qualification (const_tree, const_tree); extern int comp_cv_qualification (int, int); diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index d85e547..f427c4f 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -1530,6 +1530,33 @@ same_type_ignoring_top_level_qualifiers_p (tree type1, tree type2) return same_type_p (type1, type2); } +/* Returns nonzero iff TYPE1 and TYPE2 are similar, as per [conv.qual]. */ + +bool +similar_type_p (tree type1, tree type2) +{ + if (type1 == error_mark_node || type2 == error_mark_node) + return false; + + /* Informally, two types are similar if, ignoring top-level cv-qualification: + * they are the same type; or + * they are both pointers, and the pointed-to types are similar; or + * they are both pointers to member of the same class, and the types of + the pointed-to members are similar; or + * they are both arrays of the same size or both arrays of unknown bound, + and the array element types are similar. */ + + if (same_type_ignoring_top_level_qualifiers_p (type1, type2)) + return true; + + /* FIXME This ought to handle ARRAY_TYPEs too. */ + if ((TYPE_PTR_P (type1) && TYPE_PTR_P (type2)) + || (TYPE_PTRDATAMEM_P (type1) && TYPE_PTRDATAMEM_P (type2))) + return comp_ptr_ttypes_const (type1, type2); + + return false; +} + /* Returns 1 if TYPE1 is at least as qualified as TYPE2. */ bool |