cppStructType.cxx 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700
  1. // Filename: cppStructType.cxx
  2. // Created by: drose (19Oct99)
  3. //
  4. ////////////////////////////////////////////////////////////////////
  5. //
  6. // PANDA 3D SOFTWARE
  7. // Copyright (c) Carnegie Mellon University. All rights reserved.
  8. //
  9. // All use of this software is subject to the terms of the revised BSD
  10. // license. You should have received a copy of this license along
  11. // with this source code in a file named "LICENSE."
  12. //
  13. ////////////////////////////////////////////////////////////////////
  14. #include "cppStructType.h"
  15. #include "cppTypedefType.h"
  16. #include "cppScope.h"
  17. #include "cppTypeProxy.h"
  18. #include "cppTemplateScope.h"
  19. #include "cppFunctionGroup.h"
  20. #include "cppFunctionType.h"
  21. #include "cppTBDType.h"
  22. #include "indent.h"
  23. #include "cppParser.h"
  24. ////////////////////////////////////////////////////////////////////
  25. // Function: CPPStructType::Base::output
  26. // Access: Public
  27. // Description:
  28. ////////////////////////////////////////////////////////////////////
  29. void CPPStructType::Base::
  30. output(ostream &out) const {
  31. if (_is_virtual) {
  32. out << "virtual ";
  33. }
  34. out << _vis << " " << *_base;
  35. }
  36. ////////////////////////////////////////////////////////////////////
  37. // Function: CPPStructType::Constructor
  38. // Access: Public
  39. // Description:
  40. ////////////////////////////////////////////////////////////////////
  41. CPPStructType::
  42. CPPStructType(CPPStructType::Type type, CPPIdentifier *ident,
  43. CPPScope *current_scope, CPPScope *scope,
  44. const CPPFile &file) :
  45. CPPExtensionType(type, ident, current_scope, file),
  46. _scope(scope)
  47. {
  48. _subst_decl_recursive_protect = false;
  49. _incomplete = true;
  50. }
  51. ////////////////////////////////////////////////////////////////////
  52. // Function: CPPStructType::Copy Constructor
  53. // Access: Public
  54. // Description:
  55. ////////////////////////////////////////////////////////////////////
  56. CPPStructType::
  57. CPPStructType(const CPPStructType &copy) :
  58. CPPExtensionType(copy),
  59. _scope(copy._scope),
  60. _incomplete(copy._incomplete),
  61. _derivation(copy._derivation)
  62. {
  63. _subst_decl_recursive_protect = false;
  64. }
  65. ////////////////////////////////////////////////////////////////////
  66. // Function: CPPStructType::Copy Assignment Operator
  67. // Access: Public
  68. // Description:
  69. ////////////////////////////////////////////////////////////////////
  70. void CPPStructType::
  71. operator = (const CPPStructType &copy) {
  72. CPPExtensionType::operator = (copy);
  73. _scope = copy._scope;
  74. _incomplete = copy._incomplete;
  75. _derivation = copy._derivation;
  76. }
  77. ////////////////////////////////////////////////////////////////////
  78. // Function: CPPStructType::append_derivation
  79. // Access: Public
  80. // Description: A handy function used while parsing to add a new base
  81. // class to the list of classes (or structs) this class
  82. // derives from.
  83. ////////////////////////////////////////////////////////////////////
  84. void CPPStructType::
  85. append_derivation(CPPType *base, CPPVisibility vis, bool is_virtual) {
  86. if (base != NULL) {
  87. // Unwrap any typedefs, since we can't inherit from a typedef.
  88. CPPTypedefType *def = base->as_typedef_type();
  89. while (def != NULL) {
  90. base = def->_type;
  91. def = base->as_typedef_type();
  92. }
  93. Base b;
  94. b._base = base;
  95. b._vis = vis;
  96. b._is_virtual = is_virtual;
  97. _derivation.push_back(b);
  98. }
  99. }
  100. ////////////////////////////////////////////////////////////////////
  101. // Function: CPPStructType::get_scope
  102. // Access: Public
  103. // Description:
  104. ////////////////////////////////////////////////////////////////////
  105. CPPScope *CPPStructType::
  106. get_scope() const {
  107. return _scope;
  108. }
  109. ////////////////////////////////////////////////////////////////////
  110. // Function: CPPStructType::is_abstract
  111. // Access: Public
  112. // Description: Returns true if this struct declaration is abstract,
  113. // e.g. it contains or inherits at least one method that
  114. // is pure virtual.
  115. ////////////////////////////////////////////////////////////////////
  116. bool CPPStructType::
  117. is_abstract() const {
  118. VFunctions funcs;
  119. get_pure_virtual_funcs(funcs);
  120. return !funcs.empty();
  121. }
  122. ////////////////////////////////////////////////////////////////////
  123. // Function: CPPStructType::is_trivial
  124. // Access: Public, Virtual
  125. // Description: Returns true if the type is considered a Plain Old
  126. // Data (POD) type.
  127. ////////////////////////////////////////////////////////////////////
  128. bool CPPStructType::
  129. is_trivial() const {
  130. // Make sure all base classes are trivial.
  131. Derivation::const_iterator di;
  132. for (di = _derivation.begin(); di != _derivation.end(); ++di) {
  133. CPPStructType *base = (*di)._base->as_struct_type();
  134. if (base != NULL && !base->is_trivial()) {
  135. return false;
  136. }
  137. }
  138. assert(_scope != NULL);
  139. // Make sure all members are trivial.
  140. CPPScope::Variables::const_iterator vi;
  141. for (vi = _scope->_variables.begin(); vi != _scope->_variables.end(); ++vi) {
  142. CPPInstance *instance = (*vi).second;
  143. assert(instance != NULL);
  144. if (instance->_storage_class & CPPInstance::SC_static) {
  145. // Static members don't count.
  146. continue;
  147. }
  148. if (instance->_initializer != NULL) {
  149. // A member with an initializer means the default constructor would
  150. // assign a value. This means the type can't be trivial.
  151. return false;
  152. }
  153. // Finally, check if the data member itself is non-trivial.
  154. assert(instance->_type != NULL);
  155. if (!instance->_type->is_trivial()) {
  156. return false;
  157. }
  158. }
  159. // Now look for functions that are virtual or con/destructors.
  160. bool is_default_constructible = true;
  161. CPPScope::Functions::const_iterator fi;
  162. for (fi = _scope->_functions.begin(); fi != _scope->_functions.end(); ++fi) {
  163. CPPFunctionGroup *fgroup = (*fi).second;
  164. CPPFunctionGroup::Instances::const_iterator ii;
  165. for (ii = fgroup->_instances.begin(); ii != fgroup->_instances.end(); ++ii) {
  166. CPPInstance *inst = (*ii);
  167. if (inst->_storage_class & CPPInstance::SC_virtual) {
  168. // Virtual functions are banned right off the bat.
  169. return false;
  170. }
  171. assert(inst->_type != (CPPType *)NULL);
  172. CPPFunctionType *ftype = inst->_type->as_function_type();
  173. assert(ftype != (CPPFunctionType *)NULL);
  174. if (ftype->_flags & (CPPFunctionType::F_destructor |
  175. CPPFunctionType::F_move_constructor |
  176. CPPFunctionType::F_copy_constructor)) {
  177. // User-provided destructors and copy/move constructors are not trivial.
  178. return false;
  179. }
  180. if ((ftype->_flags & CPPFunctionType::F_constructor) != 0) {
  181. if (ftype->_parameters->_parameters.size() == 0 &&
  182. !ftype->_parameters->_includes_ellipsis) {
  183. // Same for the default constructor.
  184. return false;
  185. }
  186. // The presence of a non-default constructor makes the class not
  187. // default-constructible.
  188. is_default_constructible = false;
  189. }
  190. if (fgroup->_name == "operator =") {
  191. // Or assignment operators.
  192. return false;
  193. }
  194. }
  195. }
  196. // Finally, the class must be default-constructible.
  197. return is_default_constructible;
  198. }
  199. ////////////////////////////////////////////////////////////////////
  200. // Function: CPPStructType::check_virtual
  201. // Access: Public
  202. // Description: Ensures all functions are correctly marked with the
  203. // "virtual" flag if they are truly virtual by virtue of
  204. // inheritance, rather than simply being labeled
  205. // virtual.
  206. //
  207. // This also sets the CPPInstance::SC_inherited_virtual
  208. // flags on those virtual methods that override a
  209. // virtual method defined in a parent class (as opposed
  210. // to those that appear for this first time in this
  211. // class). It is sometimes useful to know whether a
  212. // given virtual method represents the first time that
  213. // particular method appears.
  214. //
  215. // The return value is true if this class defines or
  216. // inherits any virtual methods (and thus requires a
  217. // virtual function pointer), or false otherwise.
  218. ////////////////////////////////////////////////////////////////////
  219. bool CPPStructType::
  220. check_virtual() {
  221. VFunctions funcs;
  222. get_virtual_funcs(funcs);
  223. return !funcs.empty();
  224. }
  225. ////////////////////////////////////////////////////////////////////
  226. // Function: CPPStructType::is_fully_specified
  227. // Access: Public, Virtual
  228. // Description: Returns true if this declaration is an actual,
  229. // factual declaration, or false if some part of the
  230. // declaration depends on a template parameter which has
  231. // not yet been instantiated.
  232. ////////////////////////////////////////////////////////////////////
  233. bool CPPStructType::
  234. is_fully_specified() const {
  235. if (_scope != NULL && !_scope->is_fully_specified()) {
  236. return false;
  237. }
  238. return CPPType::is_fully_specified();
  239. }
  240. ////////////////////////////////////////////////////////////////////
  241. // Function: CPPStructType::is_incomplete
  242. // Access: Public, Virtual
  243. // Description: Returns true if the type has not yet been fully
  244. // specified, false if it has.
  245. ////////////////////////////////////////////////////////////////////
  246. bool CPPStructType::
  247. is_incomplete() const {
  248. return _incomplete;
  249. }
  250. ////////////////////////////////////////////////////////////////////
  251. // Function: CPPStructType::get_destructor
  252. // Access: Public
  253. // Description: Returns the destructor defined for the struct type,
  254. // if any, or NULL if no destructor is found.
  255. ////////////////////////////////////////////////////////////////////
  256. CPPInstance *CPPStructType::
  257. get_destructor() const {
  258. // Iterate through all the functions that begin with '~' until we
  259. // find one that claims to be a destructor. In theory, there should
  260. // only be one such function.
  261. CPPScope::Functions::const_iterator fi;
  262. fi = _scope->_functions.lower_bound("~");
  263. while (fi != _scope->_functions.end() &&
  264. (*fi).first[0] == '~') {
  265. CPPFunctionGroup *fgroup = (*fi).second;
  266. CPPFunctionGroup::Instances::const_iterator ii;
  267. for (ii = fgroup->_instances.begin();
  268. ii != fgroup->_instances.end();
  269. ++ii) {
  270. CPPInstance *inst = (*ii);
  271. assert(inst->_type != (CPPType *)NULL);
  272. CPPFunctionType *ftype = inst->_type->as_function_type();
  273. assert(ftype != (CPPFunctionType *)NULL);
  274. if ((ftype->_flags & CPPFunctionType::F_destructor) != 0) {
  275. return inst;
  276. }
  277. }
  278. ++fi;
  279. }
  280. return (CPPInstance *)NULL;
  281. }
  282. ////////////////////////////////////////////////////////////////////
  283. // Function: CPPStructType::instantiate
  284. // Access: Public, Virtual
  285. // Description:
  286. ////////////////////////////////////////////////////////////////////
  287. CPPDeclaration *CPPStructType::
  288. instantiate(const CPPTemplateParameterList *actual_params,
  289. CPPScope *current_scope, CPPScope *global_scope,
  290. CPPPreprocessor *error_sink) const {
  291. // I *think* this assertion is no longer valid. Who knows.
  292. // assert(!_incomplete);
  293. if (_scope == NULL) {
  294. if (error_sink != NULL) {
  295. error_sink->warning("Ignoring template parameters for class " +
  296. get_local_name());
  297. }
  298. return (CPPDeclaration *)this;
  299. }
  300. CPPScope *scope =
  301. _scope->instantiate(actual_params, current_scope, global_scope, error_sink);
  302. if (scope->get_struct_type()->get_scope() != scope) {
  303. // Hmm, this type seems to be not completely defined. We must be
  304. // in the middle of recursively instantiating the scope. Thus, we
  305. // don't yet know what its associated struct type will be.
  306. // Postpone the evaluation of this type.
  307. CPPIdentifier *ident = new CPPIdentifier(get_fully_scoped_name(), _file);
  308. return CPPType::new_type(new CPPTBDType(ident));
  309. }
  310. CPPType *result = scope->get_struct_type();
  311. result = CPPType::new_type(result);
  312. if (result != (CPPType *)this) {
  313. // This really means the method ought to be non-const. But I'm
  314. // too lazy to propagate this change all the way back right now,
  315. // so this hack is here.
  316. ((CPPStructType *)this)->_instantiations.insert(result);
  317. }
  318. return result;
  319. }
  320. ////////////////////////////////////////////////////////////////////
  321. // Function: CPPStructType::substitute_decl
  322. // Access: Public, Virtual
  323. // Description:
  324. ////////////////////////////////////////////////////////////////////
  325. CPPDeclaration *CPPStructType::
  326. substitute_decl(CPPDeclaration::SubstDecl &subst,
  327. CPPScope *current_scope, CPPScope *global_scope) {
  328. SubstDecl::const_iterator si = subst.find(this);
  329. if (si != subst.end()) {
  330. assert((*si).second != NULL);
  331. return (*si).second;
  332. }
  333. if (_incomplete) {
  334. // We haven't finished defining the class yet.
  335. return this;
  336. }
  337. if (_subst_decl_recursive_protect) {
  338. // We're already executing this block; we'll have to return a
  339. // proxy to the type which we'll define later.
  340. CPPTypeProxy *proxy = new CPPTypeProxy;
  341. _proxies.push_back(proxy);
  342. assert(proxy != NULL);
  343. return proxy;
  344. }
  345. _subst_decl_recursive_protect = true;
  346. CPPStructType *rep = new CPPStructType(*this);
  347. if (_ident != NULL) {
  348. rep->_ident =
  349. _ident->substitute_decl(subst, current_scope, global_scope);
  350. }
  351. if (_scope != NULL) {
  352. rep->_scope =
  353. _scope->substitute_decl(subst, current_scope, global_scope);
  354. if (rep->_scope != _scope) {
  355. rep->_scope->set_struct_type(rep);
  356. // If we just instantiated a template scope, write the template
  357. // parameters into our identifier.
  358. CPPScope *pscope = rep->_scope->get_parent_scope();
  359. if (pscope != (CPPScope *)NULL &&
  360. pscope->_name.has_templ()) {
  361. // If the struct name didn't have an explicit template
  362. // reference before, now it does.
  363. if (!_ident->_names.empty() && !_ident->_names.back().has_templ()) {
  364. if (rep->is_template()) {
  365. rep->_template_scope = (CPPTemplateScope *)NULL;
  366. CPPNameComponent nc(get_simple_name());
  367. nc.set_templ(pscope->_name.get_templ());
  368. rep->_ident = new CPPIdentifier(nc, _file);
  369. }
  370. }
  371. }
  372. }
  373. }
  374. bool unchanged =
  375. (rep->_ident == _ident && rep->_scope == _scope);
  376. for (int i = 0; i < (int)_derivation.size(); ++i) {
  377. rep->_derivation[i]._base =
  378. _derivation[i]._base->substitute_decl(subst, current_scope, global_scope)->as_type();
  379. if (rep->_derivation[i]._base != _derivation[i]._base) {
  380. unchanged = false;
  381. }
  382. }
  383. if (unchanged) {
  384. delete rep;
  385. rep = this;
  386. }
  387. subst.insert(SubstDecl::value_type(this, rep));
  388. _subst_decl_recursive_protect = false;
  389. // Now fill in all the proxies we created for our recursive
  390. // references.
  391. Proxies::iterator pi;
  392. for (pi = _proxies.begin(); pi != _proxies.end(); ++pi) {
  393. (*pi)->_actual_type = rep;
  394. }
  395. assert(rep != NULL);
  396. rep = CPPType::new_type(rep)->as_struct_type();
  397. assert(rep != NULL);
  398. if (rep != this) {
  399. _instantiations.insert(rep);
  400. }
  401. return rep;
  402. }
  403. ////////////////////////////////////////////////////////////////////
  404. // Function: CPPStructType::output
  405. // Access: Public, Virtual
  406. // Description:
  407. ////////////////////////////////////////////////////////////////////
  408. void CPPStructType::
  409. output(ostream &out, int indent_level, CPPScope *scope, bool complete) const {
  410. if (!complete && _ident != NULL) {
  411. // If we have a name, use it.
  412. if (cppparser_output_class_keyword) {
  413. out << _type << " ";
  414. }
  415. out << _ident->get_local_name(scope);
  416. if (is_template()) {
  417. CPPTemplateScope *tscope = get_template_scope();
  418. tscope->_parameters.output(out, scope);
  419. }
  420. } else {
  421. if (is_template()) {
  422. get_template_scope()->_parameters.write_formal(out, scope);
  423. indent(out, indent_level);
  424. }
  425. if (_ident != NULL) {
  426. out << _type << " " << _ident->get_local_name(scope);
  427. } else {
  428. out << _type;
  429. }
  430. // Show any derivation we may have
  431. if (!_derivation.empty()) {
  432. Derivation::const_iterator di = _derivation.begin();
  433. out << ": " << *di;
  434. ++di;
  435. while (di != _derivation.end()) {
  436. out << ", " << *di;
  437. ++di;
  438. }
  439. }
  440. out << " {\n";
  441. _scope->write(out, indent_level + 2, _scope);
  442. indent(out, indent_level) << "}";
  443. }
  444. }
  445. ////////////////////////////////////////////////////////////////////
  446. // Function: CPPStructType::get_subtype
  447. // Access: Public, Virtual
  448. // Description:
  449. ////////////////////////////////////////////////////////////////////
  450. CPPDeclaration::SubType CPPStructType::
  451. get_subtype() const {
  452. return ST_struct;
  453. }
  454. ////////////////////////////////////////////////////////////////////
  455. // Function: CPPStructType::as_struct_type
  456. // Access: Public, Virtual
  457. // Description:
  458. ////////////////////////////////////////////////////////////////////
  459. CPPStructType *CPPStructType::
  460. as_struct_type() {
  461. return this;
  462. }
  463. ////////////////////////////////////////////////////////////////////
  464. // Function: CPPStructType::get_virtual_funcs
  465. // Access: Public
  466. // Description: Fills funcs up with a list of all the virtual
  467. // function declarations (pure-virtual or otherwise)
  468. // defined at or above this class. This is used to
  469. // determine which functions in a given class are
  470. // actually virtual, since a function is virtual whose
  471. // parent class holds a virtual function by the same
  472. // name, whether or not it is actually declared virtual
  473. // in the derived class.
  474. ////////////////////////////////////////////////////////////////////
  475. void CPPStructType::
  476. get_virtual_funcs(VFunctions &funcs) const {
  477. // First, get all the virtual funcs from our parents.
  478. Derivation::const_iterator di;
  479. for (di = _derivation.begin(); di != _derivation.end(); ++di) {
  480. VFunctions vf;
  481. CPPStructType *base = (*di)._base->as_struct_type();
  482. if (base != NULL) {
  483. base->get_virtual_funcs(vf);
  484. funcs.splice(funcs.end(), vf);
  485. }
  486. }
  487. // Now look for matching functions in this class that we can now
  488. // infer are virtual.
  489. VFunctions::iterator vfi, vfnext;
  490. vfi = funcs.begin();
  491. while (vfi != funcs.end()) {
  492. vfnext = vfi;
  493. ++vfnext;
  494. CPPInstance *inst = (*vfi);
  495. assert(inst->_type != (CPPType *)NULL);
  496. CPPFunctionType *base_ftype = inst->_type->as_function_type();
  497. assert(base_ftype != (CPPFunctionType *)NULL);
  498. if ((base_ftype->_flags & CPPFunctionType::F_destructor) != 0) {
  499. // Match destructor-for-destructor; don't try to match
  500. // destructors up by name.
  501. CPPInstance *destructor = get_destructor();
  502. if (destructor != (CPPInstance *)NULL) {
  503. // It's a match! This destructor is virtual.
  504. funcs.erase(vfi);
  505. destructor->_storage_class |=
  506. (CPPInstance::SC_virtual | CPPInstance::SC_inherited_virtual);
  507. }
  508. } else {
  509. // Non-destructors we can try to match up by name.
  510. string fname = inst->get_local_name();
  511. CPPScope::Functions::const_iterator fi;
  512. fi = _scope->_functions.find(fname);
  513. if (fi != _scope->_functions.end()) {
  514. CPPFunctionGroup *fgroup = (*fi).second;
  515. // Look for a matching function amid this group.
  516. bool match_found = false;
  517. CPPFunctionGroup::Instances::const_iterator ii;
  518. for (ii = fgroup->_instances.begin();
  519. ii != fgroup->_instances.end() && !match_found;
  520. ++ii) {
  521. CPPInstance *new_inst = (*ii);
  522. assert(new_inst->_type != (CPPType *)NULL);
  523. CPPFunctionType *new_ftype = new_inst->_type->as_function_type();
  524. assert(new_ftype != (CPPFunctionType *)NULL);
  525. if (new_ftype->is_equivalent_function(*base_ftype)) {
  526. // It's a match! We now know it's virtual. Erase this
  527. // function from the list, so we can add it back in below.
  528. funcs.erase(vfi);
  529. match_found = true;
  530. // In fact, it's not only definitely virtual, but it's
  531. // *inherited* virtual, which means only that the
  532. // interface is defined in some parent class. Sometimes
  533. // this is useful to know.
  534. new_inst->_storage_class |=
  535. (CPPInstance::SC_virtual | CPPInstance::SC_inherited_virtual);
  536. }
  537. }
  538. }
  539. }
  540. vfi = vfnext;
  541. }
  542. // Finally, look for more virtual function definitions.
  543. CPPScope::Functions::const_iterator fi;
  544. for (fi = _scope->_functions.begin();
  545. fi != _scope->_functions.end();
  546. ++fi) {
  547. CPPFunctionGroup *fgroup = (*fi).second;
  548. CPPFunctionGroup::Instances::const_iterator ii;
  549. for (ii = fgroup->_instances.begin();
  550. ii != fgroup->_instances.end();
  551. ++ii) {
  552. CPPInstance *inst = (*ii);
  553. if ((inst->_storage_class & CPPInstance::SC_virtual) != 0) {
  554. // Here's a virtual function.
  555. funcs.push_back(inst);
  556. }
  557. }
  558. }
  559. }
  560. ////////////////////////////////////////////////////////////////////
  561. // Function: CPPStructType::count_pure_virtual_funcs
  562. // Access: Public
  563. // Description: Fills funcs up with a list of all the pure virtual
  564. // function declarations defined at or above this class
  565. // that have not been given definitions.
  566. ////////////////////////////////////////////////////////////////////
  567. void CPPStructType::
  568. get_pure_virtual_funcs(VFunctions &funcs) const {
  569. // First, get all the virtual functions.
  570. VFunctions vfuncs;
  571. get_virtual_funcs(vfuncs);
  572. // Now traverse the list, getting out those functions that are pure
  573. // virtual.
  574. VFunctions::iterator vfi;
  575. for (vfi = vfuncs.begin(); vfi != vfuncs.end(); ++vfi) {
  576. CPPInstance *inst = (*vfi);
  577. if ((inst->_storage_class & CPPInstance::SC_pure_virtual) != 0) {
  578. funcs.push_back(inst);
  579. }
  580. }
  581. }
  582. ////////////////////////////////////////////////////////////////////
  583. // Function: CPPStructType::is_equal
  584. // Access: Protected, Virtual
  585. // Description: Called by CPPDeclaration to determine whether this
  586. // type is equivalent to another type of the same type.
  587. ////////////////////////////////////////////////////////////////////
  588. bool CPPStructType::
  589. is_equal(const CPPDeclaration *other) const {
  590. return CPPDeclaration::is_equal(other);
  591. /*
  592. const CPPStructType *ot = ((CPPDeclaration *)other)->as_struct_type();
  593. assert(ot != NULL);
  594. return this == ot ||
  595. (get_fully_scoped_name() == ot->get_fully_scoped_name());
  596. */
  597. }
  598. ////////////////////////////////////////////////////////////////////
  599. // Function: CPPStructType::is_less
  600. // Access: Protected, Virtual
  601. // Description: Called by CPPDeclaration to determine whether this
  602. // type should be ordered before another type of the
  603. // same type, in an arbitrary but fixed ordering.
  604. ////////////////////////////////////////////////////////////////////
  605. bool CPPStructType::
  606. is_less(const CPPDeclaration *other) const {
  607. return CPPDeclaration::is_less(other);
  608. /*
  609. const CPPStructType *ot = ((CPPDeclaration *)other)->as_struct_type();
  610. assert(ot != NULL);
  611. if (this == ot) {
  612. return false;
  613. }
  614. return
  615. (get_fully_scoped_name() < ot->get_fully_scoped_name());
  616. */
  617. }