From: Anders Carlsson Date: Thu, 31 Dec 2009 18:34:24 +0000 (+0000) Subject: Make sure that an overriding return type is complete before checking if it's covarian... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=be2e205add4c1f6375bb430e847b712a88581e46;p=clang 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 --- diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index a1c6f47067..41f8c4c356 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -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)">; diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index f8321132ff..d6aa240df4 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -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)) { diff --git a/test/SemaCXX/virtual-override.cpp b/test/SemaCXX/virtual-override.cpp index 503245dcfd..4fdac85040 100644 --- a/test/SemaCXX/virtual-override.cpp +++ b/test/SemaCXX/virtual-override.cpp @@ -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 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 *f(); // expected-note {{in instantiation of template class 'struct T9::b' requested here}} + }; +} + // PR5656 class X0 { virtual void f0(); @@ -150,3 +179,21 @@ void test3() { Bar3 b3i; // okay Bar3 b3f; // expected-error{{is an abstract class}} } + +// 5920 +namespace PR5920 { + class Base {}; + + template + class Derived : public Base {}; + + class Foo { + public: + virtual Base* Method(); + }; + + class Bar : public Foo { + public: + virtual Derived* Method(); + }; +}