aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2020-07-02 15:14:52 -0400
committerJason Merrill <jason@redhat.com>2020-07-10 08:36:50 -0400
commit50f071d999374b6dd13149a31f505d4457c9de6d (patch)
tree1885dd7dce23a0a290a08ea85c2e9f593c83d513 /gcc/cp
parente47dfca5aa473e77fdff95d631dc39de87a41eec (diff)
downloadgcc-50f071d999374b6dd13149a31f505d4457c9de6d.zip
gcc-50f071d999374b6dd13149a31f505d4457c9de6d.tar.gz
gcc-50f071d999374b6dd13149a31f505d4457c9de6d.tar.bz2
c++: Allow floating-point template parms in C++20.
P1907R1 made various adjustments to non-type template parameters, notably introducing the notion of "structural type". I implemented an early version of that specification in r10-4426, but it was adjusted in the final paper to allow more. This patch implements allowing template parameters of floating-point type; still to be implemented are unions and subobjects. gcc/cp/ChangeLog: * pt.c (convert_nontype_argument): Handle REAL_TYPE. (invalid_nontype_parm_type_p): Allow all structural types. * tree.c (structural_type_p): Use SCALAR_TYPE_P. gcc/testsuite/ChangeLog: * g++.dg/cpp0x/pr81246.C: No error in C++20. * g++.dg/cpp0x/variadic74.C: No error in C++20. * g++.dg/cpp1z/nontype-auto3.C: No error in C++20. * g++.dg/template/crash106.C: No error in C++20. * g++.dg/template/crash119.C: No error in C++20. * g++.dg/template/nontype12.C: No error in C++20. * g++.dg/template/void3.C: Don't require follow-on message. * g++.dg/template/void7.C: Don't require follow-on message. * g++.dg/template/void9.C: Don't require follow-on message.
Diffstat (limited to 'gcc/cp')
-rw-r--r--gcc/cp/pt.c47
-rw-r--r--gcc/cp/tree.c34
2 files changed, 44 insertions, 37 deletions
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index b6423f7..61f2273 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -7257,7 +7257,8 @@ convert_nontype_argument (tree type, tree expr, tsubst_flags_t complain)
For a non-type template-parameter of integral or enumeration type,
integral promotions (_conv.prom_) and integral conversions
(_conv.integral_) are applied. */
- if (INTEGRAL_OR_ENUMERATION_TYPE_P (type))
+ if (INTEGRAL_OR_ENUMERATION_TYPE_P (type)
+ || TREE_CODE (type) == REAL_TYPE)
{
if (cxx_dialect < cxx11)
{
@@ -7272,7 +7273,7 @@ convert_nontype_argument (tree type, tree expr, tsubst_flags_t complain)
/* Notice that there are constant expressions like '4 % 0' which
do not fold into integer constants. */
- if (TREE_CODE (expr) != INTEGER_CST && !val_dep_p)
+ if (!CONSTANT_CLASS_P (expr) && !val_dep_p)
{
if (complain & tf_error)
{
@@ -7287,7 +7288,7 @@ convert_nontype_argument (tree type, tree expr, tsubst_flags_t complain)
return NULL_TREE;
/* else cxx_constant_value complained but gave us
a real constant, so go ahead. */
- if (TREE_CODE (expr) != INTEGER_CST)
+ if (!CONSTANT_CLASS_P (expr))
{
/* Some assemble time constant expressions like
(intptr_t)&&lab1 - (intptr_t)&&lab2 or
@@ -7297,7 +7298,7 @@ convert_nontype_argument (tree type, tree expr, tsubst_flags_t complain)
compile time. Refuse them here. */
gcc_checking_assert (reduced_constant_expression_p (expr));
error_at (loc, "template argument %qE for type %qT not "
- "a constant integer", expr, type);
+ "a compile-time constant", expr, type);
return NULL_TREE;
}
}
@@ -26127,31 +26128,31 @@ invalid_nontype_parm_type_p (tree type, tsubst_flags_t complain)
else if (cxx_dialect >= cxx11
&& TREE_CODE (type) == BOUND_TEMPLATE_TEMPLATE_PARM)
return false;
- else if (CLASS_TYPE_P (type))
+ else if (VOID_TYPE_P (type))
+ /* Fall through. */;
+ else if (cxx_dialect >= cxx20)
{
- if (cxx_dialect < cxx20)
- {
- if (complain & tf_error)
- error ("non-type template parameters of class type only available "
- "with %<-std=c++20%> or %<-std=gnu++20%>");
- return true;
- }
if (dependent_type_p (type))
return false;
- if (!complete_type_or_else (type, NULL_TREE))
+ if (!complete_type_or_maybe_complain (type, NULL_TREE, complain))
return true;
- if (!structural_type_p (type))
+ if (structural_type_p (type))
+ return false;
+ if (complain & tf_error)
{
- if (complain & tf_error)
- {
- auto_diagnostic_group d;
- 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;
+ auto_diagnostic_group d;
+ 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 false;
+ return true;
+ }
+ else if (CLASS_TYPE_P (type))
+ {
+ if (complain & tf_error)
+ error ("non-type template parameters of class type only available "
+ "with %<-std=c++20%> or %<-std=gnu++20%>");
+ return true;
}
if (complain & tf_error)
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 7588c92..9effd27 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -4519,19 +4519,24 @@ zero_init_expr_p (tree t)
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))
+ /* A structural type is one of the following: */
+
+ /* a scalar type, or */
+ if (SCALAR_TYPE_P (t))
return true;
+ /* an lvalue reference type, or */
if (TYPE_REF_P (t) && !TYPE_REF_IS_RVALUE (t))
return true;
+ /* a literal class type with the following properties:
+ - all base classes and non-static data members are public and non-mutable
+ and
+ - the types of all bases classes and non-static data members are
+ structural types or (possibly multi-dimensional) array thereof. */
if (!CLASS_TYPE_P (t))
return false;
if (TREE_CODE (t) == UNION_TYPE)
{
+ /* FIXME allow (and mangle) unions. */
if (explain)
inform (location_of (t), "%qT is a union", t);
return false;
@@ -4542,12 +4547,6 @@ structural_type_p (tree t, bool 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)))
{
@@ -4563,12 +4562,19 @@ structural_type_p (tree t, bool explain)
}
return false;
}
- if (!structural_type_p (TREE_TYPE (m)))
+ if (DECL_MUTABLE_P (m))
+ {
+ if (explain)
+ inform (location_of (m), "%qD is mutable", m);
+ return false;
+ }
+ tree mtype = strip_array_types (TREE_TYPE (m));
+ if (!structural_type_p (mtype))
{
if (explain)
{
inform (location_of (m), "%qD has a non-structural type", m);
- structural_type_p (TREE_TYPE (m), true);
+ structural_type_p (mtype, true);
}
return false;
}