cppIdentifier.cxx 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598
  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 cppIdentifier.cxx
  10. * @author drose
  11. * @date 1999-10-26
  12. */
  13. #include "cppIdentifier.h"
  14. #include "cppScope.h"
  15. #include "cppTemplateScope.h"
  16. #include "cppPreprocessor.h"
  17. #include "cppTemplateParameterList.h"
  18. #include "cppTBDType.h"
  19. #include "cppStructType.h"
  20. /**
  21. *
  22. */
  23. CPPIdentifier::
  24. CPPIdentifier(const string &name, const CPPFile &file) {
  25. _names.push_back(CPPNameComponent(name));
  26. _native_scope = nullptr;
  27. _loc.first_line = 0;
  28. _loc.first_column = 0;
  29. _loc.last_line = 0;
  30. _loc.last_column = 0;
  31. _loc.file = file;
  32. }
  33. /**
  34. *
  35. */
  36. CPPIdentifier::
  37. CPPIdentifier(const CPPNameComponent &name, const CPPFile &file) {
  38. _names.push_back(name);
  39. _native_scope = nullptr;
  40. _loc.first_line = 0;
  41. _loc.first_column = 0;
  42. _loc.last_line = 0;
  43. _loc.last_column = 0;
  44. _loc.file = file;
  45. }
  46. /**
  47. *
  48. */
  49. CPPIdentifier::
  50. CPPIdentifier(const string &name, const cppyyltype &loc) : _loc(loc) {
  51. _names.push_back(CPPNameComponent(name));
  52. _native_scope = nullptr;
  53. }
  54. /**
  55. *
  56. */
  57. CPPIdentifier::
  58. CPPIdentifier(const CPPNameComponent &name, const cppyyltype &loc) : _loc(loc) {
  59. _names.push_back(name);
  60. _native_scope = nullptr;
  61. }
  62. /**
  63. *
  64. */
  65. void CPPIdentifier::
  66. add_name(const string &name) {
  67. _names.push_back(CPPNameComponent(name));
  68. }
  69. /**
  70. *
  71. */
  72. void CPPIdentifier::
  73. add_name(const CPPNameComponent &name) {
  74. _names.push_back(name);
  75. }
  76. /**
  77. *
  78. */
  79. bool CPPIdentifier::
  80. operator == (const CPPIdentifier &other) const {
  81. if (_names.size() != other._names.size()) {
  82. return false;
  83. }
  84. for (int i = 0; i < (int)_names.size(); ++i) {
  85. if (_names[i] != other._names[i]) {
  86. return false;
  87. }
  88. }
  89. return true;
  90. }
  91. /**
  92. *
  93. */
  94. bool CPPIdentifier::
  95. operator != (const CPPIdentifier &other) const {
  96. return !(*this == other);
  97. }
  98. /**
  99. *
  100. */
  101. bool CPPIdentifier::
  102. operator < (const CPPIdentifier &other) const {
  103. if (_names.size() != other._names.size()) {
  104. return _names.size() < other._names.size();
  105. }
  106. for (int i = 0; i < (int)_names.size(); ++i) {
  107. if (_names[i] != other._names[i]) {
  108. return _names[i] < other._names[i];
  109. }
  110. }
  111. return false;
  112. }
  113. /**
  114. *
  115. */
  116. bool CPPIdentifier::
  117. is_scoped() const {
  118. return _names.size() > 1;
  119. }
  120. /**
  121. *
  122. */
  123. string CPPIdentifier::
  124. get_simple_name() const {
  125. return _names.back().get_name();
  126. }
  127. /**
  128. *
  129. */
  130. string CPPIdentifier::
  131. get_local_name(CPPScope *scope) const {
  132. assert(!_names.empty());
  133. string result;
  134. if (scope == nullptr || (_native_scope == nullptr && _names.size() == 1)) {
  135. result = _names.back().get_name_with_templ(scope);
  136. } else if (_names.front().empty()) {
  137. result = get_fully_scoped_name();
  138. } else {
  139. // Determine the scope of everything up until but not including the last
  140. // name.
  141. CPPScope *my_scope = get_scope(scope, nullptr);
  142. // Strip off template scopes, since they don't add anything particularly
  143. // meaningful to the local name.
  144. while (my_scope != nullptr && my_scope->as_template_scope() != nullptr) {
  145. my_scope = my_scope->get_parent_scope();
  146. }
  147. if (my_scope == nullptr) {
  148. result = get_fully_scoped_name();
  149. } else if (my_scope == scope) {
  150. return _names.back().get_name_with_templ(scope);
  151. } else {
  152. result = my_scope->get_local_name(scope);
  153. if (!result.empty()) {
  154. result += "::";
  155. }
  156. result += _names.back().get_name_with_templ(scope);
  157. }
  158. }
  159. return result;
  160. }
  161. /**
  162. *
  163. */
  164. string CPPIdentifier::
  165. get_fully_scoped_name() const {
  166. assert(!_names.empty());
  167. Names::const_iterator ni = _names.begin();
  168. string name = (*ni).get_name_with_templ();
  169. ++ni;
  170. while (ni != _names.end()) {
  171. name += "::" + (*ni).get_name_with_templ();
  172. ++ni;
  173. }
  174. return name;
  175. }
  176. /**
  177. * Returns true if this declaration is an actual, factual declaration, or
  178. * false if some part of the declaration depends on a template parameter which
  179. * has not yet been instantiated.
  180. */
  181. bool CPPIdentifier::
  182. is_fully_specified() const {
  183. Names::const_iterator ni;
  184. for (ni = _names.begin(); ni != _names.end(); ++ni) {
  185. if ((*ni).has_templ() && !(*ni).get_templ()->is_fully_specified()) {
  186. return false;
  187. }
  188. }
  189. return true;
  190. }
  191. /**
  192. * Returns true if the identifier includes a template parameter list that
  193. * includes some not-yet-defined type.
  194. */
  195. bool CPPIdentifier::
  196. is_tbd() const {
  197. Names::const_iterator ni;
  198. for (ni = _names.begin(); ni != _names.end(); ++ni) {
  199. if ((*ni).is_tbd()) {
  200. return true;
  201. }
  202. }
  203. return false;
  204. }
  205. /**
  206. *
  207. */
  208. CPPScope *CPPIdentifier::
  209. get_scope(CPPScope *current_scope, CPPScope *global_scope,
  210. CPPPreprocessor *error_sink) const {
  211. assert(!_names.empty());
  212. CPPScope *scope = _native_scope;
  213. if (scope == nullptr) {
  214. scope = current_scope;
  215. }
  216. int i = 0;
  217. if (_names[i].empty()) {
  218. // This identifier starts with a ::, thus it begins at the global scope.
  219. scope = global_scope;
  220. i++;
  221. }
  222. while (i + 1 < (int)_names.size() && scope != nullptr) {
  223. CPPScope *next_scope = scope->find_scope(_names[i].get_name(), global_scope);
  224. if (next_scope == nullptr) {
  225. if (error_sink != nullptr) {
  226. error_sink->error("Symbol " + _names[i].get_name() +
  227. " is not a known scope in " +
  228. scope->get_fully_scoped_name(),
  229. _loc);
  230. }
  231. return nullptr;
  232. }
  233. if (_names[i].has_templ()) {
  234. next_scope = next_scope->instantiate(_names[i].get_templ(),
  235. current_scope, global_scope);
  236. }
  237. scope = next_scope;
  238. i++;
  239. }
  240. return scope;
  241. }
  242. /**
  243. *
  244. */
  245. CPPScope *CPPIdentifier::
  246. get_scope(CPPScope *current_scope, CPPScope *global_scope,
  247. CPPDeclaration::SubstDecl &subst,
  248. CPPPreprocessor *error_sink) const {
  249. assert(!_names.empty());
  250. CPPScope *scope = _native_scope;
  251. if (scope == nullptr) {
  252. scope = current_scope;
  253. }
  254. int i = 0;
  255. if (_names[i].empty()) {
  256. // This identifier starts with a ::, thus it begins at the global scope.
  257. scope = global_scope;
  258. i++;
  259. }
  260. while (i + 1 < (int)_names.size() && scope != nullptr) {
  261. CPPScope *next_scope = scope->find_scope(_names[i].get_name(), subst,
  262. global_scope);
  263. if (next_scope == nullptr) {
  264. if (error_sink != nullptr) {
  265. error_sink->error("Symbol " + _names[i].get_name() +
  266. " is not a known scope in " +
  267. scope->get_fully_scoped_name(),
  268. _loc);
  269. }
  270. return nullptr;
  271. }
  272. if (_names[i].has_templ()) {
  273. next_scope = next_scope->instantiate(_names[i].get_templ(),
  274. current_scope, global_scope);
  275. }
  276. scope = next_scope;
  277. i++;
  278. }
  279. return scope;
  280. }
  281. /**
  282. * Looks up the identifier in the current and/or global scopes, and returns a
  283. * CPPType pointer if it seems to refer to a type, or NULL if it does not. If
  284. * force_instantiate is true, the type will be instantiated as fully as
  285. * possible right now, even if it means instantiating it into an identical
  286. * template type. Otherwise, the instantiation may be delayed for
  287. * optimization reasons, and a CPPTBDType placeholder may be returned instead.
  288. */
  289. CPPType *CPPIdentifier::
  290. find_type(CPPScope *current_scope, CPPScope *global_scope,
  291. bool force_instantiate,
  292. CPPPreprocessor *error_sink) const {
  293. CPPScope *scope = get_scope(current_scope, global_scope, error_sink);
  294. if (scope == nullptr) {
  295. return nullptr;
  296. }
  297. CPPType *type = nullptr;
  298. if (!_names.back().has_templ()) {
  299. type = scope->find_type(get_simple_name());
  300. } else {
  301. CPPDeclaration *decl = find_symbol(current_scope, global_scope, error_sink);
  302. type = decl->as_type();
  303. /*
  304. if (type != NULL) {
  305. if (!type->is_incomplete() || force_instantiate) {
  306. type = type->instantiate(_names.back().get_templ(),
  307. current_scope, global_scope,
  308. error_sink)->as_type();
  309. // If we ended up with another template, instantiate later.
  310. if (type->is_template() && !force_instantiate) {
  311. type = CPPType::new_type(new CPPTBDType((CPPIdentifier *)this));
  312. }
  313. } else {
  314. // Otherwise, we'll have to instantiate the type later.
  315. type = CPPType::new_type(new CPPTBDType((CPPIdentifier *)this));
  316. }
  317. // type->_file.replace_nearer(_file);
  318. }
  319. */
  320. }
  321. return type;
  322. }
  323. /**
  324. * This flavor of find_type() will instantiate any scope names in the
  325. * identifier. It's useful for fully defining a type while instantiating a
  326. * class.
  327. */
  328. CPPType *CPPIdentifier::
  329. find_type(CPPScope *current_scope, CPPScope *global_scope,
  330. CPPDeclaration::SubstDecl &subst,
  331. CPPPreprocessor *error_sink) const {
  332. CPPScope *scope = get_scope(current_scope, global_scope, subst, error_sink);
  333. if (scope == nullptr) {
  334. return nullptr;
  335. }
  336. CPPType *type = scope->find_type(get_simple_name(), subst, global_scope);
  337. if (type != nullptr && _names.back().has_templ()) {
  338. // This is a template type.
  339. if (is_fully_specified()) {
  340. // If our identifier fully specifies the instantiation, then apply it.
  341. CPPDeclaration *decl =
  342. type->instantiate(_names.back().get_templ(),
  343. current_scope, global_scope,
  344. error_sink);
  345. assert(decl != nullptr);
  346. CPPType *new_type = decl->as_type();
  347. assert(new_type != nullptr);
  348. if (new_type == type) {
  349. type = CPPType::new_type(new CPPTBDType((CPPIdentifier *)this));
  350. } else {
  351. type = new_type;
  352. }
  353. } else {
  354. // Otherwise, we'll have to instantiate the type later.
  355. type = CPPType::new_type(new CPPTBDType((CPPIdentifier *)this));
  356. }
  357. // type->_file.replace_nearer(_file);
  358. }
  359. return type;
  360. }
  361. /**
  362. *
  363. */
  364. CPPDeclaration *CPPIdentifier::
  365. find_symbol(CPPScope *current_scope, CPPScope *global_scope,
  366. CPPPreprocessor *error_sink) const {
  367. CPPScope *scope = get_scope(current_scope, global_scope, error_sink);
  368. if (scope == nullptr) {
  369. return nullptr;
  370. }
  371. CPPDeclaration *sym;
  372. if (!_names.back().has_templ()) {
  373. if (_names.size() > 1 && scope->get_simple_name() == get_simple_name()) {
  374. /**
  375. */
  376. sym = scope->get_struct_type()->get_constructor();
  377. } else {
  378. sym = scope->find_symbol(get_simple_name());
  379. }
  380. } else {
  381. sym = scope->find_template(get_simple_name());
  382. if (sym != nullptr) {
  383. CPPType *type = sym->as_type();
  384. if (type != nullptr && type->is_incomplete()) {
  385. // We can't instantiate an incomplete type.
  386. sym = CPPType::new_type(new CPPTBDType((CPPIdentifier *)this));
  387. } else {
  388. // Instantiate the symbol.
  389. sym = sym->instantiate(_names.back().get_templ(), current_scope,
  390. global_scope, error_sink);
  391. }
  392. }
  393. }
  394. return sym;
  395. }
  396. /**
  397. *
  398. */
  399. CPPDeclaration *CPPIdentifier::
  400. find_symbol(CPPScope *current_scope, CPPScope *global_scope,
  401. CPPDeclaration::SubstDecl &subst,
  402. CPPPreprocessor *error_sink) const {
  403. CPPScope *scope = get_scope(current_scope, global_scope, subst, error_sink);
  404. if (scope == nullptr) {
  405. return nullptr;
  406. }
  407. CPPDeclaration *sym;
  408. if (!_names.back().has_templ()) {
  409. if (_names.size() > 1 && scope->get_simple_name() == get_simple_name()) {
  410. /**
  411. */
  412. sym = scope->get_struct_type()->get_constructor();
  413. } else {
  414. sym = scope->find_symbol(get_simple_name());
  415. }
  416. } else {
  417. sym = scope->find_template(get_simple_name());
  418. if (sym != nullptr) {
  419. CPPType *type = sym->as_type();
  420. if (type != nullptr && type->is_incomplete()) {
  421. // We can't instantiate an incomplete type.
  422. sym = CPPType::new_type(new CPPTBDType((CPPIdentifier *)this));
  423. } else {
  424. // Instantiate the symbol.
  425. sym = sym->instantiate(_names.back().get_templ(), current_scope,
  426. global_scope, error_sink);
  427. }
  428. }
  429. }
  430. return sym;
  431. }
  432. /**
  433. *
  434. */
  435. CPPDeclaration *CPPIdentifier::
  436. find_template(CPPScope *current_scope, CPPScope *global_scope,
  437. CPPPreprocessor *error_sink) const {
  438. CPPScope *scope = get_scope(current_scope, global_scope, error_sink);
  439. if (scope == nullptr) {
  440. return nullptr;
  441. }
  442. return scope->find_template(get_simple_name());
  443. }
  444. /**
  445. *
  446. */
  447. CPPScope *CPPIdentifier::
  448. find_scope(CPPScope *current_scope, CPPScope *global_scope,
  449. CPPPreprocessor *error_sink) const {
  450. CPPScope *scope = get_scope(current_scope, global_scope, error_sink);
  451. if (scope == nullptr) {
  452. return nullptr;
  453. }
  454. return scope->find_scope(get_simple_name(), global_scope);
  455. }
  456. /**
  457. *
  458. */
  459. CPPIdentifier *CPPIdentifier::
  460. substitute_decl(CPPDeclaration::SubstDecl &subst,
  461. CPPScope *current_scope, CPPScope *global_scope) {
  462. CPPIdentifier *rep = new CPPIdentifier(*this);
  463. bool anything_changed = false;
  464. for (int i = 0; i < (int)rep->_names.size(); ++i) {
  465. if (_names[i].has_templ()) {
  466. rep->_names[i].set_templ
  467. (_names[i].get_templ()->substitute_decl(subst, current_scope, global_scope));
  468. if (rep->_names[i].get_templ() != _names[i].get_templ()) {
  469. anything_changed = true;
  470. }
  471. }
  472. }
  473. if (!anything_changed) {
  474. delete rep;
  475. rep = this;
  476. }
  477. return rep;
  478. }
  479. /**
  480. *
  481. */
  482. void CPPIdentifier::
  483. output(ostream &out, CPPScope *scope) const {
  484. if (scope == nullptr) {
  485. output_fully_scoped_name(out);
  486. } else {
  487. output_local_name(out, scope);
  488. }
  489. }
  490. /**
  491. *
  492. */
  493. void CPPIdentifier::
  494. output_local_name(ostream &out, CPPScope *scope) const {
  495. assert(!_names.empty());
  496. if (scope == nullptr || (_native_scope == nullptr && _names.size() == 1)) {
  497. out << _names.back();
  498. } else if (_names.front().empty()) {
  499. output_fully_scoped_name(out);
  500. } else {
  501. // Determine the scope of everything up until but not including the last
  502. // name.
  503. CPPScope *my_scope = get_scope(scope, nullptr);
  504. if (my_scope == nullptr) {
  505. output_fully_scoped_name(out);
  506. } else {
  507. out << my_scope->get_local_name(scope) << "::" << _names.back();
  508. }
  509. }
  510. }
  511. /**
  512. *
  513. */
  514. void CPPIdentifier::
  515. output_fully_scoped_name(ostream &out) const {
  516. if (_native_scope != nullptr) {
  517. _native_scope->output(out, nullptr);
  518. out << "::";
  519. }
  520. Names::const_iterator ni = _names.begin();
  521. out << (*ni);
  522. ++ni;
  523. while (ni != _names.end()) {
  524. out << "::" << (*ni);
  525. ++ni;
  526. }
  527. }