Skip to content

fix(folding): correct unique object rep checks [GH #327] - #326

Open
jakub-labenski wants to merge 1 commit into
edgcpp:mainfrom
jakub-labenski:has_unique_object_representations
Open

jakub-labenski wants to merge 1 commit into
edgcpp:mainfrom
jakub-labenski:has_unique_object_representations

Conversation

@jakub-labenski

@jakub-labenski jakub-labenski commented Oct 19, 2026 •

Copy link
Copy Markdown

Discussion: #290

Fix __has_unique_object_representations for several cases:

  • A base class with no direct nonstatic data members that inherits some (and is thus not empty) was treated as an empty base. Its size was counted as tail padding, making the trait incorrectly FALSE for derived classes. Use is_empty_class_type instead of checking for an empty field list.

  • Treat unnamed bit-fields of nonzero width as padding in Clang 17+ and g++ 13.1+ (also g++ 10.5, 11.4, 12.3 backports).

  • Restrict treating volatile-qualified non-class types as lacking unique object representations to g++ modes before version 10, and no longer apply it in Clang modes.

Add regression test has-unique-object-rep-inherited-base and update expectations for imported Clang type-traits and g++ has-unique-obj-representations3 tests.

Summary by CodeRabbit

  • Bug Fixes
    • Corrected __has_unique_object_representations results for types with inherited data members, unnamed bit-fields, and union bit-field padding.
    • Updated handling of volatile-qualified non-class types to match GCC version-specific behavior.
    • These corrections improve consistency across supported compiler modes and versions.

@nv-cmeerw nv-cmeerw left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Thats issue #327 now.

Comment thread src/Changes Outdated
A base class that declares no nonstatic data members of its own but inherits
some (and is therefore not empty) was treated as an empty base class. Its
size was then counted as tail padding, so the trait was incorrectly FALSE for
classes derived from it. For example, with --g++:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The issue is not actually gcc specific, but also applies to default/standard mode, so should just have an example with --c++11.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Entry has been updated: --g++ was change to --c++11 and an empty message was added to static_assert.

Comment thread src/Changes Outdated
This is now fixed. In addition, the following version-dependent behaviors
of g++ and Clang are now emulated:

- An unnamed bit-field of nonzero width is treated as padding (making the

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

What should the behavior for standard-mode be in this case?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

In standard mode, an unnamed bit-field of nonzero width is treated as padding, so __has_unique_object_representations(S) evaluates to false.

This was fixed in the latest update, along with new tests covering standard mode as well as GCC, Clang, and Microsoft emulation modes.

//remark:has_unique_object_representations with a base that has no direct fields
//type:fp
//options_all:--c++17
//options:--g++ --gnu_version=150100:--clang --clang_version=190000

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The test case should also test standard mode (and ideally, also MSVC modes).

Also need to have test coverage for the other code changes (unnamed bit-field, volatile qualifiers). Should also test each version condition from the source code.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

I've updated the tests to include standard mode and Microsoft emulation, and added the missing tests for the remaining changes.

Comment thread src/folding.c
field->source_corresp.assoc_info ==
(char *)get_unnamed_field_symbol()) {
/* An unnamed bit-field of non-zero width is padding. */
result = FALSE;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Does that need to be restricted to non-union class types?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Yes, it should. In a union, an unnamed bit-field overlaps the other members, so it shouldn't be treated as padding on its own. Instead, any bit-field narrower than the union is treated as padding, except in Clang and Microsoft modes (which ignore that case). This is now implemented and tests have been added.

@jakub-labenski
jakub-labenski force-pushed the has_unique_object_representations branch from c05bcb2 to 625b0c5 Compare October 21, 2026 08:11
@jakub-labenski

Copy link
Copy Markdown
Author

I'm not sure what the recommended practice is for syncing with main. I rebased the branch (and the pull request) onto main, then amended my commit to keep the git history clean.

Below is an AI-generated summary of the changes in my commit only:

  • Unnamed bit-fields: an unnamed bit-field of nonzero width now counts as padding by default, as the standard requires. In c05bcb2 this applied only to Clang 17+ and g++ 13.1+. The old behavior stays only in Clang modes before 17 and g++ modes before 13.1 (except the 10.5, 11.4 and 12.3 backports).
  • Unions: the unnamed bit-field rule no longer applies to unions; the existing union size check decides instead.
  • Microsoft mode: like Clang mode, it no longer treats a union bit-field narrower than the union as padding, matching MSVC.
  • Volatile check: the condition was rewritten as gpp_version_is(< 100000).
  • New tests: has-unique-object-rep-bit-field, -union-bit-field and -volatile. The -inherited-base test was tweaked, and expectations were updated.
  • src/Changes: the entry now carries the [GH #327] tag, and the examples use --c++11 with static_assert(..., "").

@jakub-labenski jakub-labenski changed the title fix(folding): correct unique object rep checks [] fix(folding): correct unique object rep checks [GH #327] Oct 21, 2026
@edgcpp-bot

Copy link
Copy Markdown
Collaborator

AcknowlEDG review results updated for 625b0c5a103e:

Comment thread src/Changes Outdated

This is now fixed. In addition:

- An unnamed bit-field of nonzero width is now treated as padding (making

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Can we remove "(making the result FALSE), as the standard requires" here. I don't think it really adds much information, and the Changes entry is already quite long.

Comment thread src/Changes Outdated
the result FALSE), as the standard requires. For example:

struct S { char a; char : 8; char b; };
// __has_unique_object_representations(S) is now FALSE.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Change that to a static_assert

Comment thread src/Changes Outdated
struct S { char a; char : 8; char b; };
// __has_unique_object_representations(S) is now FALSE.

The previous behavior (TRUE) is retained in g++ modes before 13.1

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think this should just be added to the previous sentence with ", except in ..."

Comment thread src/Changes Outdated
also does not treat it as padding, matching MSVC. For example:

union U { int x : 3; };
// __has_unique_object_representations(U) is now TRUE with

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Change to a static_assert and move the --microsoft to "For example, with --microsoft".

Comment thread src/Changes Outdated
not having unique object representations only in g++ modes before
version 10 (previously this was done for all g++ versions, including
Clang modes). In other modes the result is the same as for the
unqualified type, as the standard requires.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Maybe the second sentence can also be dropped?

//remark:has_unique_object_representations with unnamed bit-fields
//type:fp
//options_all:--c++11
//options:-DSTD_MODE:--g++ --gnu_version=90400 -DOLD_PAD:--g++ --gnu_version=100400 -DOLD_PAD:--g++ --gnu_version=100500:--g++ --gnu_version=120200 -DOLD_PAD:--g++ --gnu_version=120300:--g++ --gnu_version=150100:--clang --clang_version=160000 -DOLD_PAD:--clang --clang_version=170000:--microsoft

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Instead of adding macro definitions (STD_MODE, OLD_PAD), can we change the tests to check the GCC/Clang version macros directly. The idea here would be that the test case can be pasted into godbolt where it then should pass with any compiler selected (without having to adjust macro definitions).

@jakub-labenski
jakub-labenski force-pushed the has_unique_object_representations branch from 625b0c5 to f5ecadb Compare October 22, 2026 12:35
@edgcpp-bot

Copy link
Copy Markdown
Collaborator

AcknowlEDG review results updated for f5ecadb0bd7f:

CI other.

@edgcpp-bot

Copy link
Copy Markdown
Collaborator

AcknowlEDG review results updated for f5ecadb0bd7f:

CI success.

@daveedvdv-nvidia daveedvdv-nvidia left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Thanks for taking this on!

It looks good to me. I have a tiny stylistic nit — that's all.

Comment thread src/folding.c Outdated
field->is_bit_field && field->bit_size != 0 &&
unnamed_bit_field_is_padding() &&
field->source_corresp.assoc_info ==
(char*)get_unnamed_field_symbol()) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I'd rewrite that last bit as symbol_for(field) == get_unnamed_field_symbol)()) {

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Done.

Fix __has_unique_object_representations for several cases:

- A base class with no direct nonstatic data members that inherits
  some (and is thus not empty) was treated as an empty base. Its size
  was counted as tail padding, making the trait incorrectly FALSE for
  derived classes. Use is_empty_class_type instead of checking for an
  empty field list.

- Treat unnamed bit-fields of nonzero width in classes as padding, as
  the standard requires. Keep the old behavior only in Clang modes
  before 17 and g++ modes before 13.1 (except the 10.5, 11.4, and 12.3
  backports).

- Do not apply the unnamed bit-field rule to unions, where the bit-field
  overlaps the other members; the existing union size check decides.

- In Microsoft mode, as in Clang mode, do not treat a union bit-field
  narrower than the union as padding, matching MSVC.

- Restrict treating volatile-qualified non-class types as lacking
  unique object representations to g++ modes before version 10, and
  no longer apply it in Clang modes.

Add regression tests has-unique-object-rep-inherited-base,
has-unique-object-rep-bit-field, has-unique-object-rep-union-bit-field,
and has-unique-object-rep-volatile, covering standard, g++, Clang, and
Microsoft modes, and update expectations for imported Clang type-traits
and g++ has-unique-obj-representations3 tests.
@jakub-labenski
jakub-labenski force-pushed the has_unique_object_representations branch from f5ecadb to 4b5fe66 Compare October 23, 2026 06:26
@coderabbitai

coderabbitai Bot commented Oct 23, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: b6195b57-bae7-4eda-900e-78f75eac5108
📥 Commits

Reviewing files that changed from the base of the PR and between 992dedf and 4b5fe66.

⛔ Files ignored due to path filters: 1
  • tests/expectations/edg_x86_64/imported.log is excluded by !**/*.log
📒 Files selected for processing: 34
  • src/Changes
  • src/folding.c
  • tests/tests/imported/clang/cpp/SemaCXX/.type-traits.rto/default.1.1.txt
  • tests/tests/imported/clang/cpp/SemaCXX/.type-traits.rto/edg_x86_32.1.1.txt
  • tests/tests/imported/clang/cpp/SemaCXX/.type-traits.rto/edg_x86_32_cp.1.1.txt
  • tests/tests/imported/clang/cpp/SemaCXX/.type-traits.rto/edg_x86_64_cp.1.1.txt
  • tests/tests/imported/gnu/cpp/cpp1z/.has-unique-obj-representations3.rto/default.1.1.txt
  • tests/tests/regressions/.has-unique-object-rep-bit-field.rto/default.1.1.txt
  • tests/tests/regressions/.has-unique-object-rep-bit-field.rto/default.10.1.txt
  • tests/tests/regressions/.has-unique-object-rep-bit-field.rto/default.2.1.txt
  • tests/tests/regressions/.has-unique-object-rep-bit-field.rto/default.3.1.txt
  • tests/tests/regressions/.has-unique-object-rep-bit-field.rto/default.4.1.txt
  • tests/tests/regressions/.has-unique-object-rep-bit-field.rto/default.5.1.txt
  • tests/tests/regressions/.has-unique-object-rep-bit-field.rto/default.6.1.txt
  • tests/tests/regressions/.has-unique-object-rep-bit-field.rto/default.7.1.txt
  • tests/tests/regressions/.has-unique-object-rep-bit-field.rto/default.8.1.txt
  • tests/tests/regressions/.has-unique-object-rep-bit-field.rto/default.9.1.txt
  • tests/tests/regressions/.has-unique-object-rep-inherited-base.rto/default.1.1.txt
  • tests/tests/regressions/.has-unique-object-rep-inherited-base.rto/default.2.1.txt
  • tests/tests/regressions/.has-unique-object-rep-inherited-base.rto/default.3.1.txt
  • tests/tests/regressions/.has-unique-object-rep-inherited-base.rto/default.4.1.txt
  • tests/tests/regressions/.has-unique-object-rep-union-bit-field.rto/default.1.1.txt
  • tests/tests/regressions/.has-unique-object-rep-union-bit-field.rto/default.2.1.txt
  • tests/tests/regressions/.has-unique-object-rep-union-bit-field.rto/default.3.1.txt
  • tests/tests/regressions/.has-unique-object-rep-union-bit-field.rto/default.4.1.txt
  • tests/tests/regressions/.has-unique-object-rep-volatile.rto/default.1.1.txt
  • tests/tests/regressions/.has-unique-object-rep-volatile.rto/default.2.1.txt
  • tests/tests/regressions/.has-unique-object-rep-volatile.rto/default.3.1.txt
  • tests/tests/regressions/.has-unique-object-rep-volatile.rto/default.4.1.txt
  • tests/tests/regressions/.has-unique-object-rep-volatile.rto/default.5.1.txt
  • tests/tests/regressions/has-unique-object-rep-bit-field.sft.cpp
  • tests/tests/regressions/has-unique-object-rep-inherited-base.sft.cpp
  • tests/tests/regressions/has-unique-object-rep-union-bit-field.sft.cpp
  • tests/tests/regressions/has-unique-object-rep-volatile.sft.cpp
💤 Files with no reviewable changes: 1
  • tests/tests/imported/gnu/cpp/cpp1z/.has-unique-obj-representations3.rto/default.1.1.txt

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 9 remain after this review.

📝 Walkthrough

The __has_unique_object_representations implementation now applies compiler-version-specific rules to inherited bases, unnamed and union bit-fields, and volatile-qualified non-class types. Regression tests and expected compiler outputs are updated for these cases.

Changes: Unique Object Representation Trait

Layer / File(s) Summary
Inherited-base handling
src/folding.c, src/Changes, tests/tests/regressions/has-unique-object-rep-inherited-base.sft.cpp, tests/tests/regressions/.has-unique-object-rep-inherited-base.rto/*
Empty-base detection now uses class emptiness. Regression cases cover inherited members and padding, and the release notes describe the trait rule changes.
Unnamed and union bit-field rules
src/folding.c, tests/tests/regressions/has-unique-object-rep-bit-field.sft.cpp, tests/tests/regressions/has-unique-object-rep-union-bit-field.sft.cpp, tests/tests/regressions/.has-unique-object-rep-bit-field.rto/*, tests/tests/regressions/.has-unique-object-rep-union-bit-field.rto/*, tests/tests/imported/clang/cpp/SemaCXX/.type-traits.rto/*, tests/tests/imported/gnu/cpp/cpp1z/.has-unique-obj-representations3.rto/*
Unnamed nonzero-width bit-fields use compiler-version-specific padding rules. Union bit-field handling varies by compiler mode. Regression cases and expected compiler outputs reflect these rules.
Volatile-qualified non-class types
src/folding.c, tests/tests/regressions/has-unique-object-rep-volatile.sft.cpp, tests/tests/regressions/.has-unique-object-rep-volatile.rto/*, tests/tests/imported/clang/cpp/SemaCXX/.type-traits.rto/*
Volatile-qualified non-class types fail the check only in GCC modes before version 10. Regression assertions and expected compiler diagnostics reflect the updated results.

Priority: ➖ Normal

Estimated code review effort: 3 (Moderate) | ~20 minutes

Change: Bug fix

Possibly related issues

  • Issue 327 reports a failure for __has_unique_object_representations on a class with inherited members. This PR updates inherited-base handling in that trait.

Suggested reviewers: nv-cmeerw

Merge Risk: ⚪ Minimal · up to 4b5fe

The trait changes and corresponding test expectations show no established issue that would prevent merging after normal checks.

Security architecture risk: ⚪ Minimal · up to 4b5fe

The changes correct existing compile-time trait behavior. The reviewed implementation preserves its structural checks, and the flagged entrypoints are regression-test declarations rather than new production interfaces. No material security risk was identified.

Retained concerns
No architecture-level concerns identified.

Security review details

Security Blast Radius

  • inferred — The demonstrated exposure is changed compile-time classification of supplied types and propagation into the existing equality-comparability predicate. The inspected changes do not establish a new privileged operation or expanded service, tenant, credential, or data-store authority.

Trust Boundaries and Controls

  • observed — The three specifically flagged public-entrypoint ranges contain test type declarations, compiler-option directives, and static assertions. Their complete source does not introduce a production request handler, exported callable entrypoint, or authorization bypass.
Pre-merge checks: Passed 5
Check name Status Explanation
Description Check Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check Passed The title clearly identifies a folding fix for unique object representation checks, which matches the primary changes and regression tests.
Docstring Coverage Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 4…
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Full details: Docstring Coverage

Explanation

No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 4 files. (29 skipped: 28 unsupported, 1 too large.)

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Warning

⚠️ This pull request shows signs of AI-generated slop (description_diff_mismatch). It has been flagged by CodeRabbit slop detection and should be reviewed carefully.

Comment @coderabbitai help to get the list of available commands.

@edgcpp-bot

Copy link
Copy Markdown
Collaborator

AcknowlEDG review results updated for 4b5fe66b2ed0:

  • Test - Changes (updated)
  • Bench - C (no longer applies)
  • Bench - C++ (no longer applies)

CI other.

@jakub-labenski

Copy link
Copy Markdown
Author

Thanks @daveedvdv-nvidia and @nv-cmeerw for the review.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants