From ca920ace894b454d160860ad9ea35c041e4dc821 Mon Sep 17 00:00:00 2001 From: David Rose Date: Tue, 30 Jan 2001 00:57:30 +0000 Subject: [PATCH] *** empty log message *** --- dtool/src/interrogate/interrogateBuilder.cxx | 2 +- dtool/src/interrogate/wrapperBuilder.cxx | 123 ++++++++++++++----- dtool/src/interrogate/wrapperBuilder.h | 1 + 3 files changed, 95 insertions(+), 31 deletions(-) diff --git a/dtool/src/interrogate/interrogateBuilder.cxx b/dtool/src/interrogate/interrogateBuilder.cxx index 6f5fb83050..3b2d14627a 100644 --- a/dtool/src/interrogate/interrogateBuilder.cxx +++ b/dtool/src/interrogate/interrogateBuilder.cxx @@ -1547,7 +1547,7 @@ get_wrapper(FunctionIndex function_index, WrapperBuilder *wbuilder, iwrapper._function = function_index; - // We do assume that two different libraries will not has to the + // We do assume that two different libraries will not hash to the // same name. This is pretty unlikely, although there could be big // problems if it ever happens. If it does, we'll probably need to // add an interface so the user can specify a hash offset on a diff --git a/dtool/src/interrogate/wrapperBuilder.cxx b/dtool/src/interrogate/wrapperBuilder.cxx index db87c25464..0eb36f1001 100644 --- a/dtool/src/interrogate/wrapperBuilder.cxx +++ b/dtool/src/interrogate/wrapperBuilder.cxx @@ -25,6 +25,7 @@ #include #include #include +#include #include //////////////////////////////////////////////////////////////////// @@ -144,6 +145,23 @@ set_function(CPPInstance *function, const string &description, param._remap = new ParameterRemapThis(_struct_type, is_const); _parameters.push_back(param); _has_this = true; + + // Also check the name of the function. If it's one of the + // assignment-style operators, flag it as such. + string fname = _function->get_simple_name(); + if (fname == "operator =" || + fname == "operator *=" || + fname == "operator /=" || + fname == "operator %=" || + fname == "operator +=" || + fname == "operator -=" || + fname == "operator |=" || + fname == "operator &=" || + fname == "operator ^=" || + fname == "operator <<=" || + fname == "operator >>=") { + _type = T_assignment_method; + } } const CPPParameterList::Parameters ¶ms = @@ -174,7 +192,9 @@ set_function(CPPInstance *function, const string &description, } if (_type == T_constructor) { - // Constructors are a special case. + // Constructors are a special case. These appear to return void + // as seen by the parser, but we know they actually return a new + // concrete instance. if (_struct_type == (CPPStructType *)NULL) { nout << "Method " << *_function << " has no struct type\n"; @@ -184,6 +204,20 @@ set_function(CPPInstance *function, const string &description, _void_return = false; } + } else if (_type == T_assignment_method) { + // Assignment-type methods are also a special case. We munge + // these to return *this, which is a semi-standard C++ convention + // anyway. We just enforce it. + + if (_struct_type == (CPPStructType *)NULL) { + nout << "Method " << *_function << " has no struct type\n"; + _is_valid = false; + } else { + CPPType *ref_type = CPPType::new_type(new CPPReferenceType(_struct_type)); + _return_type = make_remap(ref_type); + _void_return = false; + } + } else { // The normal case. CPPType *rtype = _ftype->_return_type->resolve_type(&parser, _scope); @@ -573,41 +607,70 @@ call_function(ostream &out, int indent_level, bool convert_result, return_expr = _return_type->get_return_expr(new_str); } + } else if (_type == T_constructor) { + // A special case for constructors. + return_expr = "new " + get_call_str(pexprs); + + } else if (_type == T_assignment_method) { + // Another special case for assignment operators. + indent(out, indent_level) + << get_call_str(pexprs) << ";\n"; + + string this_expr = get_parameter_expr(0, pexprs); + string ref_expr = "*" + this_expr; + + if (!convert_result) { + return_expr = ref_expr; + } else { + string new_str = + _return_type->prepare_return_expr(out, indent_level, ref_expr); + return_expr = _return_type->get_return_expr(new_str); + + // Now a simple special-case test. Often, we will have converted + // the reference-returning assignment operator to a pointer. In + // this case, we might inadventent generate code like "return + // &(*this)", when "return this" would do. We check for this here + // and undo it as a special case. + + // There's no real good reason to do this, other than that it + // feels more satisfying to a casual perusal of the generated + // code. It *is* conceivable that some broken compilers wouldn't + // like "&(*this)", though. + + if (return_expr == "&(" + ref_expr + ")" || + return_expr == "&" + ref_expr) { + return_expr = this_expr; + } + } + + } else if (_void_return) { + indent(out, indent_level) + << get_call_str(pexprs) << ";\n"; + } else { string call = get_call_str(pexprs); - // Now output that call. - if (_type == T_constructor) { - // A special case for constructors. - return_expr = "new " + call; - - } else if (_void_return) { - indent(out, indent_level) - << call << ";\n"; + if (!convert_result) { + return_expr = get_call_str(pexprs); } else { - if (!convert_result) { - return_expr = call; - + if (_return_type->return_value_should_be_simple()) { + // We have to assign the result to a temporary first; this makes + // it a bit easier on poor old VC++. + indent(out, indent_level); + _return_type->get_orig_type()->output_instance(out, "result", + &parser); + out << " = " << call << ";\n"; + + string new_str = + _return_type->prepare_return_expr(out, indent_level, "result"); + return_expr = _return_type->get_return_expr(new_str); + } else { - if (_return_type->return_value_should_be_simple()) { - // We have to assign the result to a temporary first; this makes - // it a bit easier on poor old VC++. - indent(out, indent_level); - _return_type->get_orig_type()->output_instance(out, "result", - &parser); - out << " = " << call << ";\n"; - - string new_str = - _return_type->prepare_return_expr(out, indent_level, "result"); - return_expr = _return_type->get_return_expr(new_str); - - } else { - // This should be simple enough that we can return it directly. - string new_str = - _return_type->prepare_return_expr(out, indent_level, call); - return_expr = _return_type->get_return_expr(new_str); - } + // This should be simple enough that we can return it directly. + string new_str = + _return_type->prepare_return_expr(out, indent_level, call); + return_expr = _return_type->get_return_expr(new_str); } } } diff --git a/dtool/src/interrogate/wrapperBuilder.h b/dtool/src/interrogate/wrapperBuilder.h index 09e853cd51..6173454a6f 100644 --- a/dtool/src/interrogate/wrapperBuilder.h +++ b/dtool/src/interrogate/wrapperBuilder.h @@ -40,6 +40,7 @@ public: T_constructor, T_destructor, T_typecast_method, + T_assignment_method, T_typecast, T_getter, T_setter