]> granicus.if.org Git - clang/commitdiff
Make sure that an overriding return type is complete before checking if it's covarian...
authorAnders Carlsson <andersca@mac.com>
Thu, 31 Dec 2009 18:34:24 +0000 (18:34 +0000)
committerAnders Carlsson <andersca@mac.com>
Thu, 31 Dec 2009 18:34:24 +0000 (18:34 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@92365 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DiagnosticSemaKinds.td
lib/Sema/SemaDeclCXX.cpp
test/SemaCXX/virtual-override.cpp

index a1c6f47067972f2bda9481a41092c69697d2b19f..41f8c4c35683e44f7ea64a3f7d5fd1be7f99b1db 100644 (file)
@@ -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)">;
index f8321132ff0ae3b2979ac553845abf568fc66a34..d6aa240df4c0542be9ed139ed47064b171fb107c 100644 (file)
@@ -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)) {
index 503245dcfd8c47699ef0c2cd22d285bf9a0985ae..4fdac85040be6fb50b68a344c028ea107312eb76 100644 (file)
@@ -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();
+  };
+}