Skip to content

Commit e458a6b

Browse files
committed
[clang] Fix overload resolution ranking of inherited constructors
Take parameter types of candidate constructors into account when deciding whether to apply the tiebreaker.
1 parent 7fa104e commit e458a6b

File tree

3 files changed

+25
-9
lines changed

3 files changed

+25
-9
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -358,6 +358,9 @@ Bug Fixes to C++ Support
358358
- Fixed a Clang regression in C++20 mode where unresolved dependent call expressions were created inside non-dependent contexts (#GH122892)
359359
- Clang now emits the ``-Wunused-variable`` warning when some structured bindings are unused
360360
and the ``[[maybe_unused]]`` attribute is not applied. (#GH125810)
361+
- Overload resolution tiebreaker for inherited constructors is now only
362+
applied if their parameters have the same type, as required by the C++
363+
standard. (#GH121331)
361364

362365
Bug Fixes to AST Handling
363366
^^^^^^^^^^^^^^^^^^^^^^^^^

clang/lib/Sema/SemaOverload.cpp

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
#include "llvm/ADT/ScopeExit.h"
4141
#include "llvm/ADT/SmallPtrSet.h"
4242
#include "llvm/ADT/SmallVector.h"
43+
#include "llvm/Support/Casting.h"
4344
#include <algorithm>
4445
#include <cassert>
4546
#include <cstddef>
@@ -10724,15 +10725,13 @@ bool clang::isBetterOverloadCandidate(
1072410725
// -- F1 is a constructor for a class D, F2 is a constructor for a base
1072510726
// class B of D, and for all arguments the corresponding parameters of
1072610727
// F1 and F2 have the same type.
10727-
// FIXME: Implement the "all parameters have the same type" check.
10728-
bool Cand1IsInherited =
10729-
isa_and_nonnull<ConstructorUsingShadowDecl>(Cand1.FoundDecl.getDecl());
10730-
bool Cand2IsInherited =
10731-
isa_and_nonnull<ConstructorUsingShadowDecl>(Cand2.FoundDecl.getDecl());
10732-
if (Cand1IsInherited != Cand2IsInherited)
10733-
return Cand2IsInherited;
10734-
else if (Cand1IsInherited) {
10735-
assert(Cand2IsInherited);
10728+
if (isa_and_nonnull<CXXConstructorDecl>(Cand1.Function) &&
10729+
isa_and_nonnull<CXXConstructorDecl>(Cand2.Function) &&
10730+
llvm::equal(Cand1.Function->parameters().take_front(NumArgs),
10731+
Cand2.Function->parameters().take_front(NumArgs),
10732+
[&](ParmVarDecl *P1, ParmVarDecl *P2) {
10733+
return S.Context.hasSameUnqualifiedType(P1->getType(), P2->getType());
10734+
})) {
1073610735
auto *Cand1Class = cast<CXXRecordDecl>(Cand1.Function->getDeclContext());
1073710736
auto *Cand2Class = cast<CXXRecordDecl>(Cand2.Function->getDeclContext());
1073810737
if (Cand1Class->isDerivedFrom(Cand2Class))

clang/test/CXX/drs/cwg22xx.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,20 @@ B b;
169169
// since-cxx11-error@-1 {{call to implicitly-deleted default constructor of 'B'}}
170170
// since-cxx11-note@#cwg2273-B {{default constructor of 'B' is implicitly deleted because base class 'A' has a deleted default constructor}}
171171
// since-cxx11-note@#cwg2273-A {{'A' has been explicitly marked deleted here}}
172+
173+
struct X {
174+
X(float); // since-cxx11-note {{candidate inherited constructor}}
175+
X(void*, int = 0) = delete;
176+
};
177+
178+
struct Y : X {
179+
using X::X; // since-cxx11-note {{constructor from base class 'X' inherited here}}
180+
Y(double); // since-cxx11-note {{candidate constructor}}
181+
Y(void* const, long = 1);
182+
};
183+
184+
Y y = 1; // since-cxx11-error {{conversion from 'int' to 'Y' is ambiguous}}
185+
Y z = nullptr;
172186
#endif
173187
} // namespace cwg2273
174188

0 commit comments

Comments
 (0)