https://github.com/flash1729 created https://github.com/llvm/llvm-project/pull/212768
`__has_unique_object_representations(_Atomic(int))` returns false even though `_Atomic(int)` has the same object representation as `int`. Atomic types were never handled: they fail the trivial-copyability check up front (they aren't scalar types), and `_Atomic T` has been on the FIXME list at the end of the function since the original implementation. This is also the root cause of the false positive pinned in the `bugprone-suspicious-memory-comparison` tests since [D89651](https://reviews.llvm.org/D89651). Handle `AtomicType` explicitly: `_Atomic(T)` has unique object representations iff `T` does and the atomic's size wasn't rounded up to a power of two (see `getTypeInfo`), since the rounding bytes are padding. The branch goes before the trivial-copyability check, which atomics always fail; triviality is judged on the value type instead. Adds trait asserts to `type-traits.cpp` and flips the tidy FIXME test to expect no diagnostic. This is groundwork for a follow-up PR adding a Sema warning for `memcmp` on types without unique object representations, so the known false positive needed fixing first. >From 8cebfe1aa29d466308528cccd539c38080a5029f Mon Sep 17 00:00:00 2001 From: flash1729 <[email protected]> Date: Wed, 29 Jul 2026 17:20:06 +0530 Subject: [PATCH] [clang] Handle _Atomic types in hasUniqueObjectRepresentations Atomic types aren't scalar, so the predicate rejected them before layout was checked and fell through to false. _Atomic(T) shares T's representation when sizes match; padding from size rounding makes it non-unique. Fixes the FIXME in bugprone-suspicious-memory-comparison (D89651). --- .../checkers/bugprone/suspicious-memory-comparison.c | 4 +--- clang/docs/ReleaseNotes.md | 6 ++++++ clang/lib/AST/ASTContext.cpp | 9 ++++++++- clang/test/SemaCXX/type-traits.cpp | 10 ++++++++++ 4 files changed, 25 insertions(+), 4 deletions(-) diff --git a/clang-tools-extra/test/clang-tidy/checkers/bugprone/suspicious-memory-comparison.c b/clang-tools-extra/test/clang-tidy/checkers/bugprone/suspicious-memory-comparison.c index d3ecffec9a781..1f8bd7bd9f1ad 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/bugprone/suspicious-memory-comparison.c +++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone/suspicious-memory-comparison.c @@ -286,9 +286,7 @@ struct AtomicMember { }; void Test_AtomicMember(void) { - // FIXME: this is a false positive as the list of objects with unique object - // representations is incomplete. + // _Atomic(int) has the same object representation as int: no warning. struct AtomicMember a, b; memcmp(&a, &b, sizeof(struct AtomicMember)); - // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: comparing object representation of type 'struct AtomicMember' which does not have a unique object representation; consider comparing the members of the object manually } diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md index 80e770a40838a..20b37f466b84f 100644 --- a/clang/docs/ReleaseNotes.md +++ b/clang/docs/ReleaseNotes.md @@ -327,6 +327,12 @@ features cannot lower the translation-unit ABI level; - Fixed a crash when classifying a call to a builtin with dependent arguments, such as when the call is used as an `auto` non-type template argument. +- `__has_unique_object_representations` now returns `true` for `_Atomic` types + whose object representation is identical to that of their value type, such + as `_Atomic(int)`. Atomic types whose size is rounded up to a power of two + (adding padding bits) continue to report `false`. This also fixes a false + positive in the `bugprone-suspicious-memory-comparison` clang-tidy check. + #### Bug Fixes to Attribute Support - The `counted_by`/`counted_by_or_null` diagnostic that rejects a pointer whose diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 2228811546c0f..6aea6cfcf25ca 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -3062,6 +3062,14 @@ bool ASTContext::hasUniqueObjectRepresentations( "hasUniqueObjectRepresentations should not be called with an " "incomplete type"); + // _Atomic(T) shares T's object representation unless its size was rounded + // up to a power of two, in which case the extra bytes are padding. Atomic + // types are never trivially copyable, so (9.1) is judged on the value type. + if (const auto *AT = Ty->getAs<AtomicType>()) + return getTypeSize(AT) == getTypeSize(AT->getValueType()) && + hasUniqueObjectRepresentations(AT->getValueType(), + CheckIfTriviallyCopyable); + // (9.1) - T is trivially copyable... if (CheckIfTriviallyCopyable && !Ty.isTriviallyCopyableType(*this)) return false; @@ -3102,7 +3110,6 @@ bool ASTContext::hasUniqueObjectRepresentations( // FIXME: More cases to handle here (list by rsmith): // vectors (careful about, eg, vector of 3 foo) // _Complex int and friends - // _Atomic T // Obj-C block pointers // Obj-C object pointers // and perhaps OpenCL's various builtin types (pipe, sampler_t, event_t, diff --git a/clang/test/SemaCXX/type-traits.cpp b/clang/test/SemaCXX/type-traits.cpp index ff74461308fb1..246da619fe046 100644 --- a/clang/test/SemaCXX/type-traits.cpp +++ b/clang/test/SemaCXX/type-traits.cpp @@ -3504,6 +3504,16 @@ static_assert(__has_unique_object_representations(const int *), "as are pointers static_assert(__has_unique_object_representations(volatile int *), "as are pointers"); static_assert(__has_unique_object_representations(const volatile int *), "as are pointers"); +static_assert(__has_unique_object_representations(_Atomic(int)), "layout-identical atomics are"); +static_assert(!__has_unique_object_representations(_Atomic(float)), "value type is not unique"); +struct AtomicReprThreeChars { char a, b, c; }; +static_assert(!__has_unique_object_representations(_Atomic(AtomicReprThreeChars)), + "atomic size rounded up to a power of two adds padding"); +struct AtomicReprMember { _Atomic(int) x; }; +static_assert(__has_unique_object_representations(AtomicReprMember), "atomic member, no padding"); +struct AtomicReprPadded { char c; _Atomic(int) x; }; +static_assert(!__has_unique_object_representations(AtomicReprPadded), "padding before atomic member"); + class C {}; using FP = int (*)(int); using PMF = int (C::*)(int); _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
