c++: ICE with __has_unique_object_representations [PR115476]

Here we started to ICE with r13-25: in check_trait_type, for "X[]" we
return true here:

  if (kind == 1 && TREE_CODE (type) == ARRAY_TYPE && !TYPE_DOMAIN (type))
    return true; // Array of unknown bound. Don't care about completeness.

and then end up crashing in record_has_unique_obj_representations:

4836	  if (cur != wi::to_offset (sz))

because sz is null.

https://eel.is/c++draft/type.traits#tab:meta.unary.prop-row-47-column-3-sentence-1
says that the preconditions for __has_unique_object_representations are:
"T shall be a complete type, cv void, or an array of unknown bound" and
that "For an array type T, the same result as
has_unique_object_representations_v<remove_all_extents_t<T>>" so T[]
should be treated as T.  So we should use kind==2 for the trait.

	PR c++/115476

gcc/cp/ChangeLog:

	* semantics.cc (finish_trait_expr)
	<case CPTK_HAS_UNIQUE_OBJ_REPRESENTATIONS>: Move below to call
	check_trait_type with kind==2.

gcc/testsuite/ChangeLog:

	* g++.dg/cpp1z/has-unique-obj-representations4.C: New test.
This commit is contained in:
Marek Polacek 2024-06-17 17:53:12 -04:00
parent b1e828dd96
commit fc382a373e
2 changed files with 17 additions and 1 deletions

View File

@ -12959,7 +12959,6 @@ finish_trait_expr (location_t loc, cp_trait_kind kind, tree type1, tree type2)
case CPTK_HAS_NOTHROW_COPY: case CPTK_HAS_NOTHROW_COPY:
case CPTK_HAS_TRIVIAL_COPY: case CPTK_HAS_TRIVIAL_COPY:
case CPTK_HAS_TRIVIAL_DESTRUCTOR: case CPTK_HAS_TRIVIAL_DESTRUCTOR:
case CPTK_HAS_UNIQUE_OBJ_REPRESENTATIONS:
if (!check_trait_type (type1)) if (!check_trait_type (type1))
return error_mark_node; return error_mark_node;
break; break;
@ -12969,6 +12968,7 @@ finish_trait_expr (location_t loc, cp_trait_kind kind, tree type1, tree type2)
case CPTK_IS_STD_LAYOUT: case CPTK_IS_STD_LAYOUT:
case CPTK_IS_TRIVIAL: case CPTK_IS_TRIVIAL:
case CPTK_IS_TRIVIALLY_COPYABLE: case CPTK_IS_TRIVIALLY_COPYABLE:
case CPTK_HAS_UNIQUE_OBJ_REPRESENTATIONS:
if (!check_trait_type (type1, /* kind = */ 2)) if (!check_trait_type (type1, /* kind = */ 2))
return error_mark_node; return error_mark_node;
break; break;

View File

@ -0,0 +1,16 @@
// PR c++/115476
// { dg-do compile { target c++11 } }
struct X;
static_assert(__has_unique_object_representations(X), ""); // { dg-error "invalid use of incomplete type" }
static_assert(__has_unique_object_representations(X[]), ""); // { dg-error "invalid use of incomplete type" }
static_assert(__has_unique_object_representations(X[1]), ""); // { dg-error "invalid use of incomplete type" }
static_assert(__has_unique_object_representations(X[][1]), ""); // { dg-error "invalid use of incomplete type" }
struct X {
int x;
};
static_assert(__has_unique_object_representations(X), "");
static_assert(__has_unique_object_representations(X[]), "");
static_assert(__has_unique_object_representations(X[1]), "");
static_assert(__has_unique_object_representations(X[][1]), "");