Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members  

dtool/src/cppparser/cppStructType.cxx

Go to the documentation of this file.
00001 // Filename: cppStructType.cxx
00002 // Created by:  drose (19Oct99)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
00008 //
00009 // All use of this software is subject to the terms of the Panda 3d
00010 // Software license.  You should have received a copy of this license
00011 // along with this source code; you will also find a current copy of
00012 // the license at http://www.panda3d.org/license.txt .
00013 //
00014 // To contact the maintainers of this program write to
00015 // panda3d@yahoogroups.com .
00016 //
00017 ////////////////////////////////////////////////////////////////////
00018 
00019 
00020 #include "cppStructType.h"
00021 #include "cppTypedef.h"
00022 #include "cppScope.h"
00023 #include "cppTypeProxy.h"
00024 #include "cppTemplateScope.h"
00025 #include "cppFunctionGroup.h"
00026 #include "cppFunctionType.h"
00027 #include "cppTBDType.h"
00028 #include "indent.h"
00029 #include "cppParser.h"
00030 
00031 ////////////////////////////////////////////////////////////////////
00032 //     Function: CPPStructType::Base::output
00033 //       Access: Public
00034 //  Description:
00035 ////////////////////////////////////////////////////////////////////
00036 void CPPStructType::Base::
00037 output(ostream &out) const {
00038   if (_is_virtual) {
00039     out << "virtual ";
00040   }
00041   out << _vis << " " << *_base;
00042 }
00043 
00044 ////////////////////////////////////////////////////////////////////
00045 //     Function: CPPStructType::Constructor
00046 //       Access: Public
00047 //  Description:
00048 ////////////////////////////////////////////////////////////////////
00049 CPPStructType::
00050 CPPStructType(CPPStructType::Type type, CPPIdentifier *ident,
00051               CPPScope *current_scope, CPPScope *scope,
00052               const CPPFile &file) :
00053   CPPExtensionType(type, ident, current_scope, file),
00054   _scope(scope)
00055 {
00056   _subst_decl_recursive_protect = false;
00057   _incomplete = true;
00058 }
00059 
00060 ////////////////////////////////////////////////////////////////////
00061 //     Function: CPPStructType::Copy Constructor
00062 //       Access: Public
00063 //  Description:
00064 ////////////////////////////////////////////////////////////////////
00065 CPPStructType::
00066 CPPStructType(const CPPStructType &copy) :
00067   CPPExtensionType(copy),
00068   _scope(copy._scope),
00069   _incomplete(copy._incomplete),
00070   _derivation(copy._derivation)
00071 {
00072   _subst_decl_recursive_protect = false;
00073 }
00074 
00075 ////////////////////////////////////////////////////////////////////
00076 //     Function: CPPStructType::Copy Assignment Operator
00077 //       Access: Public
00078 //  Description:
00079 ////////////////////////////////////////////////////////////////////
00080 void CPPStructType::
00081 operator = (const CPPStructType &copy) {
00082   CPPExtensionType::operator = (copy);
00083   _scope = copy._scope;
00084   _incomplete = copy._incomplete;
00085   _derivation = copy._derivation;
00086 }
00087 
00088 ////////////////////////////////////////////////////////////////////
00089 //     Function: CPPStructType::append_derivation
00090 //       Access: Public
00091 //  Description: A handy function used while parsing to add a new base
00092 //               class to the list of classes (or structs) this class
00093 //               derives from.
00094 ////////////////////////////////////////////////////////////////////
00095 void CPPStructType::
00096 append_derivation(CPPType *base, CPPVisibility vis, bool is_virtual) {
00097   if (base != NULL) {
00098     Base b;
00099     b._base = base;
00100     b._vis = vis;
00101     b._is_virtual = is_virtual;
00102 
00103     _derivation.push_back(b);
00104   }
00105 }
00106 
00107 ////////////////////////////////////////////////////////////////////
00108 //     Function: CPPStructType::get_scope
00109 //       Access: Public
00110 //  Description:
00111 ////////////////////////////////////////////////////////////////////
00112 CPPScope *CPPStructType::
00113 get_scope() const {
00114   return _scope;
00115 }
00116 
00117 
00118 ////////////////////////////////////////////////////////////////////
00119 //     Function: CPPStructType::is_abstract
00120 //       Access: Public
00121 //  Description: Returns true if this struct declaration is abstract,
00122 //               e.g. it contains or inherits at least one method that
00123 //               is pure virtual.
00124 ////////////////////////////////////////////////////////////////////
00125 bool CPPStructType::
00126 is_abstract() const {
00127   VFunctions funcs;
00128   get_pure_virtual_funcs(funcs);
00129   return !funcs.empty();
00130 }
00131 
00132 ////////////////////////////////////////////////////////////////////
00133 //     Function: CPPStructType::check_virtual
00134 //       Access: Public
00135 //  Description: Ensures all functions are correctly marked with the
00136 //               "virtual" flag if they are truly virtual by virtue of
00137 //               inheritance, rather than simply being labeled
00138 //               virtual.
00139 //
00140 //               This also sets the CPPInstance::SC_inherited_virtual
00141 //               flags on those virtual methods that override a
00142 //               virtual method defined in a parent class (as opposed
00143 //               to those that appear for this first time in this
00144 //               class).  It is sometimes useful to know whether a
00145 //               given virtual method represents the first time that
00146 //               particular method appears.
00147 ////////////////////////////////////////////////////////////////////
00148 void CPPStructType::
00149 check_virtual() {
00150   VFunctions funcs;
00151   get_virtual_funcs(funcs);
00152 }
00153 
00154 ////////////////////////////////////////////////////////////////////
00155 //     Function: CPPStructType::is_fully_specified
00156 //       Access: Public, Virtual
00157 //  Description: Returns true if this declaration is an actual,
00158 //               factual declaration, or false if some part of the
00159 //               declaration depends on a template parameter which has
00160 //               not yet been instantiated.
00161 ////////////////////////////////////////////////////////////////////
00162 bool CPPStructType::
00163 is_fully_specified() const {
00164   if (_scope != NULL && !_scope->is_fully_specified()) {
00165     return false;
00166   }
00167   return CPPType::is_fully_specified();
00168 }
00169 
00170 ////////////////////////////////////////////////////////////////////
00171 //     Function: CPPStructType::is_incomplete
00172 //       Access: Public, Virtual
00173 //  Description: Returns true if the type has not yet been fully
00174 //               specified, false if it has.
00175 ////////////////////////////////////////////////////////////////////
00176 bool CPPStructType::
00177 is_incomplete() const {
00178   return _incomplete;
00179 }
00180 
00181 ////////////////////////////////////////////////////////////////////
00182 //     Function: CPPStructType::get_destructor
00183 //       Access: Public
00184 //  Description: Returns the destructor defined for the struct type,
00185 //               if any, or NULL if no destructor is found.
00186 ////////////////////////////////////////////////////////////////////
00187 CPPInstance *CPPStructType::
00188 get_destructor() const {
00189   // Iterate through all the functions that begin with '~' until we
00190   // find one that claims to be a destructor.  In theory, there should
00191   // only be one such function.
00192   CPPScope::Functions::const_iterator fi;
00193   fi = _scope->_functions.lower_bound("~");
00194 
00195   while (fi != _scope->_functions.end() &&
00196          (*fi).first[0] == '~') {
00197     CPPFunctionGroup *fgroup = (*fi).second;
00198     CPPFunctionGroup::Instances::const_iterator ii;
00199     for (ii = fgroup->_instances.begin();
00200          ii != fgroup->_instances.end();
00201          ++ii) {
00202       CPPInstance *inst = (*ii);
00203       assert(inst->_type != (CPPType *)NULL);
00204 
00205       CPPFunctionType *ftype = inst->_type->as_function_type();
00206       assert(ftype != (CPPFunctionType *)NULL);
00207 
00208       if ((ftype->_flags & CPPFunctionType::F_destructor) != 0) {
00209         return inst;
00210       }
00211     }
00212     ++fi;
00213   }
00214 
00215   return (CPPInstance *)NULL;
00216 }
00217 
00218 ////////////////////////////////////////////////////////////////////
00219 //     Function: CPPStructType::instantiate
00220 //       Access: Public, Virtual
00221 //  Description:
00222 ////////////////////////////////////////////////////////////////////
00223 CPPDeclaration *CPPStructType::
00224 instantiate(const CPPTemplateParameterList *actual_params,
00225             CPPScope *current_scope, CPPScope *global_scope,
00226             CPPPreprocessor *error_sink) const {
00227 
00228   // I *think* this assertion is no longer valid.  Who knows.
00229   //  assert(!_incomplete);
00230 
00231   if (_scope == NULL) {
00232     if (error_sink != NULL) {
00233       error_sink->warning("Ignoring template parameters for class " +
00234                           get_local_name());
00235     }
00236     return (CPPDeclaration *)this;
00237   }
00238 
00239   CPPScope *scope =
00240     _scope->instantiate(actual_params, current_scope, global_scope, error_sink);
00241 
00242   if (scope->get_struct_type()->get_scope() != scope) {
00243     // Hmm, this type seems to be not completely defined.  We must be
00244     // in the middle of recursively instantiating the scope.  Thus, we
00245     // don't yet know what its associated struct type will be.
00246 
00247     // Postpone the evaluation of this type.
00248     CPPIdentifier *ident = new CPPIdentifier(get_fully_scoped_name());
00249 
00250     return CPPType::new_type(new CPPTBDType(ident));
00251   }
00252 
00253   CPPType *result = scope->get_struct_type();
00254   result = CPPType::new_type(result);
00255   if (result != (CPPType *)this) {
00256     // This really means the method ought to be non-const.  But I'm
00257     // too lazy to propagate this change all the way back right now,
00258     // so this hack is here.
00259     ((CPPStructType *)this)->_instantiations.insert(result);
00260   }
00261   return result;
00262 }
00263 
00264 ////////////////////////////////////////////////////////////////////
00265 //     Function: CPPStructType::substitute_decl
00266 //       Access: Public, Virtual
00267 //  Description:
00268 ////////////////////////////////////////////////////////////////////
00269 CPPDeclaration *CPPStructType::
00270 substitute_decl(CPPDeclaration::SubstDecl &subst,
00271                 CPPScope *current_scope, CPPScope *global_scope) {
00272   SubstDecl::const_iterator si = subst.find(this);
00273   if (si != subst.end()) {
00274     assert((*si).second != NULL);
00275     return (*si).second;
00276   }
00277 
00278   if (_incomplete) {
00279     // We haven't finished defining the class yet.
00280     return this;
00281   }
00282 
00283   if (_subst_decl_recursive_protect) {
00284     // We're already executing this block; we'll have to return a
00285     // proxy to the type which we'll define later.
00286     CPPTypeProxy *proxy = new CPPTypeProxy;
00287     _proxies.push_back(proxy);
00288     assert(proxy != NULL);
00289     return proxy;
00290   }
00291   _subst_decl_recursive_protect = true;
00292 
00293   CPPStructType *rep = new CPPStructType(*this);
00294 
00295   if (_ident != NULL) {
00296     rep->_ident =
00297       _ident->substitute_decl(subst, current_scope, global_scope);
00298   }
00299 
00300   if (_scope != NULL) {
00301     rep->_scope =
00302       _scope->substitute_decl(subst, current_scope, global_scope);
00303     if (rep->_scope != _scope) {
00304       rep->_scope->set_struct_type(rep);
00305 
00306       // If we just instantiated a template scope, write the template
00307       // parameters into our identifier.
00308       CPPScope *pscope = rep->_scope->get_parent_scope();
00309 
00310       if (pscope != (CPPScope *)NULL &&
00311           pscope->_name.has_templ()) {
00312 
00313         // If the struct name didn't have an explicit template
00314         // reference before, now it does.
00315         if (!_ident->_names.empty() && !_ident->_names.back().has_templ()) {
00316           if (rep->is_template()) {
00317             rep->_template_scope = (CPPTemplateScope *)NULL;
00318             CPPNameComponent nc(get_simple_name());
00319             nc.set_templ(pscope->_name.get_templ());
00320             rep->_ident = new CPPIdentifier(nc);
00321           }
00322         }
00323       }
00324     }
00325   }
00326 
00327   bool unchanged =
00328     (rep->_ident == _ident && rep->_scope == _scope);
00329 
00330   for (int i = 0; i < (int)_derivation.size(); i++) {
00331     rep->_derivation[i]._base =
00332       _derivation[i]._base->substitute_decl(subst, current_scope, global_scope)->as_type();
00333     if (rep->_derivation[i]._base != _derivation[i]._base) {
00334       unchanged = false;
00335     }
00336   }
00337 
00338   if (unchanged) {
00339     delete rep;
00340     rep = this;
00341   }
00342 
00343   subst.insert(SubstDecl::value_type(this, rep));
00344 
00345   _subst_decl_recursive_protect = false;
00346   // Now fill in all the proxies we created for our recursive
00347   // references.
00348   Proxies::iterator pi;
00349   for (pi = _proxies.begin(); pi != _proxies.end(); ++pi) {
00350     (*pi)->_actual_type = rep;
00351   }
00352 
00353   assert(rep != NULL);
00354   rep = CPPType::new_type(rep)->as_struct_type();
00355   assert(rep != NULL);
00356   if (rep != this) {
00357     _instantiations.insert(rep);
00358     //    cerr << "Subst for " << *this << " is " << *rep << "\n";
00359   }
00360   return rep;
00361 }
00362 
00363 ////////////////////////////////////////////////////////////////////
00364 //     Function: CPPStructType::output
00365 //       Access: Public, Virtual
00366 //  Description:
00367 ////////////////////////////////////////////////////////////////////
00368 void CPPStructType::
00369 output(ostream &out, int indent_level, CPPScope *scope, bool complete) const {
00370   if (!complete && _ident != NULL) {
00371     // If we have a name, use it.
00372     if (cppparser_output_class_keyword) {
00373       out << _type << " ";
00374     }
00375     out << _ident->get_local_name(scope);
00376 
00377     if (is_template()) {
00378       CPPTemplateScope *tscope = get_template_scope();
00379       out << "< ";
00380       tscope->_parameters.output(out, scope);
00381       out << " >";
00382     }
00383 
00384   } else if (!complete && !_typedefs.empty()) {
00385     // If we have a typedef name, use it.
00386     out << _typedefs.front()->get_local_name(scope);
00387 
00388   } else {
00389     if (is_template()) {
00390       get_template_scope()->_parameters.write_formal(out, scope);
00391       indent(out, indent_level);
00392     }
00393     if (_ident != NULL) {
00394       out << _type << " " << _ident->get_local_name(scope);
00395     } else {
00396       out << _type;
00397     }
00398 
00399     // Show any derivation we may have
00400     if (!_derivation.empty()) {
00401       Derivation::const_iterator di = _derivation.begin();
00402       out << ": " << *di;
00403       ++di;
00404       while (di != _derivation.end()) {
00405         out << ", " << *di;
00406         ++di;
00407       }
00408     }
00409 
00410     out << " {\n";
00411     _scope->write(out, indent_level + 2, _scope);
00412     indent(out, indent_level) << "}";
00413   }
00414 }
00415 
00416 ////////////////////////////////////////////////////////////////////
00417 //     Function: CPPStructType::get_subtype
00418 //       Access: Public, Virtual
00419 //  Description:
00420 ////////////////////////////////////////////////////////////////////
00421 CPPDeclaration::SubType CPPStructType::
00422 get_subtype() const {
00423   return ST_struct;
00424 }
00425 
00426 ////////////////////////////////////////////////////////////////////
00427 //     Function: CPPStructType::as_struct_type
00428 //       Access: Public, Virtual
00429 //  Description:
00430 ////////////////////////////////////////////////////////////////////
00431 CPPStructType *CPPStructType::
00432 as_struct_type() {
00433   return this;
00434 }
00435 
00436 
00437 ////////////////////////////////////////////////////////////////////
00438 //     Function: CPPStructType::get_virtual_funcs
00439 //       Access: Public
00440 //  Description: Fills funcs up with a list of all the virtual
00441 //               function declarations (pure-virtual or otherwise)
00442 //               defined at or above this class.  This is used to
00443 //               determine which functions in a given class are
00444 //               actually virtual, since a function is virtual whose
00445 //               parent class holds a virtual function by the same
00446 //               name, whether or not it is actually declared virtual
00447 //               in the derived class.
00448 ////////////////////////////////////////////////////////////////////
00449 void CPPStructType::
00450 get_virtual_funcs(VFunctions &funcs) const {
00451   // First, get all the virtual funcs from our parents.
00452   Derivation::const_iterator di;
00453   for (di = _derivation.begin(); di != _derivation.end(); ++di) {
00454     VFunctions vf;
00455     CPPStructType *base = (*di)._base->as_struct_type();
00456     if (base != NULL) {
00457       base->get_virtual_funcs(vf);
00458       funcs.splice(funcs.end(), vf);
00459     }
00460   }
00461 
00462   // Now look for matching functions in this class that we can now
00463   // infer are virtual.
00464   VFunctions::iterator vfi, vfnext;
00465   vfi = funcs.begin();
00466   while (vfi != funcs.end()) {
00467     vfnext = vfi;
00468     ++vfnext;
00469 
00470     CPPInstance *inst = (*vfi);
00471     assert(inst->_type != (CPPType *)NULL);
00472     CPPFunctionType *base_ftype = inst->_type->as_function_type();
00473     assert(base_ftype != (CPPFunctionType *)NULL);
00474 
00475     if ((base_ftype->_flags & CPPFunctionType::F_destructor) != 0) {
00476       // Match destructor-for-destructor; don't try to match
00477       // destructors up by name.
00478       CPPInstance *destructor = get_destructor();
00479       if (destructor != (CPPInstance *)NULL) {
00480         // It's a match!  This destructor is virtual.
00481         funcs.erase(vfi);
00482         destructor->_storage_class |=
00483           (CPPInstance::SC_virtual | CPPInstance::SC_inherited_virtual);
00484       }
00485 
00486     } else {
00487       // Non-destructors we can try to match up by name.
00488       string fname = inst->get_local_name();
00489       CPPScope::Functions::const_iterator fi;
00490       fi = _scope->_functions.find(fname);
00491 
00492       if (fi != _scope->_functions.end()) {
00493         CPPFunctionGroup *fgroup = (*fi).second;
00494 
00495         // Look for a matching function amid this group.
00496         bool match_found = false;
00497         CPPFunctionGroup::Instances::const_iterator ii;
00498         for (ii = fgroup->_instances.begin();
00499              ii != fgroup->_instances.end() && !match_found;
00500              ++ii) {
00501           CPPInstance *new_inst = (*ii);
00502           assert(new_inst->_type != (CPPType *)NULL);
00503 
00504           CPPFunctionType *new_ftype = new_inst->_type->as_function_type();
00505           assert(new_ftype != (CPPFunctionType *)NULL);
00506 
00507           if (new_ftype->is_equivalent_function(*base_ftype)) {
00508             // It's a match!  We now know it's virtual.  Erase this
00509             // function from the list, so we can add it back in below.
00510             funcs.erase(vfi);
00511             match_found = true;
00512 
00513             // In fact, it's not only definitely virtual, but it's
00514             // *inherited* virtual, which means only that the
00515             // interface is defined in some parent class.  Sometimes
00516             // this is useful to know.
00517             new_inst->_storage_class |=
00518               (CPPInstance::SC_virtual | CPPInstance::SC_inherited_virtual);
00519           }
00520         }
00521       }
00522     }
00523     vfi = vfnext;
00524   }
00525 
00526   // Finally, look for more virtual function definitions.
00527   CPPScope::Functions::const_iterator fi;
00528   for (fi = _scope->_functions.begin();
00529        fi != _scope->_functions.end();
00530        ++fi) {
00531     CPPFunctionGroup *fgroup = (*fi).second;
00532     CPPFunctionGroup::Instances::const_iterator ii;
00533     for (ii = fgroup->_instances.begin();
00534          ii != fgroup->_instances.end();
00535          ++ii) {
00536       CPPInstance *inst = (*ii);
00537       if ((inst->_storage_class & CPPInstance::SC_virtual) != 0) {
00538         // Here's a virtual function.
00539         funcs.push_back(inst);
00540       }
00541     }
00542   }
00543 }
00544 
00545 ////////////////////////////////////////////////////////////////////
00546 //     Function: CPPStructType::count_pure_virtual_funcs
00547 //       Access: Public
00548 //  Description: Fills funcs up with a list of all the pure virtual
00549 //               function declarations defined at or above this class
00550 //               that have not been given definitions.
00551 ////////////////////////////////////////////////////////////////////
00552 void CPPStructType::
00553 get_pure_virtual_funcs(VFunctions &funcs) const {
00554   // First, get all the virtual functions.
00555   VFunctions vfuncs;
00556   get_virtual_funcs(vfuncs);
00557 
00558   // Now traverse the list, getting out those functions that are pure
00559   // virtual.
00560   VFunctions::iterator vfi;
00561   for (vfi = vfuncs.begin(); vfi != vfuncs.end(); ++vfi) {
00562     CPPInstance *inst = (*vfi);
00563     if ((inst->_storage_class & CPPInstance::SC_pure_virtual) != 0) {
00564       funcs.push_back(inst);
00565     }
00566   }
00567 }
00568 
00569 ////////////////////////////////////////////////////////////////////
00570 //     Function: CPPStructType::is_equal
00571 //       Access: Protected, Virtual
00572 //  Description: Called by CPPDeclaration to determine whether this
00573 //               type is equivalent to another type of the same type.
00574 ////////////////////////////////////////////////////////////////////
00575 bool CPPStructType::
00576 is_equal(const CPPDeclaration *other) const {
00577   return CPPDeclaration::is_equal(other);
00578   /*
00579   const CPPStructType *ot = ((CPPDeclaration *)other)->as_struct_type();
00580   assert(ot != NULL);
00581 
00582   return this == ot ||
00583     (get_fully_scoped_name() == ot->get_fully_scoped_name());
00584   */
00585 }
00586 
00587 ////////////////////////////////////////////////////////////////////
00588 //     Function: CPPStructType::is_less
00589 //       Access: Protected, Virtual
00590 //  Description: Called by CPPDeclaration to determine whether this
00591 //               type should be ordered before another type of the
00592 //               same type, in an arbitrary but fixed ordering.
00593 ////////////////////////////////////////////////////////////////////
00594 bool CPPStructType::
00595 is_less(const CPPDeclaration *other) const {
00596   return CPPDeclaration::is_less(other);
00597   /*
00598   const CPPStructType *ot = ((CPPDeclaration *)other)->as_struct_type();
00599   assert(ot != NULL);
00600 
00601   if (this == ot) {
00602     return false;
00603   }
00604 
00605   return
00606     (get_fully_scoped_name() < ot->get_fully_scoped_name());
00607   */
00608 }
00609 

Generated on Thu May 1 22:12:55 2003 for DTool by doxygen1.3