This is an archive of the discontinued LLVM Phabricator instance.

[Clang] Support qualified name as member designator in offsetof
Needs ReviewPublic

Authored by yichi170 on Aug 5 2023, 11:07 PM.

Details

Reviewers
aaron.ballman
Group Reviewers
Restricted Project
Summary

Diff Detail

Event Timeline

yichi170 created this revision.Aug 5 2023, 11:07 PM
Herald added a project: Restricted Project. · View Herald TranscriptAug 5 2023, 11:07 PM
yichi170 requested review of this revision.Aug 5 2023, 11:07 PM
Herald added a project: Restricted Project. · View Herald TranscriptAug 5 2023, 11:07 PM
Herald added a subscriber: cfe-commits. · View Herald Transcript
Endill added reviewers: Restricted Project, aaron.ballman.Aug 5 2023, 11:28 PM
yichi170 edited the summary of this revision. (Show Details)Aug 5 2023, 11:30 PM

You're missing tests.

clang/lib/Sema/SemaExpr.cpp
16700–16701

Thanks a lot for working on this. Can you add tests (to clang/test/SemaCXX/offsetof.cpp)?
The change will also need an entry in clang/docs/ReleaseNotes.rst , in the "C++ Language Changes" section

yichi170 updated this revision to Diff 547542.EditedAug 6 2023, 3:50 AM

I updated the test! Please check it out!
Should I update which subsection in "C++ Language Changes"?

yichi170 added inline comments.Aug 6 2023, 4:09 AM
clang/lib/Sema/SemaExpr.cpp
16700–16701

I'll fix it along with the ReleaseNotes.

Fznamznon added inline comments.
clang/test/Sema/offsetof.c
79 ↗(On Diff #547542)

It probably makes sense to also add a test with static member of a class, like Aaron mentioned in GitHub - https://github.com/llvm/llvm-project/issues/64154#issuecomment-1653468938 .

yichi170 updated this revision to Diff 547703.Aug 7 2023, 3:50 AM

updated ReleaseNotes and applied suggestions. The related issue #63443 is still not fixed.

yichi170 added inline comments.Aug 7 2023, 4:23 AM
clang/test/Sema/offsetof.c
79 ↗(On Diff #547542)

Hi @Fznamznon, I found that clang and clang++ output different errors with the following test.

struct X2 { int a; static int static_a; };
int x4[__builtin_offsetof(struct X2, X2::static_a) == 0 ? 1 : -1];
// expected-error{{no member named 'static_a'}}

C doesn't allow to have a static member in the struct, so is there any way to write the correct comment to make the test pass?

cor3ntin added inline comments.Aug 7 2023, 5:37 AM
clang/test/Sema/offsetof.c
79 ↗(On Diff #547542)

the tests should be in test/SemaCXX/offsetof.cpp, where you can use C++

yichi170 updated this revision to Diff 547764.Aug 7 2023, 6:46 AM
yichi170 marked an inline comment as not done.

updated test in test/SemaCXX/offsetof.cpp

Thank you for working on this!

clang/docs/ReleaseNotes.rst
59

You should also link to https://github.com/llvm/llvm-project/issues/64154 here to tie it back to a bug report.

clang/include/clang/Sema/Sema.h
6037–6038

I think we should combine isBrackets and isQualifier since a component can't be both at the same time anyway. e.g.,

enum {
  Brackets,   // U.E is valid
  Identifier, // U.IdentInfo is valid
  Qualifier,  // Nothing in U is valid
} Kind;
clang/test/Sema/offsetof.c
77–79 ↗(On Diff #547764)

Neither of these should be valid in C -- there is no way to name subobjects in C like there is in C++.

clang/test/SemaCXX/offsetof.cpp
104

It'd be good to add the int x2[__builtin_offsetof(struct X2, X2::a) == 0 ? 1 : -1]; test here from the C test.

yichi170 updated this revision to Diff 548632.Aug 9 2023, 8:14 AM
yichi170 marked 4 inline comments as done.

Applied the suggestions. Thanks for giving me feedback!

cor3ntin added inline comments.Aug 9 2023, 8:42 AM
clang/include/clang/Sema/Sema.h
6037–6038

This are not the best names.

ArrayElement, Subobject, NestedNameQualifier

Are probably more descriptive.

aaron.ballman added inline comments.Aug 9 2023, 8:43 AM
clang/docs/ReleaseNotes.rst
59
clang/lib/Parse/ParseExpr.cpp
2646–2651

I think this is slightly more clear.

clang/test/SemaCXX/offsetof.cpp
106

There's one more test I'd like to see:

struct S {
  int Foo;
};

template <typename Ty>
void func() {
  static_assert(__builtin_offsetof(Ty, Ty::Foo) == 0, "");
}

void inst() {
  func<S>();
}
yichi170 marked an inline comment as done.Aug 9 2023, 9:22 AM
yichi170 added inline comments.
clang/docs/ReleaseNotes.rst
59
clang/test/SemaCXX/offsetof.cpp
106

It would get the compile error in the current patch, but I think it should be compiled without any error, right?

aaron.ballman added inline comments.Aug 9 2023, 9:26 AM
clang/test/SemaCXX/offsetof.cpp
106

Correct, that should be accepted: https://godbolt.org/z/1f6a9Yaxa

hubert.reinterpretcast added inline comments.
clang/test/SemaCXX/offsetof.cpp
104

Tests should include cases where the member is a direct member of a base class or an anonymous union therein (and named variously by the qualification with the base class name, the complete class name, an intermediate base class name, the base class name qualified with an intermediate base class, the base class name denoted using ::identity_t<Base>, etc.).

Additionally, there should be a diagnostic test case where the qualifier is for an unrelated identically-defined class in another namespace.

clang/test/SemaCXX/offsetof.cpp
106

Should expect this to pass too:

template <typename T>
struct Z {
  static_assert(!__builtin_offsetof(T, template Q<T>::x));
};

struct A {
  template <typename T> using Q = T;
  int x;
};

Z<A> za;
yichi170 added inline comments.Aug 10 2023, 7:21 AM
clang/test/SemaCXX/offsetof.cpp
106

Wow. Does it mean we cannot simply parse the identifier, ::, . and brackets in __builtin_offsetof?

Is there any code handling the nested qualifier that I can reference? I tried to modify the OffsetOfNode, which allows me to handle the basic template case but still failed on the nested case.

cor3ntin added inline comments.Aug 10 2023, 7:54 AM
clang/test/SemaCXX/offsetof.cpp
106

GCC seems to support that.

We probably want to call ParseOptionalCXXScopeSpecifier and store the NestedNameSpecifierLoc we'd get from it (and then parse the (sequence of) identifier(s) corresponding to the member) as we do now.

The documentation of https://gcc.gnu.org/onlinedocs/gcc-13.2.0/gcc/Offsetof.html#index-_005f_005fbuiltin_005foffsetof
seems inaccurate,

it seems to be

"__builtin_offsetof" "(" typename "," nested-name-specifier offsetof_member_designator ")"

Note that you will have to take care of transforming the nested name in TreeTransform and handle type dependencies. Let me know if you have further questions,
it's more involved than what you signed for. Sorry for not spotting that earlier (Thanks @hubert.reinterpretcast !)

yichi170 added inline comments.Aug 10 2023, 7:59 AM
clang/test/SemaCXX/offsetof.cpp
106

Thank you for all the help! I'll take a look at it!

cor3ntin added inline comments.Aug 19 2023, 6:01 AM
clang/test/SemaCXX/offsetof.cpp
106

I was wrong, we need another approach.

I think the grammar is actually

member-designator:
          qualified-id
          member-designator.qualified-id
          member-designator.qualified-id

IE, we should support https://godbolt.org/z/eEq8snMc8

Unfortunately, this looks like a much bigger change that we envisioned when we tagged this as a good first issue, to the extent I'm not sure what is actually the right design is would be.

For each component I imagine we want to store
NestedNameSpecifierLoc + DeclarationNameInfo

The parser would have to produce a CXXScopeSpec + UnqualifiedId pair for each component.

The expression is dependent if any of the component is type dependent,

OffsetOfNode would have to change, but i think we can get away
Only changing the identifier case (ie the dependent case)

yichi170 added inline comments.Aug 19 2023, 9:19 PM
clang/test/SemaCXX/offsetof.cpp
106

Would it be better for me to close this patch and submit a new one if I find out how to implement it? I hope others won't hesitate to contribute because I'm working on this. I don't want to cause any delays in the release plan!

Endill added a subscriber: Endill.Aug 20 2023, 12:11 AM
Endill added inline comments.
clang/test/SemaCXX/offsetof.cpp
106

Would it be better for me to close this patch and submit a new one if I find out how to implement it?

A possible approach is to follow the example of member reference expression in its dot form.

I hope others won't hesitate to contribute because I'm working on this. I don't want to cause any delays in the release plan!

No worries, 17 release has branched a month ago, so you don't have to feel stressed over that.