00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "cppInstance.h"
00021 #include "cppInstanceIdentifier.h"
00022 #include "cppIdentifier.h"
00023 #include "cppTemplateScope.h"
00024 #include "cppFunctionType.h"
00025 #include "cppSimpleType.h"
00026 #include "cppExpression.h"
00027 #include "cppPreprocessor.h"
00028 #include "indent.h"
00029
00030 #include "cppReferenceType.h"
00031 #include "cppConstType.h"
00032
00033 #include <algorithm>
00034
00035
00036
00037
00038
00039
00040 CPPInstance::
00041 CPPInstance(CPPType *type, const string &name, int storage_class) :
00042 CPPDeclaration(CPPFile()),
00043 _type(type),
00044 _ident(new CPPIdentifier(name)),
00045 _storage_class(storage_class)
00046 {
00047 _initializer = NULL;
00048 }
00049
00050
00051
00052
00053
00054
00055 CPPInstance::
00056 CPPInstance(CPPType *type, CPPIdentifier *ident, int storage_class) :
00057 CPPDeclaration(CPPFile()),
00058 _type(type),
00059 _ident(ident),
00060 _storage_class(storage_class)
00061 {
00062 _initializer = NULL;
00063 }
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073 CPPInstance::
00074 CPPInstance(CPPType *type, CPPInstanceIdentifier *ii, int storage_class,
00075 const CPPFile &file) :
00076 CPPDeclaration(file)
00077 {
00078 _type = ii->unroll_type(type);
00079 _ident = ii->_ident;
00080 ii->_ident = NULL;
00081 _storage_class = storage_class;
00082 delete ii;
00083 _initializer = NULL;
00084 }
00085
00086
00087
00088
00089
00090
00091 CPPInstance::
00092 CPPInstance(const CPPInstance ©) :
00093 CPPDeclaration(copy),
00094 _type(copy._type),
00095 _ident(copy._ident),
00096 _initializer(copy._initializer),
00097 _storage_class(copy._storage_class)
00098 {
00099 assert(_type != NULL);
00100 }
00101
00102
00103
00104
00105
00106
00107 CPPInstance::
00108 ~CPPInstance() {
00109
00110 }
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121 CPPInstance *CPPInstance::
00122 make_typecast_function(CPPInstance *inst, CPPIdentifier *ident,
00123 CPPParameterList *parameters, int function_flags) {
00124 CPPType *type = CPPType::new_type(inst->_type);
00125 delete inst;
00126
00127 function_flags |= (int)CPPFunctionType::F_operator_typecast;
00128
00129 CPPType *ft =
00130 CPPType::new_type(new CPPFunctionType(type, parameters, function_flags));
00131
00132 return new CPPInstance(ft, ident);
00133 }
00134
00135
00136
00137
00138
00139
00140 bool CPPInstance::
00141 operator == (const CPPInstance &other) const {
00142 if (_type != other._type) {
00143 return false;
00144 }
00145 if (_storage_class != other._storage_class) {
00146 return false;
00147 }
00148
00149
00150
00151
00152 if ((_ident == NULL && other._ident != NULL) ||
00153 (_ident != NULL && other._ident == NULL) ||
00154 (_ident != NULL && other._ident != NULL && *_ident != *other._ident))
00155 {
00156 return false;
00157 }
00158
00159
00160 if ((_initializer == NULL && other._initializer != NULL) ||
00161 (_initializer != NULL && other._initializer == NULL) ||
00162 (_initializer != NULL && other._initializer != NULL &&
00163 *_initializer != *other._initializer))
00164 {
00165 return false;
00166 }
00167
00168 return true;
00169 }
00170
00171
00172
00173
00174
00175
00176 bool CPPInstance::
00177 operator != (const CPPInstance &other) const {
00178 return !operator == (other);
00179 }
00180
00181
00182
00183
00184
00185
00186 bool CPPInstance::
00187 operator < (const CPPInstance &other) const {
00188 if (_type != other._type) {
00189 return _type < other._type;
00190 }
00191 if (_storage_class != other._storage_class) {
00192 return _storage_class < other._storage_class;
00193 }
00194
00195
00196
00197
00198 if ((_ident == NULL && other._ident != NULL) ||
00199 (_ident != NULL && other._ident == NULL) ||
00200 (_ident != NULL && other._ident != NULL && *_ident != *other._ident))
00201 {
00202 if (_ident == NULL || other._ident == NULL) {
00203 return _ident < other._ident;
00204 }
00205 return *_ident < *other._ident;
00206 }
00207
00208
00209 if ((_initializer == NULL && other._initializer != NULL) ||
00210 (_initializer != NULL && other._initializer == NULL) ||
00211 (_initializer != NULL && other._initializer != NULL &&
00212 *_initializer != *other._initializer))
00213 {
00214 if (_initializer == NULL || other._initializer == NULL) {
00215 return _initializer < other._initializer;
00216 }
00217 return *_initializer < *other._initializer;
00218 }
00219
00220 return false;
00221 }
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232 void CPPInstance::
00233 set_initializer(CPPExpression *initializer) {
00234 if (_type->as_function_type() != (CPPFunctionType *)NULL) {
00235
00236 if (initializer == (CPPExpression *)NULL) {
00237 _storage_class &= ~SC_pure_virtual;
00238 } else {
00239 _storage_class |= SC_pure_virtual;
00240 }
00241 _initializer = (CPPExpression *)NULL;
00242 } else {
00243 _initializer = initializer;
00244 }
00245 }
00246
00247
00248
00249
00250
00251
00252 bool CPPInstance::
00253 is_scoped() const {
00254 if (_ident == NULL) {
00255 return false;
00256 } else {
00257 return _ident->is_scoped();
00258 }
00259 }
00260
00261
00262
00263
00264
00265
00266 CPPScope *CPPInstance::
00267 get_scope(CPPScope *current_scope, CPPScope *global_scope,
00268 CPPPreprocessor *error_sink) const {
00269 if (_ident == NULL) {
00270 return current_scope;
00271 } else {
00272 return _ident->get_scope(current_scope, global_scope, error_sink);
00273 }
00274 }
00275
00276
00277
00278
00279
00280
00281 string CPPInstance::
00282 get_simple_name() const {
00283 if (_ident == NULL) {
00284 return "";
00285 } else {
00286 return _ident->get_simple_name();
00287 }
00288 }
00289
00290
00291
00292
00293
00294
00295 string CPPInstance::
00296 get_local_name(CPPScope *scope) const {
00297 if (_ident == NULL) {
00298 return "";
00299 } else {
00300 return _ident->get_local_name(scope);
00301 }
00302 }
00303
00304
00305
00306
00307
00308
00309 string CPPInstance::
00310 get_fully_scoped_name() const {
00311 if (_ident == NULL) {
00312 return "";
00313 } else {
00314 return _ident->get_fully_scoped_name();
00315 }
00316 }
00317
00318
00319
00320
00321
00322
00323
00324
00325 void CPPInstance::
00326 check_for_constructor(CPPScope *current_scope, CPPScope *global_scope) {
00327 CPPScope *scope = get_scope(current_scope, global_scope);
00328 if (scope == NULL) {
00329 scope = current_scope;
00330 }
00331
00332 CPPFunctionType *func = _type->as_function_type();
00333 if (func != NULL) {
00334 string method_name = get_local_name(scope);
00335 string class_name = scope->get_local_name();
00336
00337 if (!method_name.empty() && !class_name.empty()) {
00338 if (method_name == class_name) {
00339 CPPType *void_type = CPPType::new_type
00340 (new CPPSimpleType(CPPSimpleType::T_void));
00341
00342 _type = CPPType::new_type
00343 (new CPPFunctionType(void_type, func->_parameters,
00344 func->_flags | CPPFunctionType::F_constructor));
00345
00346 } else if (method_name == "~" + class_name) {
00347 CPPType *void_type = CPPType::new_type
00348 (new CPPSimpleType(CPPSimpleType::T_void));
00349
00350 _type = CPPType::new_type
00351 (new CPPFunctionType(void_type, func->_parameters,
00352 func->_flags | CPPFunctionType::F_destructor));
00353 }
00354 }
00355 }
00356 }
00357
00358
00359
00360
00361
00362
00363 CPPDeclaration *CPPInstance::
00364 instantiate(const CPPTemplateParameterList *actual_params,
00365 CPPScope *current_scope, CPPScope *global_scope,
00366 CPPPreprocessor *error_sink) const {
00367 if (!is_template()) {
00368 if (error_sink != NULL) {
00369 error_sink->warning("Ignoring template parameters for instance " +
00370 _ident->get_local_name());
00371 }
00372 return (CPPInstance *)this;
00373 }
00374
00375 Instantiations::const_iterator ii;
00376 ii = _instantiations.find(actual_params);
00377 if (ii != _instantiations.end()) {
00378
00379
00380 return (*ii).second;
00381 }
00382
00383
00384 CPPTemplateScope *tscope = get_template_scope();
00385
00386 CPPDeclaration::SubstDecl subst;
00387 actual_params->build_subst_decl(tscope->_parameters, subst,
00388 current_scope, global_scope);
00389
00390 CPPInstance *inst =
00391 ((CPPInstance *)this)->substitute_decl(subst, current_scope, global_scope)
00392 ->as_instance();
00393 if (inst == this) {
00394
00395
00396 inst = new CPPInstance(*this);
00397 }
00398 assert(inst != NULL);
00399 inst->_ident = inst->_ident->substitute_decl(subst, current_scope, global_scope);
00400 if (inst->_ident == _ident) {
00401 inst->_ident = new CPPIdentifier(*inst->_ident);
00402 }
00403 inst->_ident->_names.back().set_templ
00404 (new CPPTemplateParameterList(*actual_params));
00405
00406 inst->_template_scope = NULL;
00407
00408 ((CPPInstance *)this)->_instantiations.insert(Instantiations::value_type(actual_params, inst));
00409 return inst;
00410 }
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420 bool CPPInstance::
00421 is_fully_specified() const {
00422 if (_ident != NULL && !_ident->is_fully_specified()) {
00423 return false;
00424 }
00425 if (_initializer != NULL && !_initializer->is_fully_specified()) {
00426 return false;
00427 }
00428 return CPPDeclaration::is_fully_specified() &&
00429 _type->is_fully_specified();
00430 }
00431
00432
00433
00434
00435
00436
00437 CPPDeclaration *CPPInstance::
00438 substitute_decl(CPPDeclaration::SubstDecl &subst,
00439 CPPScope *current_scope, CPPScope *global_scope) {
00440 CPPDeclaration *top =
00441 CPPDeclaration::substitute_decl(subst, current_scope, global_scope);
00442 if (top != this) {
00443 return top;
00444 }
00445
00446 CPPInstance *rep = new CPPInstance(*this);
00447 CPPDeclaration *new_type =
00448 _type->substitute_decl(subst, current_scope, global_scope);
00449 rep->_type = new_type->as_type();
00450
00451 if (rep->_type == NULL) {
00452 cerr << "Type " << *_type << " became " << *new_type << " which isn't a type\n";
00453 rep->_type = _type;
00454 }
00455
00456 if (_initializer != NULL) {
00457 rep->_initializer =
00458 _initializer->substitute_decl(subst, current_scope, global_scope)
00459 ->as_expression();
00460 }
00461
00462 if (rep->_type == _type &&
00463 rep->_initializer == _initializer) {
00464 delete rep;
00465 rep = this;
00466 }
00467
00468 subst.insert(SubstDecl::value_type(this, rep));
00469 return rep;
00470 }
00471
00472
00473
00474
00475
00476
00477 void CPPInstance::
00478 output(ostream &out, int indent_level, CPPScope *scope, bool complete) const {
00479 output(out, indent_level, scope, complete, -1);
00480 }
00481
00482
00483
00484
00485
00486
00487
00488
00489 void CPPInstance::
00490 output(ostream &out, int indent_level, CPPScope *scope, bool complete,
00491 int num_default_parameters) const {
00492 if (is_template()) {
00493 get_template_scope()->_parameters.write_formal(out, scope);
00494 indent(out, indent_level);
00495 }
00496 if (_storage_class & SC_static) {
00497 out << "static ";
00498 }
00499 if (_storage_class & SC_extern) {
00500 out << "extern ";
00501 }
00502 if (_storage_class & SC_c_binding) {
00503 out << "\"C\" ";
00504 }
00505 if (_storage_class & SC_virtual) {
00506 out << "virtual ";
00507 }
00508 if (_storage_class & SC_inline) {
00509 out << "inline ";
00510 }
00511 if (_storage_class & SC_explicit) {
00512 out << "explicit ";
00513 }
00514 if (_storage_class & SC_register) {
00515 out << "register ";
00516 }
00517 if (_storage_class & SC_volatile) {
00518 out << "volatile ";
00519 }
00520 if (_storage_class & SC_mutable) {
00521 out << "mutable ";
00522 }
00523
00524 string name;
00525 if (_ident != NULL) {
00526 name = _ident->get_local_name(scope);
00527 }
00528 assert(_type != NULL);
00529
00530 if (_type->as_function_type()) {
00531 _type->as_function_type()->
00532 output_instance(out, indent_level, scope, complete, "", name,
00533 num_default_parameters);
00534 } else {
00535 _type->output_instance(out, indent_level, scope, complete, "", name);
00536 }
00537
00538 if (_storage_class & SC_pure_virtual) {
00539 out << " = 0";
00540 }
00541 if (_initializer != NULL) {
00542 out << " = (" << *_initializer << ")";
00543 }
00544 }
00545
00546
00547
00548
00549
00550
00551
00552 CPPDeclaration::SubType CPPInstance::
00553 get_subtype() const {
00554 return ST_instance;
00555 }
00556
00557
00558
00559
00560
00561
00562 CPPInstance *CPPInstance::
00563 as_instance() {
00564 return this;
00565 }