Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[clang-tidy] readability-redundant-member-init fails to account for explicit user-provided default constructors #134440

Open
connorsmacd-hh opened this issue Apr 4, 2025 · 1 comment

Comments

@connorsmacd-hh
Copy link

The readability-redundant-member-init check issues warnings on initializers even when the relevant default constructor is marked explicit and is user-provided.

Example code (godbolt here) with clang-tidy args -checks=-*,readability-redundant-member-init:

struct A
{
    explicit A() {}
};

struct B
{
    A a1 {}; // Compiles, but tidy detects a redundant member init
    A a2; // No warning from tidy, but does not compile
};

auto b = B{};

In the above example, clang-tidy flags the a1 line with:

<source>:8:10: warning: initializer for member 'a1' is redundant [readability-redundant-member-init]
    8 |     A a1 {}; // Compiles, but tidy detects a redundant member init

When I do what tidy wants in the a2 line, this fails to compile with:

<source>:12:12: error: chosen constructor is explicit in copy-initialization
   12 | auto b = B{};
      |            ^
<source>:3:14: note: explicit constructor declared here
    3 |     explicit A() {}
      |              ^
<source>:9:7: note: in implicit initialization of field 'a2' with omitted initializer
    9 |     A a2; // No warning from tidy, but does not compile
      |       ^
1 error generated.
Compiler returned: 1

Interestingly, clang-tidy no longer warns if the constructor is instead explicitly defaulted, i.e., explicit A() = default;.

For context, I encountered this issue when working with boost::circular_buffer's default constructor (docs here):

explicit circular_buffer(const allocator_type & alloc = allocator_type()) noexcept;

It seems to me that readability-redundant-member-init should ignore instances where the initializer is invoking an explicit default constructor. Is that correct or am I doing something wrong?

@llvmbot
Copy link
Member

llvmbot commented Apr 4, 2025

@llvm/issue-subscribers-clang-tidy

Author: Connor S. MacDonald (connorsmacd-hh)

The `readability-redundant-member-init` check issues warnings on initializers even when the relevant default constructor is **marked `explicit`** and is **user-provided**.

Example code (godbolt here) with clang-tidy args -checks=-*,readability-redundant-member-init:

struct A
{
    explicit A() {}
};

struct B
{
    A a1 {}; // Compiles, but tidy detects a redundant member init
    A a2; // No warning from tidy, but does not compile
};

auto b = B{};

In the above example, clang-tidy flags the a1 line with:

&lt;source&gt;:8:10: warning: initializer for member 'a1' is redundant [readability-redundant-member-init]
    8 |     A a1 {}; // Compiles, but tidy detects a redundant member init

When I do what tidy wants in the a2 line, this fails to compile with:

&lt;source&gt;:12:12: error: chosen constructor is explicit in copy-initialization
   12 | auto b = B{};
      |            ^
&lt;source&gt;:3:14: note: explicit constructor declared here
    3 |     explicit A() {}
      |              ^
&lt;source&gt;:9:7: note: in implicit initialization of field 'a2' with omitted initializer
    9 |     A a2; // No warning from tidy, but does not compile
      |       ^
1 error generated.
Compiler returned: 1

Interestingly, clang-tidy no longer warns if the constructor is instead explicitly defaulted, i.e., explicit A() = default;.

For context, I encountered this issue when working with boost::circular_buffer's default constructor (docs here):

explicit circular_buffer(const allocator_type &amp; alloc = allocator_type()) noexcept;

It seems to me that readability-redundant-member-init should ignore instances where the initializer is invoking an explicit default constructor. Is that correct or am I doing something wrong?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants