Skip to content

[clang] When checking for covariant return types, make sure the pointers or references are to *classes* #111856

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Oct 16, 2024
13 changes: 13 additions & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,19 @@ C++ Specific Potentially Breaking Changes
// Was error, now evaluates to false.
constexpr bool b = f() == g();

- Clang will now correctly not consider pointers to non classes for covariance.

.. code-block:: c++

struct A {
virtual const int *f() const;
};
struct B : A {
// Return type has less cv-qualification but doesn't point to a class.
// Error will be generated.
int *f() const override;
};

- The warning ``-Wdeprecated-literal-operator`` is now on by default, as this is
something that WG21 has shown interest in removing from the language. The
result is that anyone who is compiling with ``-Werror`` should see this
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Sema/SemaDeclCXX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18273,7 +18273,7 @@ bool Sema::CheckOverridingFunctionReturnType(const CXXMethodDecl *New,
}

// The return types aren't either both pointers or references to a class type.
if (NewClassTy.isNull()) {
if (NewClassTy.isNull() || !NewClassTy->isStructureOrClassType()) {
Diag(New->getLocation(),
diag::err_different_return_type_for_overriding_virtual_function)
<< New->getDeclName() << NewTy << OldTy
Expand Down
6 changes: 6 additions & 0 deletions clang/test/SemaCXX/virtual-override.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,12 @@ struct b { };

class A {
virtual a* f(); // expected-note{{overridden virtual function is here}}
virtual int *g(); // expected-note{{overridden virtual function is here}}
};

class B : A {
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 *')}}
virtual char *g(); // expected-error{{virtual function 'g' has a different return type ('char *') than the function it overrides (which has return type 'int *')}}
};

}
Expand Down Expand Up @@ -83,11 +85,15 @@ struct a { };
class A {
virtual const a* f();
virtual a* g(); // expected-note{{overridden virtual function is here}}
virtual const int* h(); // expected-note{{overridden virtual function is here}}
virtual int* i(); // expected-note{{overridden virtual function is here}}
};

class B : A {
virtual a* f();
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 *'}}
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 *')}}
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 *')}}
};

}
Expand Down
Loading