Make sure that an overriding return type is complete before checking if it's covariant. Fixes PR5920.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@92365 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Anders Carlsson 2009-12-31 18:34:24 +00:00
Родитель bba4d023de
Коммит be2e205add
3 изменённых файлов: 59 добавлений и 0 удалений

Просмотреть файл

@ -497,6 +497,9 @@ def err_covariant_return_ambiguous_derived_to_base_conv : Error<
def err_covariant_return_not_derived : Error<
"return type of virtual function %0 is not covariant with the return type of "
"the function it overrides (%1 is not derived from %2)">;
def err_covariant_return_incomplete : Error<
"return type of virtual function %0 is not covariant with the return type of "
"the function it overrides (%1 is incomplete)">;
def err_covariant_return_type_different_qualifications : Error<
"return type of virtual function %0 is not covariant with the return type of "
"the function it overrides (%1 has different qualifiers than %2)">;

Просмотреть файл

@ -5528,6 +5528,15 @@ bool Sema::CheckOverridingFunctionReturnType(const CXXMethodDecl *New,
return true;
}
// C++ [class.virtual]p6:
// If the return type of D::f differs from the return type of B::f, the
// class type in the return type of D::f shall be complete at the point of
// declaration of D::f or shall be the class type D.
if (RequireCompleteType(New->getLocation(), NewClassTy,
PDiag(diag::err_covariant_return_incomplete)
<< New->getDeclName()))
return true;
if (!Context.hasSameUnqualifiedType(NewClassTy, OldClassTy)) {
// Check if the new class derives from the old class.
if (!IsDerivedFrom(NewClassTy, OldClassTy)) {

Просмотреть файл

@ -104,6 +104,35 @@ namespace T7 {
};
}
namespace T8 {
struct a { };
struct b; // expected-note {{forward declaration of 'struct T8::b'}}
class A {
virtual a *f();
};
class B : A {
b* f(); // expected-error {{return type of virtual function 'f' is not covariant with the return type of the function it overrides ('struct T8::b' is incomplete)}}
};
}
namespace T9 {
struct a { };
template<typename T> struct b : a {
int a[sizeof(T) ? -1 : -1]; // expected-error {{array size is negative}}
};
class A {
virtual a *f();
};
class B : A {
virtual b<int> *f(); // expected-note {{in instantiation of template class 'struct T9::b<int>' requested here}}
};
}
// PR5656
class X0 {
virtual void f0();
@ -150,3 +179,21 @@ void test3() {
Bar3<int> b3i; // okay
Bar3<float> b3f; // expected-error{{is an abstract class}}
}
// 5920
namespace PR5920 {
class Base {};
template <typename T>
class Derived : public Base {};
class Foo {
public:
virtual Base* Method();
};
class Bar : public Foo {
public:
virtual Derived<int>* Method();
};
}