Skip to content

Commit b333edd

Browse files
authored
[clang] When checking for covariant return types, make sure the pointers or references are to *classes* (#111856)
https://eel.is/c++draft/class.virtual#8.1 This prevents overriding methods with non class return types that have less cv-qualification. Fixes: #111742
1 parent 87f1262 commit b333edd

File tree

3 files changed

+20
-1
lines changed

3 files changed

+20
-1
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,19 @@ C++ Specific Potentially Breaking Changes
9999
// Was error, now evaluates to false.
100100
constexpr bool b = f() == g();
101101
102+
- Clang will now correctly not consider pointers to non classes for covariance.
103+
104+
.. code-block:: c++
105+
106+
struct A {
107+
virtual const int *f() const;
108+
};
109+
struct B : A {
110+
// Return type has less cv-qualification but doesn't point to a class.
111+
// Error will be generated.
112+
int *f() const override;
113+
};
114+
102115
- The warning ``-Wdeprecated-literal-operator`` is now on by default, as this is
103116
something that WG21 has shown interest in removing from the language. The
104117
result is that anyone who is compiling with ``-Werror`` should see this

clang/lib/Sema/SemaDeclCXX.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18273,7 +18273,7 @@ bool Sema::CheckOverridingFunctionReturnType(const CXXMethodDecl *New,
1827318273
}
1827418274

1827518275
// The return types aren't either both pointers or references to a class type.
18276-
if (NewClassTy.isNull()) {
18276+
if (NewClassTy.isNull() || !NewClassTy->isStructureOrClassType()) {
1827718277
Diag(New->getLocation(),
1827818278
diag::err_different_return_type_for_overriding_virtual_function)
1827918279
<< New->getDeclName() << NewTy << OldTy

clang/test/SemaCXX/virtual-override.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,12 @@ struct b { };
1919

2020
class A {
2121
virtual a* f(); // expected-note{{overridden virtual function is here}}
22+
virtual int *g(); // expected-note{{overridden virtual function is here}}
2223
};
2324

2425
class B : A {
2526
virtual b* f(); // expected-error{{return type of virtual function 'f' is not covariant with the return type of the function it overrides ('b *' is not derived from 'a *')}}
27+
virtual char *g(); // expected-error{{virtual function 'g' has a different return type ('char *') than the function it overrides (which has return type 'int *')}}
2628
};
2729

2830
}
@@ -83,11 +85,15 @@ struct a { };
8385
class A {
8486
virtual const a* f();
8587
virtual a* g(); // expected-note{{overridden virtual function is here}}
88+
virtual const int* h(); // expected-note{{overridden virtual function is here}}
89+
virtual int* i(); // expected-note{{overridden virtual function is here}}
8690
};
8791

8892
class B : A {
8993
virtual a* f();
9094
virtual const a* g(); // expected-error{{return type of virtual function 'g' is not covariant with the return type of the function it overrides (class type 'const a *' is more qualified than class type 'a *'}}
95+
virtual int* h(); // expected-error{{virtual function 'h' has a different return type ('int *') than the function it overrides (which has return type 'const int *')}}
96+
virtual const int* i(); // expected-error{{virtual function 'i' has a different return type ('const int *') than the function it overrides (which has return type 'int *')}}
9197
};
9298

9399
}

0 commit comments

Comments
 (0)