Skip to content

[Clang] Require base element type of __has_unique_object_representations to be complete #95432

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -660,6 +660,9 @@ Bug Fixes in This Version
- Correctly reject declarations where a statement is required in C.
Fixes #GH92775

- ``__has_unique_object_representations`` correctly handles arrays of unknown bounds of
types by ensuring they are complete and instantiating them if needed. Fixes (#GH95311).

Bug Fixes to Compiler Builtins
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Expand Down
6 changes: 6 additions & 0 deletions clang/lib/AST/ASTContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2791,6 +2791,12 @@ bool ASTContext::hasUniqueObjectRepresentations(
return hasUniqueObjectRepresentations(getBaseElementType(Ty),
CheckIfTriviallyCopyable);

if (Ty->isVoidType())
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is not clear why we need this change as well.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the new !Ty->isIncompleteType() assertion below. Before void would go to the !isTriviallyCopyable path, this is just a more explicit way of handling __has_unique_object_representations(void). The assertion could also be assert(Ty->isVoidType() || !Ty->isIncompleteType()) to follow the spec better?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd prefer that, I think

return false;

assert(!Ty->isIncompleteType() && "hasUniqueObjectRepresentations should not "
"be called with an incomplete type");

// (9.1) - T is trivially copyable...
if (CheckIfTriviallyCopyable && !Ty.isTriviallyCopyableType(*this))
return false;
Expand Down
5 changes: 4 additions & 1 deletion clang/lib/Sema/SemaExprCXX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5149,6 +5149,10 @@ static bool CheckUnaryTypeTraitTypeCompleteness(Sema &S, TypeTrait UTT,
case UTT_HasTrivialCopy:
case UTT_HasTrivialDestructor:
case UTT_HasVirtualDestructor:
// has_unique_object_representations<T> when T is an array is defined in terms
// of has_unique_object_representations<remove_all_extents_t<T>>, so the base
// type needs to be complete even if the type is an incomplete array type.
case UTT_HasUniqueObjectRepresentations:
ArgTy = QualType(ArgTy->getBaseElementTypeUnsafe(), 0);
[[fallthrough]];

Expand All @@ -5157,7 +5161,6 @@ static bool CheckUnaryTypeTraitTypeCompleteness(Sema &S, TypeTrait UTT,
case UTT_IsDestructible:
case UTT_IsNothrowDestructible:
case UTT_IsTriviallyDestructible:
case UTT_HasUniqueObjectRepresentations:
if (ArgTy->isIncompleteArrayType() || ArgTy->isVoidType())
return true;

Expand Down
11 changes: 11 additions & 0 deletions clang/test/SemaCXX/type-traits.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3505,6 +3505,17 @@ static_assert(__has_unique_object_representations(_BitInt(8)), "BitInt:");
static_assert(!__has_unique_object_representations(_BitInt(127)), "BitInt:");
static_assert(__has_unique_object_representations(_BitInt(128)), "BitInt:");

namespace GH95311 {

template <int>
class Foo {
int x;
};
static_assert(__has_unique_object_representations(Foo<0>[]));
class Bar; // expected-note {{forward declaration of 'GH95311::Bar'}}
static_assert(__has_unique_object_representations(Bar[])); // expected-error {{incomplete type}}

}

namespace PR46209 {
// Foo has both a trivial assignment operator and a non-trivial one.
Expand Down
Loading