cppIdentifier.cxx 15 KB

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