diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 923f3d0a461649..e63282ca3b40d3 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -835,6 +835,9 @@ Bug Fixes in This Version - Fixed Clang from generating dangling StringRefs when deserializing Exprs & Stmts (#GH98667) +- ``__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 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 6c89e3890ae3e8..ccbb4baad68afb 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -2831,6 +2831,10 @@ bool ASTContext::hasUniqueObjectRepresentations( return hasUniqueObjectRepresentations(getBaseElementType(Ty), CheckIfTriviallyCopyable); + assert((Ty->isVoidType() || !Ty->isIncompleteType()) && + "hasUniqueObjectRepresentations should not be called with an " + "incomplete type"); + // (9.1) - T is trivially copyable... if (CheckIfTriviallyCopyable && !Ty.isTriviallyCopyableType(*this)) return false; diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index bef7da239e6e5e..14d1f395af90e3 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -5069,6 +5069,10 @@ static bool CheckUnaryTypeTraitTypeCompleteness(Sema &S, TypeTrait UTT, case UTT_HasTrivialCopy: case UTT_HasTrivialDestructor: case UTT_HasVirtualDestructor: + // has_unique_object_representations when T is an array is defined in terms + // of has_unique_object_representations>, 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]]; @@ -5077,7 +5081,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; diff --git a/clang/test/SemaCXX/type-traits.cpp b/clang/test/SemaCXX/type-traits.cpp index 7adbf4aad7afe0..23b07cac13eaf6 100644 --- a/clang/test/SemaCXX/type-traits.cpp +++ b/clang/test/SemaCXX/type-traits.cpp @@ -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 +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.