cppInstance.cxx 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623
  1. /**
  2. * PANDA 3D SOFTWARE
  3. * Copyright (c) Carnegie Mellon University. All rights reserved.
  4. *
  5. * All use of this software is subject to the terms of the revised BSD
  6. * license. You should have received a copy of this license along
  7. * with this source code in a file named "LICENSE."
  8. *
  9. * @file cppInstance.cxx
  10. * @author drose
  11. * @date 1999-10-19
  12. */
  13. #include "cppInstance.h"
  14. #include "cppInstanceIdentifier.h"
  15. #include "cppIdentifier.h"
  16. #include "cppTemplateScope.h"
  17. #include "cppFunctionType.h"
  18. #include "cppSimpleType.h"
  19. #include "cppExpression.h"
  20. #include "cppPreprocessor.h"
  21. #include "cppParameterList.h"
  22. #include "cppReferenceType.h"
  23. #include "cppConstType.h"
  24. #include "indent.h"
  25. #include <algorithm>
  26. /**
  27. *
  28. */
  29. CPPInstance::
  30. CPPInstance(CPPType *type, const string &name, int storage_class) :
  31. CPPDeclaration(CPPFile()),
  32. _type(type),
  33. _ident(new CPPIdentifier(name)),
  34. _storage_class(storage_class),
  35. _alignment(NULL),
  36. _bit_width(-1)
  37. {
  38. _initializer = NULL;
  39. }
  40. /**
  41. *
  42. */
  43. CPPInstance::
  44. CPPInstance(CPPType *type, CPPIdentifier *ident, int storage_class) :
  45. CPPDeclaration(CPPFile()),
  46. _type(type),
  47. _ident(ident),
  48. _storage_class(storage_class),
  49. _alignment(NULL),
  50. _bit_width(-1)
  51. {
  52. _initializer = NULL;
  53. }
  54. /**
  55. * Constructs a new CPPInstance object that defines a variable of the
  56. * indicated type according to the type and the InstanceIdentifier. The
  57. * InstanceIdentifier pointer is deallocated.
  58. */
  59. CPPInstance::
  60. CPPInstance(CPPType *type, CPPInstanceIdentifier *ii, int storage_class,
  61. const CPPFile &file) :
  62. CPPDeclaration(file),
  63. _alignment(NULL)
  64. {
  65. _type = ii->unroll_type(type);
  66. _ident = ii->_ident;
  67. ii->_ident = NULL;
  68. _storage_class = storage_class;
  69. _initializer = NULL;
  70. _bit_width = ii->_bit_width;
  71. CPPParameterList *params = ii->get_initializer();
  72. if (params != (CPPParameterList *)NULL) {
  73. // In this case, the instance has a parameter-list initializer, e.g.: int
  74. // foo(0); We really should save this initializer in the instance object.
  75. // But we don't for now, since no one really cares about initializers
  76. // anyway.
  77. }
  78. if (ii->_packed) {
  79. _storage_class |= SC_parameter_pack;
  80. }
  81. delete ii;
  82. }
  83. /**
  84. *
  85. */
  86. CPPInstance::
  87. CPPInstance(const CPPInstance &copy) :
  88. CPPDeclaration(copy),
  89. _type(copy._type),
  90. _ident(copy._ident),
  91. _initializer(copy._initializer),
  92. _storage_class(copy._storage_class),
  93. _alignment(copy._alignment),
  94. _bit_width(copy._bit_width)
  95. {
  96. assert(_type != NULL);
  97. }
  98. /**
  99. *
  100. */
  101. CPPInstance::
  102. ~CPPInstance() {
  103. // Can't delete the identifier. Don't try.
  104. }
  105. /**
  106. * Constructs and returns a new CPPInstance object that corresponds to a
  107. * function prototype declaration for a typecast method, whose return type is
  108. * implicit in the identifier type.
  109. */
  110. CPPInstance *CPPInstance::
  111. make_typecast_function(CPPInstance *inst, CPPIdentifier *ident,
  112. CPPParameterList *parameters, int function_flags) {
  113. CPPType *type = CPPType::new_type(inst->_type);
  114. delete inst;
  115. function_flags |= (int)CPPFunctionType::F_operator_typecast;
  116. CPPType *ft =
  117. CPPType::new_type(new CPPFunctionType(type, parameters, function_flags));
  118. return new CPPInstance(ft, ident);
  119. }
  120. /**
  121. *
  122. */
  123. bool CPPInstance::
  124. operator == (const CPPInstance &other) const {
  125. if (_type != other._type) {
  126. return false;
  127. }
  128. if (_storage_class != other._storage_class) {
  129. return false;
  130. }
  131. if (_alignment != other._alignment) {
  132. return false;
  133. }
  134. // We *do* care about the identifier. We need to differentiate types of
  135. // function variables, among possibly other things, based on the identifier.
  136. if ((_ident == NULL && other._ident != NULL) ||
  137. (_ident != NULL && other._ident == NULL) ||
  138. (_ident != NULL && other._ident != NULL && *_ident != *other._ident))
  139. {
  140. return false;
  141. }
  142. // We similarly care about the initializer.
  143. if ((_initializer == NULL && other._initializer != NULL) ||
  144. (_initializer != NULL && other._initializer == NULL) ||
  145. (_initializer != NULL && other._initializer != NULL &&
  146. *_initializer != *other._initializer))
  147. {
  148. return false;
  149. }
  150. return true;
  151. }
  152. /**
  153. *
  154. */
  155. bool CPPInstance::
  156. operator != (const CPPInstance &other) const {
  157. return !operator == (other);
  158. }
  159. /**
  160. *
  161. */
  162. bool CPPInstance::
  163. operator < (const CPPInstance &other) const {
  164. if (_type != other._type) {
  165. return _type < other._type;
  166. }
  167. if (_storage_class != other._storage_class) {
  168. return _storage_class < other._storage_class;
  169. }
  170. if (_alignment != other._alignment) {
  171. return _alignment < other._alignment;
  172. }
  173. // We *do* care about the identifier. We need to differentiate types of
  174. // function variables, among possibly other things, based on the identifier.
  175. if ((_ident == NULL && other._ident != NULL) ||
  176. (_ident != NULL && other._ident == NULL) ||
  177. (_ident != NULL && other._ident != NULL && *_ident != *other._ident))
  178. {
  179. if (_ident == NULL || other._ident == NULL) {
  180. return _ident < other._ident;
  181. }
  182. return *_ident < *other._ident;
  183. }
  184. // We similarly care about the initializer.
  185. if ((_initializer == NULL && other._initializer != NULL) ||
  186. (_initializer != NULL && other._initializer == NULL) ||
  187. (_initializer != NULL && other._initializer != NULL &&
  188. *_initializer != *other._initializer))
  189. {
  190. if (_initializer == NULL || other._initializer == NULL) {
  191. return _initializer < other._initializer;
  192. }
  193. return *_initializer < *other._initializer;
  194. }
  195. return false;
  196. }
  197. /**
  198. * Sets the value of the expression that is used to initialize the variable,
  199. * or the default value for a parameter. If a non-null expression is set on a
  200. * function declaration, it implies that the function is pure virtual.
  201. */
  202. void CPPInstance::
  203. set_initializer(CPPExpression *initializer) {
  204. if (_type->as_function_type() != (CPPFunctionType *)NULL) {
  205. // This is a function declaration.
  206. _storage_class &= ~(SC_pure_virtual | SC_defaulted | SC_deleted);
  207. _initializer = (CPPExpression *)NULL;
  208. if (initializer != (CPPExpression *)NULL) {
  209. if (initializer->_type == CPPExpression::T_integer) { // = 0
  210. _storage_class |= SC_pure_virtual;
  211. } else if (initializer->_type == CPPExpression::T_default) {
  212. _storage_class |= SC_defaulted;
  213. } else if (initializer->_type == CPPExpression::T_delete) {
  214. _storage_class |= SC_deleted;
  215. }
  216. }
  217. } else {
  218. _initializer = initializer;
  219. }
  220. }
  221. /**
  222. * Sets the number of bytes to align this instance to.
  223. */
  224. void CPPInstance::
  225. set_alignment(int align) {
  226. _alignment = new CPPExpression(align);
  227. }
  228. /**
  229. * Sets the expression that is used to determine the required alignment for
  230. * the variable. This should be a constant expression, but we don't presently
  231. * verify that it is.
  232. */
  233. void CPPInstance::
  234. set_alignment(CPPExpression *const_expr) {
  235. _alignment = const_expr;
  236. }
  237. /**
  238. *
  239. */
  240. bool CPPInstance::
  241. is_scoped() const {
  242. if (_ident == NULL) {
  243. return false;
  244. } else {
  245. return _ident->is_scoped();
  246. }
  247. }
  248. /**
  249. *
  250. */
  251. CPPScope *CPPInstance::
  252. get_scope(CPPScope *current_scope, CPPScope *global_scope,
  253. CPPPreprocessor *error_sink) const {
  254. if (_ident == NULL) {
  255. return current_scope;
  256. } else {
  257. return _ident->get_scope(current_scope, global_scope, error_sink);
  258. }
  259. }
  260. /**
  261. *
  262. */
  263. string CPPInstance::
  264. get_simple_name() const {
  265. if (_ident == NULL) {
  266. return "";
  267. } else {
  268. return _ident->get_simple_name();
  269. }
  270. }
  271. /**
  272. *
  273. */
  274. string CPPInstance::
  275. get_local_name(CPPScope *scope) const {
  276. if (_ident == NULL) {
  277. return "";
  278. } else {
  279. return _ident->get_local_name(scope);
  280. }
  281. }
  282. /**
  283. *
  284. */
  285. string CPPInstance::
  286. get_fully_scoped_name() const {
  287. if (_ident == NULL) {
  288. return "";
  289. } else {
  290. return _ident->get_fully_scoped_name();
  291. }
  292. }
  293. /**
  294. * If this is a function type instance, checks whether the function name
  295. * matches the class name (or ~name), and if so, flags it as a constructor,
  296. * destructor or assignment operator
  297. */
  298. void CPPInstance::
  299. check_for_constructor(CPPScope *current_scope, CPPScope *global_scope) {
  300. CPPScope *scope = get_scope(current_scope, global_scope);
  301. if (scope == NULL) {
  302. scope = current_scope;
  303. }
  304. CPPFunctionType *func = _type->as_function_type();
  305. if (func != NULL) {
  306. string method_name = get_local_name(scope);
  307. string class_name = scope->get_local_name();
  308. if (!method_name.empty() && !class_name.empty()) {
  309. // Check either a constructor or assignment operator.
  310. if (method_name == class_name || method_name == "operator =") {
  311. CPPType *void_type = CPPType::new_type
  312. (new CPPSimpleType(CPPSimpleType::T_void));
  313. int flags = func->_flags;
  314. if (method_name == class_name) {
  315. flags |= CPPFunctionType::F_constructor;
  316. }
  317. CPPParameterList *params = func->_parameters;
  318. if (params->_parameters.size() == 1 && !params->_includes_ellipsis) {
  319. CPPType *param_type = params->_parameters[0]->_type;
  320. CPPReferenceType *ref_type = param_type->as_reference_type();
  321. if (ref_type != NULL) {
  322. param_type = ref_type->_pointing_at->remove_cv();
  323. if (class_name == param_type->get_simple_name()) {
  324. if (flags & CPPFunctionType::F_constructor) {
  325. if (ref_type->_value_category == CPPReferenceType::VC_rvalue) {
  326. flags |= CPPFunctionType::F_move_constructor;
  327. } else {
  328. flags |= CPPFunctionType::F_copy_constructor;
  329. }
  330. } else {
  331. if (ref_type->_value_category == CPPReferenceType::VC_rvalue) {
  332. flags |= CPPFunctionType::F_move_assignment_operator;
  333. } else {
  334. flags |= CPPFunctionType::F_copy_assignment_operator;
  335. }
  336. }
  337. }
  338. }
  339. }
  340. _type = CPPType::new_type
  341. (new CPPFunctionType(void_type, func->_parameters, flags));
  342. } else if (method_name == "~" + class_name) {
  343. CPPType *void_type = CPPType::new_type
  344. (new CPPSimpleType(CPPSimpleType::T_void));
  345. _type = CPPType::new_type
  346. (new CPPFunctionType(void_type, func->_parameters,
  347. func->_flags | CPPFunctionType::F_destructor));
  348. }
  349. }
  350. }
  351. }
  352. /**
  353. *
  354. */
  355. CPPDeclaration *CPPInstance::
  356. instantiate(const CPPTemplateParameterList *actual_params,
  357. CPPScope *current_scope, CPPScope *global_scope,
  358. CPPPreprocessor *error_sink) const {
  359. if (!is_template()) {
  360. if (error_sink != NULL) {
  361. error_sink->warning("Ignoring template parameters for instance " +
  362. _ident->get_local_name());
  363. }
  364. return (CPPInstance *)this;
  365. }
  366. Instantiations::const_iterator ii;
  367. ii = _instantiations.find(actual_params);
  368. if (ii != _instantiations.end()) {
  369. // We've already instantiated this instance with these parameters. Return
  370. // that.
  371. return (*ii).second;
  372. }
  373. CPPTemplateScope *tscope = get_template_scope();
  374. CPPDeclaration::SubstDecl subst;
  375. actual_params->build_subst_decl(tscope->_parameters, subst,
  376. current_scope, global_scope);
  377. CPPInstance *inst =
  378. ((CPPInstance *)this)->substitute_decl(subst, current_scope, global_scope)
  379. ->as_instance();
  380. if (inst == this) {
  381. // Hmm, nothing to substitute. Make a new instance anyway, so we can
  382. // change the name.
  383. inst = new CPPInstance(*this);
  384. }
  385. assert(inst != NULL);
  386. inst->_ident = inst->_ident->substitute_decl(subst, current_scope, global_scope);
  387. if (inst->_ident == _ident) {
  388. inst->_ident = new CPPIdentifier(*inst->_ident);
  389. }
  390. inst->_ident->_names.back().set_templ
  391. (new CPPTemplateParameterList(*actual_params));
  392. inst->_template_scope = NULL;
  393. ((CPPInstance *)this)->_instantiations.insert(Instantiations::value_type(actual_params, inst));
  394. return inst;
  395. }
  396. /**
  397. * Returns true if this declaration is an actual, factual declaration, or
  398. * false if some part of the declaration depends on a template parameter which
  399. * has not yet been instantiated.
  400. */
  401. bool CPPInstance::
  402. is_fully_specified() const {
  403. if (_ident != NULL && !_ident->is_fully_specified()) {
  404. return false;
  405. }
  406. if (_initializer != NULL && !_initializer->is_fully_specified()) {
  407. return false;
  408. }
  409. return CPPDeclaration::is_fully_specified() &&
  410. _type->is_fully_specified();
  411. }
  412. /**
  413. *
  414. */
  415. CPPDeclaration *CPPInstance::
  416. substitute_decl(CPPDeclaration::SubstDecl &subst,
  417. CPPScope *current_scope, CPPScope *global_scope) {
  418. CPPDeclaration *top =
  419. CPPDeclaration::substitute_decl(subst, current_scope, global_scope);
  420. if (top != this) {
  421. return top;
  422. }
  423. CPPInstance *rep = new CPPInstance(*this);
  424. CPPDeclaration *new_type =
  425. _type->substitute_decl(subst, current_scope, global_scope);
  426. rep->_type = new_type->as_type();
  427. if (rep->_type == NULL) {
  428. rep->_type = _type;
  429. }
  430. if (_initializer != NULL) {
  431. rep->_initializer =
  432. _initializer->substitute_decl(subst, current_scope, global_scope)
  433. ->as_expression();
  434. }
  435. if (rep->_type == _type &&
  436. rep->_initializer == _initializer) {
  437. delete rep;
  438. rep = this;
  439. }
  440. subst.insert(SubstDecl::value_type(this, rep));
  441. return rep;
  442. }
  443. /**
  444. *
  445. */
  446. void CPPInstance::
  447. output(ostream &out, int indent_level, CPPScope *scope, bool complete) const {
  448. output(out, indent_level, scope, complete, -1);
  449. }
  450. /**
  451. * The extra parameter comes into play only when we happen to be outputting a
  452. * function prototype. See CPPFunctionType::output().
  453. */
  454. void CPPInstance::
  455. output(ostream &out, int indent_level, CPPScope *scope, bool complete,
  456. int num_default_parameters) const {
  457. assert(_type != NULL);
  458. if (_type->is_parameter_expr()) {
  459. // In this case, the whole thing is really an expression, and not an
  460. // instance at all. This can only happen if we parsed an instance
  461. // declaration while we thought we were parsing a function prototype.
  462. out << *_initializer;
  463. return;
  464. }
  465. if (is_template()) {
  466. get_template_scope()->_parameters.write_formal(out, scope);
  467. indent(out, indent_level);
  468. }
  469. if (_alignment != NULL) {
  470. out << "alignas(" << *_alignment << ") ";
  471. }
  472. if (_storage_class & SC_static) {
  473. out << "static ";
  474. }
  475. if (_storage_class & SC_extern) {
  476. out << "extern ";
  477. }
  478. if (_storage_class & SC_c_binding) {
  479. out << "\"C\" ";
  480. }
  481. if (_storage_class & SC_virtual) {
  482. out << "virtual ";
  483. }
  484. if (_storage_class & SC_inline) {
  485. out << "inline ";
  486. }
  487. if (_storage_class & SC_explicit) {
  488. out << "explicit ";
  489. }
  490. if (_storage_class & SC_register) {
  491. out << "register ";
  492. }
  493. if (_storage_class & SC_volatile) {
  494. out << "volatile ";
  495. }
  496. if (_storage_class & SC_mutable) {
  497. out << "mutable ";
  498. }
  499. if (_storage_class & SC_constexpr) {
  500. out << "constexpr ";
  501. }
  502. if (_storage_class & SC_thread_local) {
  503. out << "thread_local ";
  504. }
  505. string name;
  506. if (_ident != NULL) {
  507. name = _ident->get_local_name(scope);
  508. }
  509. if (_storage_class & SC_parameter_pack) {
  510. name = "..." + name;
  511. }
  512. if (_type->as_function_type()) {
  513. _type->as_function_type()->
  514. output_instance(out, indent_level, scope, complete, "", name,
  515. num_default_parameters);
  516. } else {
  517. _type->output_instance(out, indent_level, scope, complete, "", name);
  518. }
  519. if (_bit_width != -1) {
  520. out << " : " << _bit_width;
  521. }
  522. if (_storage_class & SC_pure_virtual) {
  523. out << " = 0";
  524. }
  525. if (_storage_class & SC_defaulted) {
  526. out << " = default";
  527. }
  528. if (_storage_class & SC_deleted) {
  529. out << " = delete";
  530. }
  531. if (_initializer != NULL) {
  532. out << " = " << *_initializer;
  533. }
  534. }
  535. /**
  536. *
  537. */
  538. CPPDeclaration::SubType CPPInstance::
  539. get_subtype() const {
  540. return ST_instance;
  541. }
  542. /**
  543. *
  544. */
  545. CPPInstance *CPPInstance::
  546. as_instance() {
  547. return this;
  548. }