From 483a491ed7eedd370035c619ee2a01b16ee4c463 Mon Sep 17 00:00:00 2001 From: rdb Date: Mon, 6 Nov 2017 19:51:49 +0100 Subject: [PATCH] interrogate: simplify coercion code This remove support for coercing non-ReferenceCounted types that are neither default-constructible nor move-assignable, but it turns out none of the classes we really need it for matches that. It further cuts down on the amount of code that is being generated to support coercion in cases where it makes absolutely no sense. --- dtool/src/cppparser/cppExtensionType.cxx | 8 + dtool/src/cppparser/cppExtensionType.h | 1 + dtool/src/cppparser/cppFunctionType.h | 2 + dtool/src/cppparser/cppInstance.cxx | 27 ++- dtool/src/cppparser/cppPointerType.cxx | 8 + dtool/src/cppparser/cppPointerType.h | 1 + dtool/src/cppparser/cppSimpleType.cxx | 8 + dtool/src/cppparser/cppSimpleType.h | 1 + dtool/src/cppparser/cppStructType.cxx | 176 ++++++++++++++++++ dtool/src/cppparser/cppStructType.h | 8 +- dtool/src/cppparser/cppType.cxx | 8 + dtool/src/cppparser/cppType.h | 1 + dtool/src/cppparser/cppTypedefType.cxx | 8 + dtool/src/cppparser/cppTypedefType.h | 1 + .../interfaceMakerPythonNative.cxx | 111 ++--------- dtool/src/interrogate/typeManager.cxx | 52 ------ dtool/src/interrogate/typeManager.h | 1 - dtool/src/parser-inc/iostream | 9 + panda/src/express/pointerToArray.h | 3 +- panda/src/pgraph/nodePathCollection.I | 7 - panda/src/pgraph/nodePathCollection.cxx | 24 --- panda/src/pgraph/nodePathCollection.h | 5 +- 22 files changed, 279 insertions(+), 191 deletions(-) diff --git a/dtool/src/cppparser/cppExtensionType.cxx b/dtool/src/cppparser/cppExtensionType.cxx index 8a0676883d..eba135eb64 100644 --- a/dtool/src/cppparser/cppExtensionType.cxx +++ b/dtool/src/cppparser/cppExtensionType.cxx @@ -131,6 +131,14 @@ is_copy_constructible() const { return (_type == T_enum || _type == T_enum_class || _type == T_enum_struct); } +/** + * Returns true if the type is copy-assignable. + */ +bool CPPExtensionType:: +is_copy_assignable() const { + return (_type == T_enum || _type == T_enum_class || _type == T_enum_struct); +} + /** * */ diff --git a/dtool/src/cppparser/cppExtensionType.h b/dtool/src/cppparser/cppExtensionType.h index 7f7bf15abf..dca9cf8cb3 100644 --- a/dtool/src/cppparser/cppExtensionType.h +++ b/dtool/src/cppparser/cppExtensionType.h @@ -52,6 +52,7 @@ public: virtual bool is_constructible(const CPPType *type) const; virtual bool is_default_constructible() const; virtual bool is_copy_constructible() const; + virtual bool is_copy_assignable() const; virtual CPPDeclaration *substitute_decl(SubstDecl &subst, CPPScope *current_scope, diff --git a/dtool/src/cppparser/cppFunctionType.h b/dtool/src/cppparser/cppFunctionType.h index a5a66976b0..b6bdff7ac6 100644 --- a/dtool/src/cppparser/cppFunctionType.h +++ b/dtool/src/cppparser/cppFunctionType.h @@ -43,6 +43,8 @@ public: F_volatile_method = 0x4000, F_lvalue_method = 0x8000, F_rvalue_method = 0x10000, + F_copy_assignment_operator = 0x20000, + F_move_assignment_operator = 0x40000, }; CPPFunctionType(CPPType *return_type, CPPParameterList *parameters, diff --git a/dtool/src/cppparser/cppInstance.cxx b/dtool/src/cppparser/cppInstance.cxx index 86768af511..0bfdcabde1 100644 --- a/dtool/src/cppparser/cppInstance.cxx +++ b/dtool/src/cppparser/cppInstance.cxx @@ -328,8 +328,8 @@ get_fully_scoped_name() const { /** * If this is a function type instance, checks whether the function name - * matches the class name (or ~name), and if so, flags it as a constructor (or - * destructor). + * matches the class name (or ~name), and if so, flags it as a constructor, + * destructor or assignment operator */ void CPPInstance:: check_for_constructor(CPPScope *current_scope, CPPScope *global_scope) { @@ -344,13 +344,16 @@ check_for_constructor(CPPScope *current_scope, CPPScope *global_scope) { string class_name = scope->get_local_name(); if (!method_name.empty() && !class_name.empty()) { - if (method_name == class_name) { + // Check either a constructor or assignment operator. + if (method_name == class_name || method_name == "operator =") { CPPType *void_type = CPPType::new_type (new CPPSimpleType(CPPSimpleType::T_void)); - int flags = func->_flags | CPPFunctionType::F_constructor; + int flags = func->_flags; + if (method_name == class_name) { + flags |= CPPFunctionType::F_constructor; + } - // Check if it might be a copy or move constructor. CPPParameterList *params = func->_parameters; if (params->_parameters.size() == 1 && !params->_includes_ellipsis) { CPPType *param_type = params->_parameters[0]->_type; @@ -360,10 +363,18 @@ check_for_constructor(CPPScope *current_scope, CPPScope *global_scope) { param_type = ref_type->_pointing_at->remove_cv(); if (class_name == param_type->get_simple_name()) { - if (ref_type->_value_category == CPPReferenceType::VC_rvalue) { - flags |= CPPFunctionType::F_move_constructor; + if (flags & CPPFunctionType::F_constructor) { + if (ref_type->_value_category == CPPReferenceType::VC_rvalue) { + flags |= CPPFunctionType::F_move_constructor; + } else { + flags |= CPPFunctionType::F_copy_constructor; + } } else { - flags |= CPPFunctionType::F_copy_constructor; + if (ref_type->_value_category == CPPReferenceType::VC_rvalue) { + flags |= CPPFunctionType::F_move_assignment_operator; + } else { + flags |= CPPFunctionType::F_copy_assignment_operator; + } } } } diff --git a/dtool/src/cppparser/cppPointerType.cxx b/dtool/src/cppparser/cppPointerType.cxx index 6fac65a6b1..4ae396e22d 100644 --- a/dtool/src/cppparser/cppPointerType.cxx +++ b/dtool/src/cppparser/cppPointerType.cxx @@ -177,6 +177,14 @@ is_copy_constructible() const { return true; } +/** + * Returns true if the type is copy-assignable. + */ +bool CPPPointerType:: +is_copy_assignable() const { + return true; +} + /** * This is a little more forgiving than is_equal(): it returns true if the * types appear to be referring to the same thing, even if they may have diff --git a/dtool/src/cppparser/cppPointerType.h b/dtool/src/cppparser/cppPointerType.h index 41aed4876b..3fce00b2f5 100644 --- a/dtool/src/cppparser/cppPointerType.h +++ b/dtool/src/cppparser/cppPointerType.h @@ -41,6 +41,7 @@ public: virtual bool is_constructible(const CPPType *other) const; virtual bool is_default_constructible() const; virtual bool is_copy_constructible() const; + virtual bool is_copy_assignable() const; virtual bool is_equivalent(const CPPType &other) const; virtual void output(ostream &out, int indent_level, CPPScope *scope, diff --git a/dtool/src/cppparser/cppSimpleType.cxx b/dtool/src/cppparser/cppSimpleType.cxx index 82d7735bdc..8107e7ee24 100644 --- a/dtool/src/cppparser/cppSimpleType.cxx +++ b/dtool/src/cppparser/cppSimpleType.cxx @@ -103,6 +103,14 @@ is_copy_constructible() const { return (_type != T_void); } +/** + * Returns true if the type is copy-assignable. + */ +bool CPPSimpleType:: +is_copy_assignable() const { + return (_type != T_void); +} + /** * Returns true if the type is destructible. */ diff --git a/dtool/src/cppparser/cppSimpleType.h b/dtool/src/cppparser/cppSimpleType.h index 8adb254a1b..850353e9eb 100644 --- a/dtool/src/cppparser/cppSimpleType.h +++ b/dtool/src/cppparser/cppSimpleType.h @@ -75,6 +75,7 @@ public: virtual bool is_constructible(const CPPType *type) const; virtual bool is_default_constructible() const; virtual bool is_copy_constructible() const; + virtual bool is_copy_assignable() const; virtual bool is_destructible() const; virtual bool is_parameter_expr() const; diff --git a/dtool/src/cppparser/cppStructType.cxx b/dtool/src/cppparser/cppStructType.cxx index afb03dd463..fda8feaa2b 100644 --- a/dtool/src/cppparser/cppStructType.cxx +++ b/dtool/src/cppparser/cppStructType.cxx @@ -435,6 +435,17 @@ is_copy_constructible() const { return is_copy_constructible(V_public); } +/** + * Returns true if the type is copy-assignable. + */ +bool CPPStructType:: +is_copy_assignable() const { + if (is_abstract()) { + return false; + } + return is_copy_assignable(V_public); +} + /** * Returns true if the type is destructible. */ @@ -606,6 +617,97 @@ is_move_constructible(CPPVisibility min_vis) const { return is_copy_constructible(min_vis); } +/** + * Returns true if the type is copy-assignable, without checking whether the + * class is abstract. + */ +bool CPPStructType:: +is_copy_assignable(CPPVisibility min_vis) const { + CPPInstance *assignment_operator = get_copy_assignment_operator(); + if (assignment_operator != (CPPInstance *)NULL) { + // It has a copy assignment operator. + if (assignment_operator->_vis > min_vis) { + // Inaccessible copy assignment operator. + return false; + } + + if (assignment_operator->_storage_class & CPPInstance::SC_deleted) { + // Deleted copy assignment operator. + return false; + } + + // NB: if it's defaulted, it may still be deleted. + if ((assignment_operator->_storage_class & CPPInstance::SC_defaulted) == 0) { + return true; + } + } + + // Implicit copy assignment operator. Check if the implicit or defaulted + // copy assignment operator is deleted. + if (!assignment_operator && (get_move_constructor() || get_move_assignment_operator())) { + // It's not explicitly defaulted, and there is a move constructor or move + // assignment operator, so the implicitly-declared one is deleted. + return false; + } + + Derivation::const_iterator di; + for (di = _derivation.begin(); di != _derivation.end(); ++di) { + CPPStructType *base = (*di)._base->as_struct_type(); + if (base != NULL) { + if (!base->is_copy_assignable(V_protected)) { + return false; + } + } + } + + // Make sure all members are assignable. + CPPScope::Variables::const_iterator vi; + for (vi = _scope->_variables.begin(); vi != _scope->_variables.end(); ++vi) { + CPPInstance *instance = (*vi).second; + assert(instance != NULL); + + if (instance->_storage_class & CPPInstance::SC_static) { + // Static members don't count. + continue; + } + + if (!instance->_type->is_copy_assignable()) { + // Const or reference member, can't do it. + return false; + } + } + + return true; +} + +/** + * Returns true if the type is move-assignable. + */ +bool CPPStructType:: +is_move_assignable(CPPVisibility min_vis) const { + CPPInstance *assignment_operator = get_move_assignment_operator(); + if (assignment_operator != (CPPInstance *)NULL) { + // It has a user-declared move assignment_operator. + if (assignment_operator->_vis > min_vis) { + // Inaccessible move assignment_operator. + return false; + } + + if (assignment_operator->_storage_class & CPPInstance::SC_deleted) { + // It is deleted. + return false; + } + + if (is_abstract()) { + return false; + } + + return true; + } + + return is_copy_assignable(min_vis); +} + /** * Returns true if the type is destructible. */ @@ -886,6 +988,80 @@ get_move_constructor() const { return (CPPInstance *)NULL; } +/** + * Returns the assignment operator defined for the struct type, if any, or + * NULL if no assignment operator is found. + */ +CPPFunctionGroup *CPPStructType:: +get_assignment_operator() const { + // Just look for the function with the name "operator =" + CPPScope::Functions::const_iterator fi; + fi = _scope->_functions.find("operator ="); + if (fi != _scope->_functions.end()) { + return fi->second; + } else { + return (CPPFunctionGroup *)NULL; + } +} + +/** + * Returns the copy assignment operator defined for the struct type, or NULL + * if no user-declared copy assignment operator exists. + */ +CPPInstance *CPPStructType:: +get_copy_assignment_operator() const { + CPPFunctionGroup *fgroup = get_assignment_operator(); + if (fgroup == (CPPFunctionGroup *)NULL) { + return (CPPInstance *)NULL; + } + + CPPFunctionGroup::Instances::const_iterator ii; + for (ii = fgroup->_instances.begin(); + ii != fgroup->_instances.end(); + ++ii) { + CPPInstance *inst = (*ii); + assert(inst->_type != (CPPType *)NULL); + + CPPFunctionType *ftype = inst->_type->as_function_type(); + assert(ftype != (CPPFunctionType *)NULL); + + if ((ftype->_flags & CPPFunctionType::F_copy_assignment_operator) != 0) { + return inst; + } + } + + return (CPPInstance *)NULL; +} + +/** + * Returns the move assignment operator defined for the struct type, or NULL + * if no user-declared move assignment operator exists. + */ +CPPInstance *CPPStructType:: +get_move_assignment_operator() const { + CPPFunctionGroup *fgroup = get_assignment_operator(); + if (fgroup == (CPPFunctionGroup *)NULL) { + return (CPPInstance *)NULL; + } + + CPPFunctionGroup::Instances::const_iterator ii; + for (ii = fgroup->_instances.begin(); + ii != fgroup->_instances.end(); + ++ii) { + CPPInstance *inst = (*ii); + assert(inst->_type != (CPPType *)NULL); + + CPPFunctionType *ftype = inst->_type->as_function_type(); + assert(ftype != (CPPFunctionType *)NULL); + + if ((ftype->_flags & CPPFunctionType::F_move_assignment_operator) != 0) { + return inst; + } + } + + return (CPPInstance *)NULL; +} + /** * Returns the destructor defined for the struct type, if any, or NULL if no * user-declared destructor is found. diff --git a/dtool/src/cppparser/cppStructType.h b/dtool/src/cppparser/cppStructType.h index 585c7476b2..9da8777a6c 100644 --- a/dtool/src/cppparser/cppStructType.h +++ b/dtool/src/cppparser/cppStructType.h @@ -56,10 +56,13 @@ public: virtual bool is_constructible(const CPPType *arg_type) const; virtual bool is_default_constructible() const; virtual bool is_copy_constructible() const; + virtual bool is_copy_assignable() const; virtual bool is_destructible() const; bool is_default_constructible(CPPVisibility min_vis) const; bool is_copy_constructible(CPPVisibility min_vis) const; - bool is_move_constructible(CPPVisibility min_vis) const; + bool is_move_constructible(CPPVisibility min_vis = V_public) const; + bool is_copy_assignable(CPPVisibility min_vis) const; + bool is_move_assignable(CPPVisibility min_vis = V_public) const; bool is_destructible(CPPVisibility min_vis) const; virtual bool is_convertible_to(const CPPType *other) const; @@ -69,6 +72,9 @@ public: CPPInstance *get_default_constructor() const; CPPInstance *get_copy_constructor() const; CPPInstance *get_move_constructor() const; + CPPFunctionGroup *get_assignment_operator() const; + CPPInstance *get_copy_assignment_operator() const; + CPPInstance *get_move_assignment_operator() const; CPPInstance *get_destructor() const; virtual CPPDeclaration * diff --git a/dtool/src/cppparser/cppType.cxx b/dtool/src/cppparser/cppType.cxx index 801c571add..af3f511da4 100644 --- a/dtool/src/cppparser/cppType.cxx +++ b/dtool/src/cppparser/cppType.cxx @@ -110,6 +110,14 @@ is_copy_constructible() const { return false; } +/** + * Returns true if the type is copy-assignable. + */ +bool CPPType:: +is_copy_assignable() const { + return false; +} + /** * Returns true if the type is destructible. */ diff --git a/dtool/src/cppparser/cppType.h b/dtool/src/cppparser/cppType.h index c709c475d6..a312f45d33 100644 --- a/dtool/src/cppparser/cppType.h +++ b/dtool/src/cppparser/cppType.h @@ -51,6 +51,7 @@ public: virtual bool is_constructible(const CPPType *type) const; virtual bool is_default_constructible() const; virtual bool is_copy_constructible() const; + virtual bool is_copy_assignable() const; virtual bool is_destructible() const; virtual bool is_parameter_expr() const; diff --git a/dtool/src/cppparser/cppTypedefType.cxx b/dtool/src/cppparser/cppTypedefType.cxx index 61c569760e..d965d5db48 100644 --- a/dtool/src/cppparser/cppTypedefType.cxx +++ b/dtool/src/cppparser/cppTypedefType.cxx @@ -205,6 +205,14 @@ is_copy_constructible() const { return _type->is_copy_constructible(); } +/** + * Returns true if the type is copy-assignable. + */ +bool CPPTypedefType:: +is_copy_assignable() const { + return _type->is_copy_assignable(); +} + /** * Returns true if the type is destructible. */ diff --git a/dtool/src/cppparser/cppTypedefType.h b/dtool/src/cppparser/cppTypedefType.h index 280033738d..04a9b05995 100644 --- a/dtool/src/cppparser/cppTypedefType.h +++ b/dtool/src/cppparser/cppTypedefType.h @@ -48,6 +48,7 @@ public: virtual bool is_constructible(const CPPType *type) const; virtual bool is_default_constructible() const; virtual bool is_copy_constructible() const; + virtual bool is_copy_assignable() const; virtual bool is_destructible() const; virtual bool is_fully_specified() const; diff --git a/dtool/src/interrogate/interfaceMakerPythonNative.cxx b/dtool/src/interrogate/interfaceMakerPythonNative.cxx index 575e6fc776..174afca658 100644 --- a/dtool/src/interrogate/interfaceMakerPythonNative.cxx +++ b/dtool/src/interrogate/interfaceMakerPythonNative.cxx @@ -855,31 +855,13 @@ write_prototypes(ostream &out_code, ostream *out_h) { << " return ((bool (*)(PyObject *, PT(" << class_name << ") &))Dtool_Ptr_" << safe_name << "->_Dtool_Coerce)(args, coerced);\n" << "}\n"; } - - } else if (TypeManager::is_trivial(type)) { + } else { out_code << "inline static " << class_name << " *Dtool_Coerce_" << safe_name << "(PyObject *args, " << class_name << " &coerced) {\n" << " nassertr(Dtool_Ptr_" << safe_name << " != NULL, NULL);\n" << " nassertr(Dtool_Ptr_" << safe_name << "->_Dtool_Coerce != NULL, NULL);\n" << " return ((" << class_name << " *(*)(PyObject *, " << class_name << " &))Dtool_Ptr_" << safe_name << "->_Dtool_Coerce)(args, coerced);\n" << "}\n"; - - } else { - out_code - << "inline static bool Dtool_ConstCoerce_" << safe_name << "(PyObject *args, " << class_name << " const *&coerced, bool &manage) {\n" - << " nassertr(Dtool_Ptr_" << safe_name << " != NULL, false);\n" - << " nassertr(Dtool_Ptr_" << safe_name << "->_Dtool_ConstCoerce != NULL, false);\n" - << " return ((bool (*)(PyObject *, " << class_name << " const *&, bool&))Dtool_Ptr_" << safe_name << "->_Dtool_ConstCoerce)(args, coerced, manage);\n" - << "}\n"; - - if (has_coerce > 1) { - out_code - << "inline static bool Dtool_Coerce_" << safe_name << "(PyObject *args, " << class_name << " *&coerced, bool &manage) {\n" - << " nassertr(Dtool_Ptr_" << safe_name << " != NULL, false);\n" - << " nassertr(Dtool_Ptr_" << safe_name << "->_Dtool_Coerce != NULL, false);\n" - << " return ((bool (*)(PyObject *, " << class_name << " *&, bool&))Dtool_Ptr_" << safe_name << "->_Dtool_Coerce)(args, coerced, manage);\n" - << "}\n"; - } } } out_code << "#else\n"; @@ -888,20 +870,12 @@ write_prototypes(ostream &out_code, ostream *out_h) { if (has_coerce > 0) { if (TypeManager::is_reference_count(type)) { - assert(!type->is_trivial()); out_code << "extern bool Dtool_ConstCoerce_" << safe_name << "(PyObject *args, CPT(" << class_name << ") &coerced);\n"; if (has_coerce > 1) { out_code << "extern bool Dtool_Coerce_" << safe_name << "(PyObject *args, PT(" << class_name << ") &coerced);\n"; } - - } else if (TypeManager::is_trivial(type)) { - out_code << "extern " << class_name << " *Dtool_Coerce_" << safe_name << "(PyObject *args, " << class_name << " &coerced);\n"; - } else { - out_code << "extern bool Dtool_ConstCoerce_" << safe_name << "(PyObject *args, " << class_name << " const *&coerced, bool &manage);\n"; - if (has_coerce > 1) { - out_code << "extern bool Dtool_Coerce_" << safe_name << "(PyObject *args, " << class_name << " *&coerced, bool &manage);\n"; - } + out_code << "extern " << class_name << " *Dtool_Coerce_" << safe_name << "(PyObject *args, " << class_name << " &coerced);\n"; } } out_code << "#endif\n"; @@ -1062,7 +1036,7 @@ write_class_details(ostream &out, Object *obj) { int has_coerce = has_coerce_constructor(cpptype->as_struct_type()); if (has_coerce > 0) { write_coerce_constructor(out, obj, true); - if (has_coerce > 1 && !TypeManager::is_trivial(obj->_itype._cpptype)) { + if (has_coerce > 1 && TypeManager::is_reference_count(obj->_itype._cpptype)) { write_coerce_constructor(out, obj, false); } } @@ -1182,20 +1156,12 @@ write_class_declarations(ostream &out, ostream *out_h, Object *obj) { int has_coerce = has_coerce_constructor(type->as_struct_type()); if (has_coerce > 0) { if (TypeManager::is_reference_count(type)) { - assert(!type->is_trivial()); out << "bool Dtool_ConstCoerce_" << class_name << "(PyObject *args, CPT(" << c_class_name << ") &coerced);\n"; if (has_coerce > 1) { out << "bool Dtool_Coerce_" << class_name << "(PyObject *args, PT(" << c_class_name << ") &coerced);\n"; } - - } else if (TypeManager::is_trivial(type)) { - out << "" << c_class_name << " *Dtool_Coerce_" << class_name << "(PyObject *args, " << c_class_name << " &coerced);\n"; - } else { - out << "bool Dtool_ConstCoerce_" << class_name << "(PyObject *args, " << c_class_name << " const *&coerced, bool &manage);\n"; - if (has_coerce > 1) { - out << "bool Dtool_Coerce_" << class_name << "(PyObject *args, " << c_class_name << " *&coerced, bool &manage);\n"; - } + out << "" << c_class_name << " *Dtool_Coerce_" << class_name << "(PyObject *args, " << c_class_name << " &coerced);\n"; } } @@ -3046,8 +3012,7 @@ write_module_class(ostream &out, Object *obj) { int has_coerce = has_coerce_constructor(obj->_itype._cpptype->as_struct_type()); if (has_coerce > 0) { - if (TypeManager::is_reference_count(obj->_itype._cpptype) || - !TypeManager::is_trivial(obj->_itype._cpptype)) { + if (TypeManager::is_reference_count(obj->_itype._cpptype)) { out << " (CoerceFunction)Dtool_ConstCoerce_" << ClassName << ",\n"; if (has_coerce > 1) { out << " (CoerceFunction)Dtool_Coerce_" << ClassName << ",\n"; @@ -3920,7 +3885,7 @@ write_coerce_constructor(ostream &out, Object *obj, bool is_const) { } return_flags |= RF_err_false; - } else if (TypeManager::is_trivial(obj->_itype._cpptype)) { + } else { out << cClassName << " *Dtool_Coerce_" << ClassName << "(PyObject *args, " << cClassName << " &coerced) {\n"; out << " " << cClassName << " *local_this;\n"; @@ -3934,26 +3899,6 @@ write_coerce_constructor(ostream &out, Object *obj, bool is_const) { out << " return local_this;\n"; return_flags |= RF_err_null; - - } else { - if (is_const) { - out << "bool Dtool_ConstCoerce_" << ClassName << "(PyObject *args, " << cClassName << " const *&coerced, bool &manage) {\n"; - } else { - out << "bool Dtool_Coerce_" << ClassName << "(PyObject *args, " << cClassName << " *&coerced, bool &manage) {\n"; - } - - out << " DTOOL_Call_ExtractThisPointerForType(args, &Dtool_" << ClassName << ", (void**)&coerced);\n"; - out << " if (coerced != NULL) {\n"; - if (!is_const) { - out << " if (!((Dtool_PyInstDef *)args)->_is_const) {\n"; - out << " // A non-const instance is required, which this is.\n"; - out << " return true;\n"; - out << " }\n"; - } else { - out << " return true;\n"; - } - - return_flags |= RF_err_false; } out << " }\n\n"; @@ -5498,8 +5443,8 @@ write_function_instance(ostream &out, FunctionRemap *remap, // actual PointerTo. This eliminates an unref()ref() pair. pexpr_string = "MOVE(" + param_name + "_this)"; - } else if (TypeManager::is_trivial(obj_type)) { - // This is a trivial type, such as TypeHandle or LVecBase4. + } else { + // This is a move-assignable type, such as TypeHandle or LVecBase4. obj_type->output_instance(extra_convert, param_name + "_local", &parser); extra_convert << ";\n"; @@ -5522,29 +5467,6 @@ write_function_instance(ostream &out, FunctionRemap *remap, coerce_call = "(" + param_name + "_this != NULL)"; pexpr_string = param_name + "_this"; - - } else { - // This is a bit less elegant: we use a bool to store whether we're - // supposed to clean up the reference afterward. - type->output_instance(extra_convert, param_name + "_this", &parser); - extra_convert - << default_expr << ";\n" - << "bool " << param_name << "_manage = false;\n"; - - if (TypeManager::is_const_pointer_or_ref(orig_type)) { - coerce_call = "Dtool_ConstCoerce_" + make_safe_name(class_name) + - "(" + param_name + ", " + param_name + "_this, " + param_name + "_manage)"; - } else { - coerce_call = "Dtool_Coerce_" + make_safe_name(class_name) + - "(" + param_name + ", " + param_name + "_this, " + param_name + "_manage)"; - } - - extra_cleanup - << "if (" << param_name << "_manage) {\n" - << " delete " << param_name << "_this;\n" - << "}\n"; - - pexpr_string = param_name + "_this"; } if (report_errors) { @@ -5848,7 +5770,7 @@ write_function_instance(ostream &out, FunctionRemap *remap, manage_return = remap->_return_value_needs_management; return_expr = "return_value"; - } else if ((return_flags & RF_coerced) != 0 && TypeManager::is_trivial(remap->_cpptype)) { + } else if ((return_flags & RF_coerced) != 0 && !TypeManager::is_reference_count(remap->_cpptype)) { // Another special case is the coerce constructor for a trivial type. We // don't want to invoke "operator new" unnecessarily. if (is_constructor && remap->_extension) { @@ -6152,13 +6074,8 @@ write_function_instance(ostream &out, FunctionRemap *remap, indent(out, indent_level) << "coerced = MOVE(" << return_expr << ");\n"; indent(out, indent_level) << "return true;\n"; - } else if (TypeManager::is_trivial(remap->_cpptype)) { - indent(out, indent_level) << "return &coerced;\n"; - } else { - indent(out, indent_level) << "coerced = " << return_expr << ";\n"; - indent(out, indent_level) << "manage = true;\n"; - indent(out, indent_level) << "return true;\n"; + indent(out, indent_level) << "return &coerced;\n"; } } else if (return_flags & RF_raise_keyerror) { @@ -7357,6 +7274,14 @@ has_coerce_constructor(CPPStructType *type) { return 0; } + // It is convenient to set default-constructability and move-assignability + // as requirement for non-reference-counted objects, since it simplifies the + // implementation and it holds for all classes we need it for. + if (!TypeManager::is_reference_count(type) && + (!type->is_default_constructible() || !type->is_move_assignable())) { + return 0; + } + CPPScope *scope = type->get_scope(); if (scope == NULL) { return 0; diff --git a/dtool/src/interrogate/typeManager.cxx b/dtool/src/interrogate/typeManager.cxx index 995f677cc6..1485c785ca 100644 --- a/dtool/src/interrogate/typeManager.cxx +++ b/dtool/src/interrogate/typeManager.cxx @@ -2517,55 +2517,3 @@ is_local(CPPType *source_type) { return false; */ } - -/** - * Returns true if the type is trivial (or trivial enough for our purposes). - */ -bool TypeManager:: -is_trivial(CPPType *source_type) { - switch (source_type->get_subtype()) { - case CPPDeclaration::ST_const: - return is_trivial(source_type->as_const_type()->_wrapped_around); - - case CPPDeclaration::ST_reference: - return false; - - case CPPDeclaration::ST_pointer: - return true; - - case CPPDeclaration::ST_simple: - return true; - - case CPPDeclaration::ST_typedef: - return is_trivial(source_type->as_typedef_type()->_type); - - default: - if (source_type->is_trivial() || is_handle(source_type)) { - return true; - } else { - // This is a bit of a hack. is_trivial() returns false for types that - // have an empty constructor (since we can't use =default yet). For the - // other classes, it's just convenient to consider them trivial even if - // they aren't, since they are simple enough. - string name = source_type->get_simple_name(); - return (name == "ButtonHandle" || name == "DatagramIterator" || - name == "BitMask" || name == "Filename" || name == "pixel" || - name == "NodePath" || name == "LoaderOptions" || - name == "PointerToArray" || name == "ConstPointerToArray" || - name == "PStatThread" || - (name.size() >= 6 && name.substr(0, 6) == "LPlane") || - (name.size() > 6 && name.substr(0, 6) == "LPoint") || - (name.size() > 7 && name.substr(0, 7) == "LVector") || - (name.size() > 7 && name.substr(0, 7) == "LMatrix") || - (name.size() > 8 && name.substr(0, 8) == "LVecBase") || - (name.size() >= 9 && name.substr(0, 9) == "LParabola") || - (name.size() >= 9 && name.substr(0, 9) == "LRotation") || - (name.size() >= 11 && name.substr(0, 11) == "LQuaternion") || - (name.size() >= 12 && name.substr(0, 12) == "LOrientation") || - (name.size() > 16 && name.substr(0, 16) == "UnalignedLMatrix") || - (name.size() > 17 && name.substr(0, 17) == "UnalignedLVecBase")); - } - } - - return false; -} diff --git a/dtool/src/interrogate/typeManager.h b/dtool/src/interrogate/typeManager.h index 97b4bd8158..65f192edf7 100644 --- a/dtool/src/interrogate/typeManager.h +++ b/dtool/src/interrogate/typeManager.h @@ -149,7 +149,6 @@ public: static bool is_exported(CPPType *type); static bool is_local(CPPType *type); - static bool is_trivial(CPPType *type); }; #endif diff --git a/dtool/src/parser-inc/iostream b/dtool/src/parser-inc/iostream index 6ba0763c44..170d1d03f9 100644 --- a/dtool/src/parser-inc/iostream +++ b/dtool/src/parser-inc/iostream @@ -88,6 +88,9 @@ __published: streampos tellp(); void seekp(streampos pos); void seekp(streamoff off, ios_base::seekdir dir); + +protected: + ostream(ostream &&); }; class istream : virtual public ios { __published: @@ -97,12 +100,18 @@ __published: streampos tellg(); void seekg(streampos pos); void seekg(streamoff off, ios_base::seekdir dir); + +protected: + istream(istream &&); }; class iostream : public istream, public ostream { __published: iostream(const iostream&) = delete; void flush(); + +protected: + iostream(iostream &&); }; class ofstream : public ostream { diff --git a/panda/src/express/pointerToArray.h b/panda/src/express/pointerToArray.h index b4458f17b8..e3dcc2f110 100644 --- a/panda/src/express/pointerToArray.h +++ b/panda/src/express/pointerToArray.h @@ -247,6 +247,8 @@ private: template class ConstPointerToArray : public PointerToArrayBase { public: + INLINE ConstPointerToArray(TypeHandle type_handle = get_type_handle(Element)); + // By hiding this template from interrogate, we would improve compile-time // speed and memory utilization. However, we do want to export a minimal // subset of this class. So we define just the exportable interface here. @@ -287,7 +289,6 @@ PUBLISHED: typedef TYPENAME pvector::difference_type difference_type; typedef TYPENAME pvector::size_type size_type; - INLINE ConstPointerToArray(TypeHandle type_handle = get_type_handle(Element)); INLINE ConstPointerToArray(const Element *begin, const Element *end, TypeHandle type_handle = get_type_handle(Element)); INLINE ConstPointerToArray(const PointerToArray ©); INLINE ConstPointerToArray(const ConstPointerToArray ©); diff --git a/panda/src/pgraph/nodePathCollection.I b/panda/src/pgraph/nodePathCollection.I index 6c7b5df2d6..1ea730f4ab 100644 --- a/panda/src/pgraph/nodePathCollection.I +++ b/panda/src/pgraph/nodePathCollection.I @@ -11,13 +11,6 @@ * @date 2002-03-06 */ -/** - * - */ -INLINE NodePathCollection:: -~NodePathCollection() { -} - /** * Appends the other list onto the end of this one. */ diff --git a/panda/src/pgraph/nodePathCollection.cxx b/panda/src/pgraph/nodePathCollection.cxx index a2310b9e99..40efb80192 100644 --- a/panda/src/pgraph/nodePathCollection.cxx +++ b/panda/src/pgraph/nodePathCollection.cxx @@ -19,30 +19,6 @@ #include "colorAttrib.h" #include "indent.h" -/** - * - */ -NodePathCollection:: -NodePathCollection() { -} - -/** - * - */ -NodePathCollection:: -NodePathCollection(const NodePathCollection ©) : - _node_paths(copy._node_paths) -{ -} - -/** - * - */ -void NodePathCollection:: -operator = (const NodePathCollection ©) { - _node_paths = copy._node_paths; -} - /** * Adds a new NodePath to the collection. */ diff --git a/panda/src/pgraph/nodePathCollection.h b/panda/src/pgraph/nodePathCollection.h index 1d1ba9bd1f..9eb0c1ce90 100644 --- a/panda/src/pgraph/nodePathCollection.h +++ b/panda/src/pgraph/nodePathCollection.h @@ -25,10 +25,7 @@ */ class EXPCL_PANDA_PGRAPH NodePathCollection { PUBLISHED: - NodePathCollection(); - NodePathCollection(const NodePathCollection ©); - void operator = (const NodePathCollection ©); - INLINE ~NodePathCollection(); + NodePathCollection() DEFAULT_CTOR; #ifdef HAVE_PYTHON EXTENSION(NodePathCollection(PyObject *self, PyObject *sequence));