aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp
diff options
context:
space:
mode:
authorJonathan Wakely <jwakely@redhat.com>2022-09-06 13:21:09 +0100
committerJonathan Wakely <jwakely@redhat.com>2022-09-08 19:29:13 +0100
commit30c811f2bac73e63e0b461ba7ed3805b77898798 (patch)
tree4d3fc323d13afc3c182720d9d9ae1137ef5c1e97 /gcc/cp
parent4977507e329ee3ed410fc7338b9aaada81b68361 (diff)
downloadgcc-30c811f2bac73e63e0b461ba7ed3805b77898798.zip
gcc-30c811f2bac73e63e0b461ba7ed3805b77898798.tar.gz
gcc-30c811f2bac73e63e0b461ba7ed3805b77898798.tar.bz2
c++: Fix type completeness checks for type traits [PR106838]
The check_trait_type function is used for a number of different type traits that have different requirements on their arguments. For example, __is_constructible allows arrays of unknown bound even if the array element is an incomplete type, but __is_aggregate does not, it always requires the array element type to be complete. Other traits have different requirements again, e.g. __is_empty allows incomplete unions, and arrays (of known or unknown bound) of incomplete types. This alters the check_trait_type function to take an additional KIND parameter which indicates which set of type trait requirements to check. As noted in a comment, the requirements for __is_aggregate deviate from the ones for std::is_aggregate in the standard. It's not necessary for the elements of an array to be complete types, because arrays are always aggregates. The type_has_virtual_destructor change is needed to avoid an ICE. Previously it could never be called for incomplete union types as they were (incorrectly) rejected by check_trait_type. This change causes some additional diagnostics in some libstdc++ tests, where the front end was not previously complaining about invalid types that the library assertions diagnosed. We should consider removing the library assertions from traits where the front end implements the correct checks now. PR c++/106838 gcc/cp/ChangeLog: * class.cc (type_has_virtual_destructor): Return false for union types. * semantics.cc (check_trait_type): Add KIND parameter to support different sets of requirements. (finish_trait_expr): Pass KIND argument for relevant traits. gcc/ChangeLog: * doc/extend.texi (Type Traits): Fix requirements. Document __is_aggregate and __is_final. gcc/testsuite/ChangeLog: * g++.dg/ext/array4.C: Fix invalid use of __is_constructible. * g++.dg/ext/unary_trait_incomplete.C: Fix tests for traits with different requirements. libstdc++-v3/ChangeLog: * testsuite/20_util/is_complete_or_unbounded/memoization_neg.cc: Prune additional errors from front-end. * testsuite/20_util/is_move_constructible/incomplete_neg.cc: Likewise. * testsuite/20_util/is_nothrow_swappable/incomplete_neg.cc: Likewise. * testsuite/20_util/is_nothrow_swappable_with/incomplete_neg.cc: Likewise. * testsuite/20_util/is_swappable_with/incomplete_neg.cc: Likewise.
Diffstat (limited to 'gcc/cp')
-rw-r--r--gcc/cp/class.cc2
-rw-r--r--gcc/cp/semantics.cc58
2 files changed, 47 insertions, 13 deletions
diff --git a/gcc/cp/class.cc b/gcc/cp/class.cc
index a12d367..b84f422 100644
--- a/gcc/cp/class.cc
+++ b/gcc/cp/class.cc
@@ -5620,7 +5620,7 @@ type_has_virtual_destructor (tree type)
{
tree dtor;
- if (!CLASS_TYPE_P (type))
+ if (!NON_UNION_CLASS_TYPE_P (type))
return false;
gcc_assert (COMPLETE_TYPE_P (type));
diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
index 3d58d67..6bda30e 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -12028,11 +12028,23 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree type2)
}
}
-/* If TYPE is an array of unknown bound, or (possibly cv-qualified)
- void, or a complete type, returns true, otherwise false. */
+/* Returns true if TYPE meets the requirements for the specified KIND,
+ false otherwise.
+
+ When KIND == 1, TYPE must be an array of unknown bound,
+ or (possibly cv-qualified) void, or a complete type.
+
+ When KIND == 2, TYPE must be a complete type, or array of complete type,
+ or (possibly cv-qualified) void.
+
+ When KIND == 3:
+ If TYPE is a non-union class type, it must be complete.
+
+ When KIND == 4:
+ If TYPE is a class type, it must be complete. */
static bool
-check_trait_type (tree type)
+check_trait_type (tree type, int kind = 1)
{
if (type == NULL_TREE)
return true;
@@ -12041,8 +12053,14 @@ check_trait_type (tree type)
return (check_trait_type (TREE_VALUE (type))
&& check_trait_type (TREE_CHAIN (type)));
- if (TREE_CODE (type) == ARRAY_TYPE && !TYPE_DOMAIN (type))
- return true;
+ if (kind == 1 && TREE_CODE (type) == ARRAY_TYPE && !TYPE_DOMAIN (type))
+ return true; // Array of unknown bound. Don't care about completeness.
+
+ if (kind == 3 && !NON_UNION_CLASS_TYPE_P (type))
+ return true; // Not a non-union class type. Don't care about completeness.
+
+ if (kind == 4 && TREE_CODE (type) == ARRAY_TYPE)
+ return true; // Not a class type. Don't care about completeness.
if (VOID_TYPE_P (type))
return true;
@@ -12080,23 +12098,39 @@ finish_trait_expr (location_t loc, cp_trait_kind kind, tree type1, tree type2)
case CPTK_HAS_TRIVIAL_COPY:
case CPTK_HAS_TRIVIAL_DESTRUCTOR:
case CPTK_HAS_UNIQUE_OBJ_REPRESENTATIONS:
- case CPTK_HAS_VIRTUAL_DESTRUCTOR:
- case CPTK_IS_ABSTRACT:
- case CPTK_IS_AGGREGATE:
- case CPTK_IS_EMPTY:
- case CPTK_IS_FINAL:
+ if (!check_trait_type (type1))
+ return error_mark_node;
+ break;
+
case CPTK_IS_LITERAL_TYPE:
case CPTK_IS_POD:
- case CPTK_IS_POLYMORPHIC:
case CPTK_IS_STD_LAYOUT:
case CPTK_IS_TRIVIAL:
case CPTK_IS_TRIVIALLY_COPYABLE:
- if (!check_trait_type (type1))
+ if (!check_trait_type (type1, /* kind = */ 2))
+ return error_mark_node;
+ break;
+
+ case CPTK_IS_EMPTY:
+ case CPTK_IS_POLYMORPHIC:
+ case CPTK_IS_ABSTRACT:
+ case CPTK_HAS_VIRTUAL_DESTRUCTOR:
+ if (!check_trait_type (type1, /* kind = */ 3))
+ return error_mark_node;
+ break;
+
+ /* N.B. std::is_aggregate is kind=2 but we don't need a complete element
+ type to know whether an array is an aggregate, so use kind=4 here. */
+ case CPTK_IS_AGGREGATE:
+ case CPTK_IS_FINAL:
+ if (!check_trait_type (type1, /* kind = */ 4))
return error_mark_node;
break;
case CPTK_IS_ASSIGNABLE:
case CPTK_IS_CONSTRUCTIBLE:
+ if (!check_trait_type (type1))
+ return error_mark_node;
break;
case CPTK_IS_TRIVIALLY_ASSIGNABLE: