| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606 |
- /**
- * PANDA 3D SOFTWARE
- * Copyright (c) Carnegie Mellon University. All rights reserved.
- *
- * All use of this software is subject to the terms of the revised BSD
- * license. You should have received a copy of this license along
- * with this source code in a file named "LICENSE."
- *
- * @file cppIdentifier.cxx
- * @author drose
- * @date 1999-10-26
- */
- #include "cppIdentifier.h"
- #include "cppFunctionGroup.h"
- #include "cppScope.h"
- #include "cppPreprocessor.h"
- #include "cppTemplateParameterList.h"
- #include "cppType.h"
- #include "cppTBDType.h"
- #include "cppStructType.h"
- using std::string;
- /**
- *
- */
- CPPIdentifier::
- CPPIdentifier(const string &name, const CPPFile &file) {
- _names.push_back(CPPNameComponent(name));
- _native_scope = nullptr;
- _loc.first_line = 0;
- _loc.first_column = 0;
- _loc.last_line = 0;
- _loc.last_column = 0;
- _loc.file = file;
- }
- /**
- *
- */
- CPPIdentifier::
- CPPIdentifier(const CPPNameComponent &name, const CPPFile &file) {
- _names.push_back(name);
- _native_scope = nullptr;
- _loc.first_line = 0;
- _loc.first_column = 0;
- _loc.last_line = 0;
- _loc.last_column = 0;
- _loc.file = file;
- }
- /**
- *
- */
- CPPIdentifier::
- CPPIdentifier(const string &name, const cppyyltype &loc) : _loc(loc) {
- _names.push_back(CPPNameComponent(name));
- _native_scope = nullptr;
- }
- /**
- *
- */
- CPPIdentifier::
- CPPIdentifier(const CPPNameComponent &name, const cppyyltype &loc) : _loc(loc) {
- _names.push_back(name);
- _native_scope = nullptr;
- }
- /**
- *
- */
- void CPPIdentifier::
- add_name(const string &name) {
- _names.push_back(CPPNameComponent(name));
- }
- /**
- *
- */
- void CPPIdentifier::
- add_name(const CPPNameComponent &name) {
- _names.push_back(name);
- }
- /**
- *
- */
- bool CPPIdentifier::
- operator == (const CPPIdentifier &other) const {
- if (_names.size() != other._names.size()) {
- return false;
- }
- for (int i = 0; i < (int)_names.size(); ++i) {
- if (_names[i] != other._names[i]) {
- return false;
- }
- }
- return true;
- }
- /**
- *
- */
- bool CPPIdentifier::
- operator != (const CPPIdentifier &other) const {
- return !(*this == other);
- }
- /**
- *
- */
- bool CPPIdentifier::
- operator < (const CPPIdentifier &other) const {
- if (_names.size() != other._names.size()) {
- return _names.size() < other._names.size();
- }
- for (int i = 0; i < (int)_names.size(); ++i) {
- if (_names[i] != other._names[i]) {
- return _names[i] < other._names[i];
- }
- }
- return false;
- }
- /**
- *
- */
- bool CPPIdentifier::
- is_scoped() const {
- return _names.size() > 1;
- }
- /**
- *
- */
- string CPPIdentifier::
- get_simple_name() const {
- return _names.back().get_name();
- }
- /**
- *
- */
- string CPPIdentifier::
- get_local_name(CPPScope *scope) const {
- assert(!_names.empty());
- string result;
- if (scope == nullptr || (_native_scope == nullptr && _names.size() == 1)) {
- result = _names.back().get_name_with_templ(scope);
- } else if (_names.front().empty()) {
- result = get_fully_scoped_name();
- } else {
- // Determine the scope of everything up until but not including the last
- // name.
- CPPScope *my_scope = get_scope(scope, nullptr);
- // Strip off template scopes, since they don't add anything particularly
- // meaningful to the local name.
- while (my_scope != nullptr && my_scope->as_template_scope() != nullptr) {
- my_scope = my_scope->get_parent_scope();
- }
- if (my_scope == nullptr) {
- result = get_fully_scoped_name();
- } else if (my_scope == scope) {
- return _names.back().get_name_with_templ(scope);
- } else {
- result = my_scope->get_local_name(scope);
- if (!result.empty()) {
- result += "::";
- }
- result += _names.back().get_name_with_templ(scope);
- }
- }
- return result;
- }
- /**
- *
- */
- string CPPIdentifier::
- get_fully_scoped_name() const {
- assert(!_names.empty());
- Names::const_iterator ni = _names.begin();
- string name = (*ni).get_name_with_templ();
- ++ni;
- while (ni != _names.end()) {
- name += "::" + (*ni).get_name_with_templ();
- ++ni;
- }
- return name;
- }
- /**
- * Returns true if this declaration is an actual, factual declaration, or
- * false if some part of the declaration depends on a template parameter which
- * has not yet been instantiated.
- */
- bool CPPIdentifier::
- is_fully_specified() const {
- Names::const_iterator ni;
- for (ni = _names.begin(); ni != _names.end(); ++ni) {
- if ((*ni).has_templ() && !(*ni).get_templ()->is_fully_specified()) {
- return false;
- }
- }
- return true;
- }
- /**
- * Returns true if the identifier includes a template parameter list that
- * includes some not-yet-defined type.
- */
- bool CPPIdentifier::
- is_tbd() const {
- Names::const_iterator ni;
- for (ni = _names.begin(); ni != _names.end(); ++ni) {
- if ((*ni).is_tbd()) {
- return true;
- }
- }
- return false;
- }
- /**
- *
- */
- CPPScope *CPPIdentifier::
- get_scope(CPPScope *current_scope, CPPScope *global_scope,
- CPPPreprocessor *error_sink) const {
- assert(!_names.empty());
- CPPScope *scope = _native_scope;
- if (scope == nullptr) {
- scope = current_scope;
- }
- int i = 0;
- if (_names[i].empty()) {
- // This identifier starts with a ::, thus it begins at the global scope.
- scope = global_scope;
- i++;
- }
- while (i + 1 < (int)_names.size() && scope != nullptr) {
- // Check for an explicitly specialized scope first.
- CPPScope *next_scope = scope->find_scope(_names[i].get_name_with_templ(), global_scope);
- if (next_scope == nullptr) {
- next_scope = scope->find_scope(_names[i].get_name(), global_scope);
- if (next_scope == nullptr) {
- if (error_sink != nullptr) {
- error_sink->error("Symbol " + _names[i].get_name() +
- " is not a known scope in " +
- scope->get_fully_scoped_name(),
- _loc);
- }
- return nullptr;
- }
- if (_names[i].has_templ()) {
- next_scope = next_scope->instantiate(_names[i].get_templ(),
- current_scope, global_scope);
- }
- }
- scope = next_scope;
- i++;
- }
- return scope;
- }
- /**
- *
- */
- CPPScope *CPPIdentifier::
- get_scope(CPPScope *current_scope, CPPScope *global_scope,
- CPPDeclaration::SubstDecl &subst,
- CPPPreprocessor *error_sink) const {
- assert(!_names.empty());
- CPPScope *scope = _native_scope;
- if (scope == nullptr) {
- scope = current_scope;
- }
- int i = 0;
- if (_names[i].empty()) {
- // This identifier starts with a ::, thus it begins at the global scope.
- scope = global_scope;
- i++;
- }
- while (i + 1 < (int)_names.size() && scope != nullptr) {
- CPPScope *next_scope = scope->find_scope(_names[i].get_name(), subst,
- global_scope);
- if (next_scope == nullptr) {
- if (error_sink != nullptr) {
- error_sink->error("Symbol " + _names[i].get_name() +
- " is not a known scope in " +
- scope->get_fully_scoped_name(),
- _loc);
- }
- return nullptr;
- }
- if (_names[i].has_templ()) {
- next_scope = next_scope->instantiate(_names[i].get_templ(),
- current_scope, global_scope);
- }
- scope = next_scope;
- i++;
- }
- return scope;
- }
- /**
- * Looks up the identifier in the current and/or global scopes, and returns a
- * CPPType pointer if it seems to refer to a type, or NULL if it does not. If
- * force_instantiate is true, the type will be instantiated as fully as
- * possible right now, even if it means instantiating it into an identical
- * template type. Otherwise, the instantiation may be delayed for
- * optimization reasons, and a CPPTBDType placeholder may be returned instead.
- */
- CPPType *CPPIdentifier::
- find_type(CPPScope *current_scope, CPPScope *global_scope,
- bool force_instantiate,
- CPPPreprocessor *error_sink) const {
- CPPScope *scope = get_scope(current_scope, global_scope, error_sink);
- if (scope == nullptr) {
- return nullptr;
- }
- CPPType *type = nullptr;
- if (!_names.back().has_templ()) {
- type = scope->find_type(get_simple_name());
- } else {
- CPPDeclaration *decl = find_symbol(current_scope, global_scope, error_sink);
- type = decl->as_type();
- /*
- if (type != NULL) {
- if (!type->is_incomplete() || force_instantiate) {
- type = type->instantiate(_names.back().get_templ(),
- current_scope, global_scope,
- error_sink)->as_type();
- // If we ended up with another template, instantiate later.
- if (type->is_template() && !force_instantiate) {
- type = CPPType::new_type(new CPPTBDType((CPPIdentifier *)this));
- }
- } else {
- // Otherwise, we'll have to instantiate the type later.
- type = CPPType::new_type(new CPPTBDType((CPPIdentifier *)this));
- }
- // type->_file.replace_nearer(_file);
- }
- */
- }
- return type;
- }
- /**
- * This flavor of find_type() will instantiate any scope names in the
- * identifier. It's useful for fully defining a type while instantiating a
- * class.
- */
- CPPType *CPPIdentifier::
- find_type(CPPScope *current_scope, CPPScope *global_scope,
- CPPDeclaration::SubstDecl &subst,
- CPPPreprocessor *error_sink) const {
- CPPScope *scope = get_scope(current_scope, global_scope, subst, error_sink);
- if (scope == nullptr) {
- return nullptr;
- }
- CPPType *type = scope->find_type(get_simple_name(), subst, global_scope);
- if (type != nullptr && _names.back().has_templ()) {
- // This is a template type.
- if (is_fully_specified()) {
- // If our identifier fully specifies the instantiation, then apply it.
- CPPDeclaration *decl =
- type->instantiate(_names.back().get_templ(),
- current_scope, global_scope,
- error_sink);
- assert(decl != nullptr);
- CPPType *new_type = decl->as_type();
- assert(new_type != nullptr);
- if (new_type == type) {
- type = CPPType::new_type(new CPPTBDType((CPPIdentifier *)this));
- } else {
- type = new_type;
- }
- } else {
- // Otherwise, we'll have to instantiate the type later.
- type = CPPType::new_type(new CPPTBDType((CPPIdentifier *)this));
- }
- // type->_file.replace_nearer(_file);
- }
- return type;
- }
- /**
- *
- */
- CPPDeclaration *CPPIdentifier::
- find_symbol(CPPScope *current_scope, CPPScope *global_scope,
- CPPPreprocessor *error_sink) const {
- CPPScope *scope = get_scope(current_scope, global_scope, error_sink);
- if (scope == nullptr) {
- return nullptr;
- }
- CPPDeclaration *sym;
- if (!_names.back().has_templ()) {
- if (_names.size() > 1 && scope->get_simple_name() == get_simple_name()) {
- /**
- */
- sym = scope->get_struct_type()->get_constructor();
- } else {
- sym = scope->find_symbol(get_simple_name());
- }
- } else {
- sym = scope->find_template(get_simple_name());
- if (sym != nullptr) {
- CPPType *type = sym->as_type();
- if (type != nullptr && type->is_incomplete()) {
- // We can't instantiate an incomplete type.
- sym = CPPType::new_type(new CPPTBDType((CPPIdentifier *)this));
- } else {
- // Instantiate the symbol.
- sym = sym->instantiate(_names.back().get_templ(), current_scope,
- global_scope, error_sink);
- }
- }
- }
- return sym;
- }
- /**
- *
- */
- CPPDeclaration *CPPIdentifier::
- find_symbol(CPPScope *current_scope, CPPScope *global_scope,
- CPPDeclaration::SubstDecl &subst,
- CPPPreprocessor *error_sink) const {
- CPPScope *scope = get_scope(current_scope, global_scope, subst, error_sink);
- if (scope == nullptr) {
- return nullptr;
- }
- CPPDeclaration *sym;
- if (!_names.back().has_templ()) {
- if (_names.size() > 1 && scope->get_simple_name() == get_simple_name()) {
- /**
- */
- sym = scope->get_struct_type()->get_constructor();
- } else {
- sym = scope->find_symbol(get_simple_name());
- }
- } else {
- sym = scope->find_template(get_simple_name());
- if (sym != nullptr) {
- CPPType *type = sym->as_type();
- if (type != nullptr && type->is_incomplete()) {
- // We can't instantiate an incomplete type.
- sym = CPPType::new_type(new CPPTBDType((CPPIdentifier *)this));
- } else {
- // Instantiate the symbol.
- sym = sym->instantiate(_names.back().get_templ(), current_scope,
- global_scope, error_sink);
- }
- }
- }
- return sym;
- }
- /**
- *
- */
- CPPDeclaration *CPPIdentifier::
- find_template(CPPScope *current_scope, CPPScope *global_scope,
- CPPPreprocessor *error_sink) const {
- CPPScope *scope = get_scope(current_scope, global_scope, error_sink);
- if (scope == nullptr) {
- return nullptr;
- }
- return scope->find_template(get_simple_name());
- }
- /**
- *
- */
- CPPScope *CPPIdentifier::
- find_scope(CPPScope *current_scope, CPPScope *global_scope,
- CPPPreprocessor *error_sink) const {
- CPPScope *scope = get_scope(current_scope, global_scope, error_sink);
- if (scope == nullptr) {
- return nullptr;
- }
- return scope->find_scope(get_simple_name(), global_scope);
- }
- /**
- *
- */
- CPPIdentifier *CPPIdentifier::
- substitute_decl(CPPDeclaration::SubstDecl &subst,
- CPPScope *current_scope, CPPScope *global_scope) {
- CPPIdentifier *rep = new CPPIdentifier(*this);
- bool anything_changed = false;
- for (int i = 0; i < (int)rep->_names.size(); ++i) {
- if (_names[i].has_templ()) {
- rep->_names[i].set_templ
- (_names[i].get_templ()->substitute_decl(subst, current_scope, global_scope));
- if (rep->_names[i].get_templ() != _names[i].get_templ()) {
- anything_changed = true;
- }
- }
- }
- if (!anything_changed) {
- delete rep;
- rep = this;
- }
- return rep;
- }
- /**
- *
- */
- void CPPIdentifier::
- output(std::ostream &out, CPPScope *scope) const {
- if (scope == nullptr) {
- output_fully_scoped_name(out);
- } else {
- output_local_name(out, scope);
- }
- }
- /**
- *
- */
- void CPPIdentifier::
- output_local_name(std::ostream &out, CPPScope *scope) const {
- assert(!_names.empty());
- if (scope == nullptr || (_native_scope == nullptr && _names.size() == 1)) {
- out << _names.back();
- } else if (_names.front().empty()) {
- output_fully_scoped_name(out);
- } else {
- // Determine the scope of everything up until but not including the last
- // name.
- CPPScope *my_scope = get_scope(scope, nullptr);
- if (my_scope == nullptr) {
- output_fully_scoped_name(out);
- } else {
- out << my_scope->get_local_name(scope) << "::" << _names.back();
- }
- }
- }
- /**
- *
- */
- void CPPIdentifier::
- output_fully_scoped_name(std::ostream &out) const {
- if (_native_scope != nullptr) {
- _native_scope->output(out, nullptr);
- out << "::";
- }
- Names::const_iterator ni = _names.begin();
- out << (*ni);
- ++ni;
- while (ni != _names.end()) {
- out << "::" << (*ni);
- ++ni;
- }
- }
|