Quuxplusone / LLVMBugzillaTest

0 stars 0 forks source link

Wrong initialization performed with empty initializer list #49528

Open Quuxplusone opened 3 years ago

Quuxplusone commented 3 years ago
Bugzilla Link PR50559
Status NEW
Importance P normal
Reported by Krzysztof Lewko (lewko.krzys@gmail.com)
Reported on 2021-06-02 03:17:51 -0700
Last modified on 2021-06-07 12:51:59 -0700
Version unspecified
Hardware PC Linux
CC blitzrakete@gmail.com, dgregor@apple.com, efriedma@quicinc.com, erik.pilkington@gmail.com, llvm-bugs@lists.llvm.org, predelnik@gmail.com, rajkumar.ananthu108@gmail.com, richard-llvm@metafoo.co.uk
Fixed by commit(s)
Attachments
Blocks
Blocked by
See also

Given code below:

struct S {
  S(std::initializer_list<double>); // #1
  S(std::initializer_list<int>);    // #2
  S();                              // #3
  // ...
};
int main() {
  S s1 = {}; // invoked #3
  s1 = {}; // should invoke #3 again, but tries to invoke #1 or #2 and call is ambigious.
}

Code is tried to be miscompiled, s1 should be value initialized due to empty initializer list assignment.

Quuxplusone commented 3 years ago

These are my observations: The statement:

S s1 = {};

the above statement is considered as initialization, this specific type is called list initialization. As you have not specified any value, this instance is called zero initialization or empty initialization(void). As a result it invokes #3(default constructor).

The statement:

s1 = {};

Here this is considered as an assignment, not as an initialization, so compiler is looking for overloaded assignment operator, as it not able to find an overloaded operator function inside the struct S, it is errors out saying it is not able to find overloaded operator = with operand types S and void

Refernce: https://www.learncpp.com/cpp-tutorial/variable-assignment-and-initialization/

So the compiler is right in this situation.

Please let me know if you have any questions, otherwise you can close this bug as Invalid.

Thanks, Rajkumar Ananthu.

Quuxplusone commented 3 years ago
(In reply to Rajkumar Ananthu from comment #1)
> as it not able to find an overloaded operator function inside the struct S

This isn't right.  clang is finding the implicit move assignment and copy
assignment operators.  It's just incorrectly complaining that they're ambiguous.

If you mess with one of the operators so it isn't viable (for example, declare
"S&& operator=(S&&) volatile;"), the code compiles.