浏览代码

properly detect need to upcast in single-inheritance cases

David Rose 22 年之前
父节点
当前提交
e3b7aa48f9

+ 6 - 1
dtool/src/cppparser/cppStructType.cxx

@@ -144,11 +144,16 @@ is_abstract() const {
 //               class).  It is sometimes useful to know whether a
 //               given virtual method represents the first time that
 //               particular method appears.
+//
+//               The return value is true if this class defines or
+//               inherits any virtual methods (and thus requires a
+//               virtual function pointer), or false otherwise.
 ////////////////////////////////////////////////////////////////////
-void CPPStructType::
+bool CPPStructType::
 check_virtual() {
   VFunctions funcs;
   get_virtual_funcs(funcs);
+  return !funcs.empty();
 }
 
 ////////////////////////////////////////////////////////////////////

+ 1 - 1
dtool/src/cppparser/cppStructType.h

@@ -48,7 +48,7 @@ public:
   CPPScope *get_scope() const;
 
   bool is_abstract() const;
-  void check_virtual();
+  bool check_virtual();
   virtual bool is_fully_specified() const;
   virtual bool is_incomplete() const;
 

+ 8 - 1
dtool/src/interrogate/interrogateBuilder.cxx

@@ -1863,7 +1863,7 @@ define_struct_type(InterrogateType &itype, CPPStructType *cpptype,
 
   cpptype = TypeManager::resolve_type(cpptype)->as_struct_type();
   assert(cpptype != (CPPStructType *)NULL);
-  cpptype->check_virtual();
+  bool has_virt_methods = cpptype->check_virtual();
 
   switch (cpptype->_type) {
   case CPPExtensionType::T_class:
@@ -1958,6 +1958,13 @@ define_struct_type(InterrogateType &itype, CPPStructType *cpptype,
           // requires a pointer change.  (For many compilers, this does
           // not require a pointer change.)
           generate_casts = true;
+
+        } else if (has_virt_methods && (base_type->as_struct_type() == (CPPStructType *)NULL || !base_type->as_struct_type()->check_virtual())) {
+          // Finally, if this class has virtual methods, but its
+          // parent doesn't, then we have to upcast (because this
+          // class will require space for a virtual function table
+          // pointer, while the parent class won't).
+          generate_casts = true;
         }
         
         if (generate_casts) {