]> granicus.if.org Git - clang/commitdiff
[Sema] Incomplete types are OK for covariant returns
authorDavid Majnemer <david.majnemer@gmail.com>
Tue, 26 Jan 2016 01:37:01 +0000 (01:37 +0000)
committerDavid Majnemer <david.majnemer@gmail.com>
Tue, 26 Jan 2016 01:37:01 +0000 (01:37 +0000)
Per C++14 [class.virtual]p8, it is OK for the return type's class type
to be incomplete so long as the return type is the same between the base
and complete classes.

This fixes PR26297.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@258768 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaDeclCXX.cpp
test/SemaCXX/virtual-override.cpp

index 82d81a85fa90424b7e8a98d62f4f16eb24aa3270..fc1c2ec75f45872fb5e1d8a2aeea2606507491f5 100644 (file)
@@ -13020,19 +13020,20 @@ 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 (const RecordType *RT = NewClassTy->getAs<RecordType>()) {
-    if (!RT->isBeingDefined() &&
-        RequireCompleteType(New->getLocation(), NewClassTy, 
-                            diag::err_covariant_return_incomplete,
-                            New->getDeclName()))
-    return true;
-  }
-
   if (!Context.hasSameUnqualifiedType(NewClassTy, OldClassTy)) {
+    // C++14 [class.virtual]p8:
+    //   If the class type in the covariant return type of D::f differs from
+    //   that 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 (const RecordType *RT = NewClassTy->getAs<RecordType>()) {
+      if (!RT->isBeingDefined() &&
+          RequireCompleteType(New->getLocation(), NewClassTy,
+                              diag::err_covariant_return_incomplete,
+                              New->getDeclName()))
+        return true;
+    }
+
     // Check if the new class derives from the old class.
     if (!IsDerivedFrom(New->getLocation(), NewClassTy, OldClassTy)) {
       Diag(New->getLocation(), diag::err_covariant_return_not_derived)
index ec884f36323587b8d3ca9b1546fb90a480773ea6..42491178482e3dd84037332fc0811f524df89742 100644 (file)
@@ -289,3 +289,15 @@ namespace PR8168 {
     static void foo() {} // expected-error{{'static' member function 'foo' overrides a virtual function}}
   };
 }
+
+namespace PR26297 {
+struct Incomplete;
+
+struct Base {
+  virtual const Incomplete *meow() = 0;
+};
+
+struct Derived : Base {
+  virtual Incomplete *meow() override { return nullptr; }
+};
+}