Skip to content

Commit 3292ce0

Browse files
authored
[Clang] fix overload resolution for object parameters with top-level cv-qualifiers in member functions (llvm#110435)
Fixes llvm#100394
1 parent 9f24c14 commit 3292ce0

File tree

3 files changed

+48
-10
lines changed

3 files changed

+48
-10
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -512,6 +512,7 @@ Bug Fixes to C++ Support
512512
and undeclared templates. (#GH107047, #GH49093)
513513
- Clang no longer crashes when a lambda contains an invalid block declaration that contains an unexpanded
514514
parameter pack. (#GH109148)
515+
- Fixed overload handling for object parameters with top-level cv-qualifiers in explicit member functions (#GH100394)
515516

516517
Bug Fixes to AST Handling
517518
^^^^^^^^^^^^^^^^^^^^^^^^^

clang/lib/Sema/SemaOverload.cpp

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1422,8 +1422,12 @@ static bool IsOverloadOrOverrideImpl(Sema &SemaRef, FunctionDecl *New,
14221422
// the implicit object parameter are of the same type.
14231423

14241424
auto NormalizeQualifiers = [&](const CXXMethodDecl *M, Qualifiers Q) {
1425-
if (M->isExplicitObjectMemberFunction())
1425+
if (M->isExplicitObjectMemberFunction()) {
1426+
auto ThisType = M->getFunctionObjectParameterReferenceType();
1427+
if (ThisType.isConstQualified())
1428+
Q.removeConst();
14261429
return Q;
1430+
}
14271431

14281432
// We do not allow overloading based off of '__restrict'.
14291433
Q.removeRestrict();
@@ -1439,14 +1443,23 @@ static bool IsOverloadOrOverrideImpl(Sema &SemaRef, FunctionDecl *New,
14391443
return Q;
14401444
};
14411445

1442-
auto CompareType = [&](QualType Base, QualType D) {
1443-
auto BS = Base.getNonReferenceType().getCanonicalType().split();
1446+
auto AreQualifiersEqual = [&](SplitQualType BS, SplitQualType DS) {
14441447
BS.Quals = NormalizeQualifiers(OldMethod, BS.Quals);
1448+
DS.Quals = NormalizeQualifiers(NewMethod, DS.Quals);
1449+
1450+
if (OldMethod->isExplicitObjectMemberFunction()) {
1451+
BS.Quals.removeVolatile();
1452+
DS.Quals.removeVolatile();
1453+
}
14451454

1455+
return BS.Quals == DS.Quals;
1456+
};
1457+
1458+
auto CompareType = [&](QualType Base, QualType D) {
1459+
auto BS = Base.getNonReferenceType().getCanonicalType().split();
14461460
auto DS = D.getNonReferenceType().getCanonicalType().split();
1447-
DS.Quals = NormalizeQualifiers(NewMethod, DS.Quals);
14481461

1449-
if (BS.Quals != DS.Quals)
1462+
if (!AreQualifiersEqual(BS, DS))
14501463
return false;
14511464

14521465
if (OldMethod->isImplicitObjectMemberFunction() &&

clang/test/SemaCXX/cxx2b-deducing-this.cpp

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -142,8 +142,8 @@ struct Corresponding {
142142
void d(this Corresponding&&);
143143
void d(this const Corresponding&);
144144
void d(this const int&);
145-
void d(this const int);
146-
void d(this int);
145+
void d(this const int); // expected-note {{previous declaration is here}}
146+
void d(this int); // expected-error {{class member cannot be redeclared}}
147147

148148
void e(this const Corresponding&&); // expected-note {{here}}
149149
void e() const &&; // expected-error{{cannot be redeclared}}
@@ -171,9 +171,8 @@ struct CorrespondingTpl {
171171
void d(this Corresponding&&);
172172
void d(this const Corresponding&);
173173
void d(this const int&);
174-
void d(this const int);
175-
void d(this int);
176-
174+
void d(this const int); // expected-note {{previous declaration is here}}
175+
void d(this int); // expected-error {{class member cannot be redeclared}}
177176
void e(this const CorrespondingTpl&&); // expected-note {{here}}
178177
void e() const &&; // expected-error{{cannot be redeclared}}
179178
};
@@ -1073,3 +1072,28 @@ int main() {
10731072
return foo[]; // expected-error {{no viable overloaded operator[] for type 'Foo'}}
10741073
}
10751074
}
1075+
1076+
namespace GH100394 {
1077+
struct C1 {
1078+
void f(this const C1);
1079+
void f() const; // ok
1080+
};
1081+
1082+
struct C2 {
1083+
void f(this const C2); // expected-note {{previous declaration is here}}
1084+
void f(this volatile C2); // expected-error {{class member cannot be redeclared}} \
1085+
// expected-warning {{volatile-qualified parameter type 'volatile C2' is deprecated}}
1086+
};
1087+
1088+
struct C3 {
1089+
void f(this volatile C3); // expected-note {{previous declaration is here}} \
1090+
// expected-warning {{volatile-qualified parameter type 'volatile C3' is deprecated}}
1091+
void f(this const C3); // expected-error {{class member cannot be redeclared}}
1092+
};
1093+
1094+
struct C4 {
1095+
void f(this const C4); // expected-note {{previous declaration is here}}
1096+
void f(this const volatile C4); // expected-error {{class member cannot be redeclared}} \
1097+
// expected-warning {{volatile-qualified parameter type 'const volatile C4' is deprecated}}
1098+
};
1099+
}

0 commit comments

Comments
 (0)