aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2019-11-06 19:50:19 -0500
committerJason Merrill <jason@gcc.gnu.org>2019-11-06 19:50:19 -0500
commit74fa38297b22d826f53f0b1894a1847eca3503dc (patch)
tree80dd4fe6801052da50c979452f37253d83c5496b
parent951c6f3dd975d795adc409da1a1477b5229199ae (diff)
downloadgcc-74fa38297b22d826f53f0b1894a1847eca3503dc.zip
gcc-74fa38297b22d826f53f0b1894a1847eca3503dc.tar.gz
gcc-74fa38297b22d826f53f0b1894a1847eca3503dc.tar.bz2
Implement D1907R1 "structural type".
ISO C++ paper D1907R1 proposes "structural type" as an alternative to the current notion of "strong structural equality", which has various problems. I'm implementing it to give people a chance to try it. The build_base_field changes are to make it easier for structural_type_p to see whether a base is private or protected. * tree.c (structural_type_p): New. * pt.c (invalid_nontype_parm_type_p): Use it. * class.c (build_base_field_1): Take binfo. Copy TREE_PRIVATE. (build_base_field): Pass binfo. From-SVN: r277902
-rw-r--r--gcc/cp/ChangeLog6
-rw-r--r--gcc/cp/class.c9
-rw-r--r--gcc/cp/cp-tree.h1
-rw-r--r--gcc/cp/pt.c18
-rw-r--r--gcc/cp/tree.c57
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/udlit-class-nttp-neg2.C2
6 files changed, 77 insertions, 16 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 8f6a71a..a0b93e7 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,5 +1,11 @@
2019-11-06 Jason Merrill <jason@redhat.com>
+ Implement D1907R1 "structural type".
+ * tree.c (structural_type_p): New.
+ * pt.c (invalid_nontype_parm_type_p): Use it.
+ * class.c (build_base_field_1): Take binfo. Copy TREE_PRIVATE.
+ (build_base_field): Pass binfo.
+
PR c++/92150 - partial specialization with class NTTP.
* pt.c (unify): Handle VIEW_CONVERT_EXPR.
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 89ed1c04..a9aa5e7 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -4353,15 +4353,18 @@ layout_empty_base_or_field (record_layout_info rli, tree binfo_or_decl,
fields at NEXT_FIELD, and return it. */
static tree
-build_base_field_1 (tree t, tree basetype, tree *&next_field)
+build_base_field_1 (tree t, tree binfo, tree *&next_field)
{
/* Create the FIELD_DECL. */
+ tree basetype = BINFO_TYPE (binfo);
gcc_assert (CLASSTYPE_AS_BASE (basetype));
tree decl = build_decl (input_location,
FIELD_DECL, NULL_TREE, CLASSTYPE_AS_BASE (basetype));
DECL_ARTIFICIAL (decl) = 1;
DECL_IGNORED_P (decl) = 1;
DECL_FIELD_CONTEXT (decl) = t;
+ TREE_PRIVATE (decl) = TREE_PRIVATE (binfo);
+ TREE_PROTECTED (decl) = TREE_PROTECTED (binfo);
if (is_empty_class (basetype))
/* CLASSTYPE_SIZE is one byte, but the field needs to have size zero. */
DECL_SIZE (decl) = DECL_SIZE_UNIT (decl) = size_zero_node;
@@ -4414,7 +4417,7 @@ build_base_field (record_layout_info rli, tree binfo,
CLASSTYPE_EMPTY_P (t) = 0;
/* Create the FIELD_DECL. */
- decl = build_base_field_1 (t, basetype, next_field);
+ decl = build_base_field_1 (t, binfo, next_field);
/* Try to place the field. It may take more than one try if we
have a hard time placing the field without putting two
@@ -4448,7 +4451,7 @@ build_base_field (record_layout_info rli, tree binfo,
aggregate bases. */
if (cxx_dialect >= cxx17 && !BINFO_VIRTUAL_P (binfo))
{
- tree decl = build_base_field_1 (t, basetype, next_field);
+ tree decl = build_base_field_1 (t, binfo, next_field);
DECL_FIELD_OFFSET (decl) = BINFO_OFFSET (binfo);
DECL_FIELD_BIT_OFFSET (decl) = bitsize_zero_node;
SET_DECL_OFFSET_ALIGN (decl, BITS_PER_UNIT);
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 2b45d62..adc021b 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -7302,6 +7302,7 @@ extern bool trivial_type_p (const_tree);
extern bool trivially_copyable_p (const_tree);
extern bool type_has_unique_obj_representations (const_tree);
extern bool scalarish_type_p (const_tree);
+extern bool structural_type_p (tree, bool = false);
extern bool type_has_nontrivial_default_init (const_tree);
extern bool type_has_nontrivial_copy_init (const_tree);
extern void maybe_warn_parm_abi (tree, location_t);
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 061a92c..8bacb39 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -25748,21 +25748,15 @@ invalid_nontype_parm_type_p (tree type, tsubst_flags_t complain)
return false;
if (!complete_type_or_else (type, NULL_TREE))
return true;
- if (!literal_type_p (type))
+ if (!structural_type_p (type))
{
- error ("%qT is not a valid type for a template non-type parameter "
- "because it is not literal", type);
- explain_non_literal_class (type);
- return true;
- }
- if (cp_has_mutable_p (type))
- {
- error ("%qT is not a valid type for a template non-type parameter "
- "because it has a mutable member", type);
+ auto_diagnostic_group d;
+ if (complain & tf_error)
+ error ("%qT is not a valid type for a template non-type parameter "
+ "because it is not structural", type);
+ structural_type_p (type, true);
return true;
}
- /* FIXME check op<=> and strong structural equality once spaceship is
- implemented. */
return false;
}
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 5cdeb6a..ba635d4 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -4378,6 +4378,63 @@ zero_init_p (const_tree t)
return 1;
}
+/* True IFF T is a C++20 structural type (P1907R1) that can be used as a
+ non-type template parameter. If EXPLAIN, explain why not. */
+
+bool
+structural_type_p (tree t, bool explain)
+{
+ t = strip_array_types (t);
+ if (INTEGRAL_OR_ENUMERATION_TYPE_P (t))
+ return true;
+ if (NULLPTR_TYPE_P (t))
+ return true;
+ if (TYPE_PTR_P (t) || TYPE_PTRMEM_P (t))
+ return true;
+ if (TYPE_REF_P (t) && !TYPE_REF_IS_RVALUE (t))
+ return true;
+ if (!CLASS_TYPE_P (t))
+ return false;
+ if (TREE_CODE (t) == UNION_TYPE)
+ {
+ if (explain)
+ inform (location_of (t), "%qT is a union", t);
+ return false;
+ }
+ if (!literal_type_p (t))
+ {
+ if (explain)
+ explain_non_literal_class (t);
+ return false;
+ }
+ if (CLASSTYPE_HAS_MUTABLE (t))
+ {
+ if (explain)
+ inform (location_of (t), "%qT has a mutable member", t);
+ return false;
+ }
+ for (tree m = next_initializable_field (TYPE_FIELDS (t)); m;
+ m = next_initializable_field (DECL_CHAIN (m)))
+ {
+ if (TREE_PRIVATE (m) || TREE_PROTECTED (m))
+ {
+ if (explain)
+ inform (location_of (m), "%qD is not public", m);
+ return false;
+ }
+ if (!structural_type_p (TREE_TYPE (m)))
+ {
+ if (explain)
+ {
+ inform (location_of (m), "%qD has a non-structural type", m);
+ structural_type_p (TREE_TYPE (m), true);
+ }
+ return false;
+ }
+ }
+ return true;
+}
+
/* Handle the C++17 [[nodiscard]] attribute, which is similar to the GNU
warn_unused_result attribute. */
diff --git a/gcc/testsuite/g++.dg/cpp2a/udlit-class-nttp-neg2.C b/gcc/testsuite/g++.dg/cpp2a/udlit-class-nttp-neg2.C
index 2c00c5c..71ba8f9 100644
--- a/gcc/testsuite/g++.dg/cpp2a/udlit-class-nttp-neg2.C
+++ b/gcc/testsuite/g++.dg/cpp2a/udlit-class-nttp-neg2.C
@@ -9,5 +9,5 @@ struct non_literal_class {
// auto operator<=> (const non_literal_fixed_string&) = default;
};
-template <non_literal_class> // { dg-error "11:is not a valid type for a template non-type parameter because it is not literal" }
+template <non_literal_class> // { dg-error "11:is not a valid type for a template non-type parameter because it is not structural" }
int operator"" _udl(); // { dg-error "5:literal operator template .int operator\"\"_udl\\(\\). has invalid parameter list" }