diff options
author | Jason Merrill <jason@redhat.com> | 2020-07-02 15:14:52 -0400 |
---|---|---|
committer | Jason Merrill <jason@redhat.com> | 2020-07-10 08:36:50 -0400 |
commit | 50f071d999374b6dd13149a31f505d4457c9de6d (patch) | |
tree | 1885dd7dce23a0a290a08ea85c2e9f593c83d513 /gcc/cp | |
parent | e47dfca5aa473e77fdff95d631dc39de87a41eec (diff) | |
download | gcc-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.c | 47 | ||||
-rw-r--r-- | gcc/cp/tree.c | 34 |
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; } |