This is an archive of the discontinued LLVM Phabricator instance.

[clang-tidy] Fix wrong FixIt about union in cppcoreguidelines-pro-type-member-init
ClosedPublic

Authored by Sockke on Aug 19 2021, 5:52 AM.

Details

Summary

At most one variant member of a union may have a default member initializer. The case of anonymous records with multiple levels of nesting like the following also needs to meet this rule. The original logic is to horizontally obtain all the member variables in a record that need to be initialized and then filter to the variables that need to be fixed. Obviously, it is impossible to correctly initialize the desired variables according to the nesting relationship.

See Example 3 in class.union

union U {
  U() {}
  int x;  // int x{};
  union {
    int k;  // int k{};  <==  wrong fix
  };
  union {
    int z;  // int z{};  <== wrong fix
    int y;
  };
};

Diff Detail

Event Timeline

Sockke created this revision.Aug 19 2021, 5:52 AM
Sockke requested review of this revision.Aug 19 2021, 5:52 AM
Herald added a project: Restricted Project. · View Herald TranscriptAug 19 2021, 5:52 AM
Herald added a subscriber: cfe-commits. · View Herald Transcript
Sockke edited the summary of this revision. (Show Details)Aug 19 2021, 6:03 AM
MTC added inline comments.Aug 19 2021, 6:31 AM
clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.cpp
49

Can it be modified to the following form? Or further abstract filter into a parameter to make this function more general.

template <typename T, typename Func>
void forEachFieldWithFilter(const RecordDecl &Record, const T &Fields,
                            bool &AnyMemberHasInitPerUnion, Func &&Fn) {
  forEachField(Record, Fields, Fn);
  if (Record.isUnion() && AnyMemberHasInitPerUnion)
    break;
}
This comment was removed by Sockke.
clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.cpp
49

Can it be modified to the following form? Or further abstract filter into a parameter to make this function more general.

template <typename T, typename Func>
void forEachFieldWithFilter(const RecordDecl &Record, const T &Fields,
                            bool &AnyMemberHasInitPerUnion, Func &&Fn) {
  forEachField(Record, Fields, Fn);
  if (Record.isUnion() && AnyMemberHasInitPerUnion)
    break;
}

This does not seem to work, because the "AnyMemberHasInitPerUnion" needs to be passed along the call stack.

Any thoughts? : )

Any thoughts? : )

Sockke added a comment.Sep 2 2021, 8:41 AM

Hi, Could anyone please review this diff?

aaron.ballman added inline comments.Sep 2 2021, 2:38 PM
clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines-pro-type-member-init.cpp
526

Can you add a CHECK-FIXES-NOT that we're not adding the fix for this case?

529

Same here.

534

A related interesting test would be:

union U3 {
  U3() {}

  struct {
    int B;
  } b;
  int A;
};

I would expect A or b to need initialization for the union, and B to need initialization for the struct.

Sockke added inline comments.Sep 13 2021, 1:26 AM
clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines-pro-type-member-init.cpp
534

A related interesting test would be:

union U3 {
  U3() {}

  struct {
    int B;
  } b;
  int A;
};

I would expect A or b to need initialization for the union, and B to need initialization for the struct.

I apologize for the delay in responding. It seems to me that struct {}b has no user-defined constructor, so all members are initialized to their defaults, it is unnecessary to initialize B explicitly.

Hi, Could you please take some time to review this diff again? @aaron.ballman

aaron.ballman added inline comments.Sep 22 2021, 11:59 AM
clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.cpp
484

Given that we're touching this code, we might as well make clang-format happy with it (though I can't quite spot what it wants changed, so if it turns out to be a bad idea for some reason, I don't insist).

clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines-pro-type-member-init.cpp
526

I think you missed this request? Same for the one immediately below.

534

Okay, fair point!

Sockke updated this revision to Diff 374430.Sep 23 2021, 5:08 AM

Update!

clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.cpp
484

Given that we're touching this code, we might as well make clang-format happy with it (though I can't quite spot what it wants changed, so if it turns out to be a bad idea for some reason, I don't insist).

Yes, I have tried to format this code with clang-format but it does not work perfectly.

aaron.ballman accepted this revision.Sep 23 2021, 5:41 AM

LGTM!

clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.cpp
484

Then as-is is fine by me, thank you!

This revision is now accepted and ready to land.Sep 23 2021, 5:41 AM
This comment was removed by Sockke.

LGTM!

Thanks for your review! I don't have commit access, here is my information:
Name: liuke
Email: liuke.gehry@bytedance.com

LGTM!

Thanks for your review! I don't have commit access, here is my information:
Name: liuke
Email: liuke.gehry@bytedance.com

Thanks! I've commit on your behalf in e4902480f1e2f12f73c2b504e3d717536653dd7b.