Skip to content

Commit 28e1e7e

Browse files
authored
Revert "[Clang] Do not treat Foo -> const Foo conversion sequences as perfect" (#149272)
Reverts #148613 Considering object argument conversion qualifications perfect leads to situations where we prefer a non-template const qualified function over a non-qualified template function, which is very wrong indeed. I explored solutions to work around that, but instead, we might want to go the GCC road and prefer the friend overload in the #147374 example, as this seems a lot more consistent and reliable
1 parent a78a0f8 commit 28e1e7e

File tree

3 files changed

+4
-49
lines changed

3 files changed

+4
-49
lines changed

clang/include/clang/Sema/Overload.h

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -350,11 +350,6 @@ class Sema;
350350
LLVM_PREFERRED_TYPE(bool)
351351
unsigned BindsToRvalue : 1;
352352

353-
/// Whether this was an identity conversion with qualification
354-
/// conversion for the implicit object argument.
355-
LLVM_PREFERRED_TYPE(bool)
356-
unsigned IsImplicitObjectArgumentQualificationConversion : 1;
357-
358353
/// Whether this binds an implicit object argument to a
359354
/// non-static member function without a ref-qualifier.
360355
LLVM_PREFERRED_TYPE(bool)
@@ -453,11 +448,11 @@ class Sema;
453448
#endif
454449
return true;
455450
}
451+
if (!C.hasSameType(getFromType(), getToType(2)))
452+
return false;
456453
if (BindsToRvalue && IsLvalueReference)
457454
return false;
458-
if (IsImplicitObjectArgumentQualificationConversion)
459-
return C.hasSameUnqualifiedType(getFromType(), getToType(2));
460-
return C.hasSameType(getFromType(), getToType(2));
455+
return true;
461456
}
462457

463458
ImplicitConversionRank getRank() const;

clang/lib/Sema/SemaOverload.cpp

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,6 @@ void StandardConversionSequence::setAsIdentityConversion() {
245245
IsLvalueReference = true;
246246
BindsToFunctionLvalue = false;
247247
BindsToRvalue = false;
248-
IsImplicitObjectArgumentQualificationConversion = false;
249248
BindsImplicitObjectArgumentWithoutRefQualifier = false;
250249
ObjCLifetimeConversionBinding = false;
251250
FromBracedInitList = false;
@@ -5318,7 +5317,6 @@ TryReferenceInit(Sema &S, Expr *Init, QualType DeclType,
53185317
ICS.Standard.DirectBinding = BindsDirectly;
53195318
ICS.Standard.IsLvalueReference = !isRValRef;
53205319
ICS.Standard.BindsToFunctionLvalue = T2->isFunctionType();
5321-
ICS.Standard.IsImplicitObjectArgumentQualificationConversion = false;
53225320
ICS.Standard.BindsToRvalue = InitCategory.isRValue();
53235321
ICS.Standard.BindsImplicitObjectArgumentWithoutRefQualifier = false;
53245322
ICS.Standard.ObjCLifetimeConversionBinding =
@@ -5498,7 +5496,6 @@ TryReferenceInit(Sema &S, Expr *Init, QualType DeclType,
54985496
ICS.Standard.IsLvalueReference = !isRValRef;
54995497
ICS.Standard.BindsToFunctionLvalue = false;
55005498
ICS.Standard.BindsToRvalue = true;
5501-
ICS.Standard.IsImplicitObjectArgumentQualificationConversion = false;
55025499
ICS.Standard.BindsImplicitObjectArgumentWithoutRefQualifier = false;
55035500
ICS.Standard.ObjCLifetimeConversionBinding = false;
55045501
} else if (ICS.isUserDefined()) {
@@ -5521,8 +5518,6 @@ TryReferenceInit(Sema &S, Expr *Init, QualType DeclType,
55215518
ICS.UserDefined.After.IsLvalueReference = !isRValRef;
55225519
ICS.UserDefined.After.BindsToFunctionLvalue = false;
55235520
ICS.UserDefined.After.BindsToRvalue = !LValRefType;
5524-
ICS.UserDefined.After.IsImplicitObjectArgumentQualificationConversion =
5525-
false;
55265521
ICS.UserDefined.After.BindsImplicitObjectArgumentWithoutRefQualifier = false;
55275522
ICS.UserDefined.After.ObjCLifetimeConversionBinding = false;
55285523
ICS.UserDefined.After.FromBracedInitList = false;
@@ -5807,7 +5802,6 @@ TryListConversion(Sema &S, InitListExpr *From, QualType ToType,
58075802
StandardConversionSequence &SCS = Result.isStandard() ? Result.Standard :
58085803
Result.UserDefined.After;
58095804
SCS.ReferenceBinding = true;
5810-
SCS.IsImplicitObjectArgumentQualificationConversion = false;
58115805
SCS.IsLvalueReference = ToType->isLValueReferenceType();
58125806
SCS.BindsToRvalue = true;
58135807
SCS.BindsToFunctionLvalue = false;
@@ -6005,12 +5999,8 @@ static ImplicitConversionSequence TryObjectArgumentInitialization(
60055999
// affects the conversion rank.
60066000
QualType ClassTypeCanon = S.Context.getCanonicalType(ClassType);
60076001
ImplicitConversionKind SecondKind;
6008-
bool IsQualificationConversion = false;
6009-
if (ImplicitParamType.getCanonicalType() == FromTypeCanon) {
6002+
if (ClassTypeCanon == FromTypeCanon.getLocalUnqualifiedType()) {
60106003
SecondKind = ICK_Identity;
6011-
} else if (ClassTypeCanon == FromTypeCanon.getLocalUnqualifiedType()) {
6012-
SecondKind = ICK_Identity;
6013-
IsQualificationConversion = true;
60146004
} else if (S.IsDerivedFrom(Loc, FromType, ClassType)) {
60156005
SecondKind = ICK_Derived_To_Base;
60166006
} else if (!Method->isExplicitObjectMemberFunction()) {
@@ -6051,8 +6041,6 @@ static ImplicitConversionSequence TryObjectArgumentInitialization(
60516041
ICS.Standard.setFromType(FromType);
60526042
ICS.Standard.setAllToTypes(ImplicitParamType);
60536043
ICS.Standard.ReferenceBinding = true;
6054-
ICS.Standard.IsImplicitObjectArgumentQualificationConversion =
6055-
IsQualificationConversion;
60566044
ICS.Standard.DirectBinding = true;
60576045
ICS.Standard.IsLvalueReference = Method->getRefQualifier() != RQ_RValue;
60586046
ICS.Standard.BindsToFunctionLvalue = false;

clang/test/SemaCXX/overload-resolution-deferred-templates.cpp

Lines changed: 0 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -283,31 +283,3 @@ void f() {
283283
}
284284

285285
#endif
286-
287-
namespace GH147374 {
288-
289-
struct String {};
290-
template <typename T> void operator+(T, String &&) = delete;
291-
292-
struct Bar {
293-
void operator+(String) const; // expected-note {{candidate function}}
294-
friend void operator+(Bar, String) {}; // expected-note {{candidate function}}
295-
};
296-
297-
struct Baz {
298-
void operator+(String); // expected-note {{candidate function}}
299-
friend void operator+(Baz, String) {}; // expected-note {{candidate function}}
300-
};
301-
302-
void test() {
303-
Bar a;
304-
String b;
305-
a + b;
306-
//expected-error@-1 {{use of overloaded operator '+' is ambiguous (with operand types 'Bar' and 'String')}}
307-
308-
Baz z;
309-
z + b;
310-
//expected-error@-1 {{use of overloaded operator '+' is ambiguous (with operand types 'Baz' and 'String')}}
311-
}
312-
313-
}

0 commit comments

Comments
 (0)