00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "cppStructType.h"
00021 #include "cppTypedef.h"
00022 #include "cppScope.h"
00023 #include "cppTypeProxy.h"
00024 #include "cppTemplateScope.h"
00025 #include "cppFunctionGroup.h"
00026 #include "cppFunctionType.h"
00027 #include "cppTBDType.h"
00028 #include "indent.h"
00029 #include "cppParser.h"
00030
00031
00032
00033
00034
00035
00036 void CPPStructType::Base::
00037 output(ostream &out) const {
00038 if (_is_virtual) {
00039 out << "virtual ";
00040 }
00041 out << _vis << " " << *_base;
00042 }
00043
00044
00045
00046
00047
00048
00049 CPPStructType::
00050 CPPStructType(CPPStructType::Type type, CPPIdentifier *ident,
00051 CPPScope *current_scope, CPPScope *scope,
00052 const CPPFile &file) :
00053 CPPExtensionType(type, ident, current_scope, file),
00054 _scope(scope)
00055 {
00056 _subst_decl_recursive_protect = false;
00057 _incomplete = true;
00058 }
00059
00060
00061
00062
00063
00064
00065 CPPStructType::
00066 CPPStructType(const CPPStructType ©) :
00067 CPPExtensionType(copy),
00068 _scope(copy._scope),
00069 _incomplete(copy._incomplete),
00070 _derivation(copy._derivation)
00071 {
00072 _subst_decl_recursive_protect = false;
00073 }
00074
00075
00076
00077
00078
00079
00080 void CPPStructType::
00081 operator = (const CPPStructType ©) {
00082 CPPExtensionType::operator = (copy);
00083 _scope = copy._scope;
00084 _incomplete = copy._incomplete;
00085 _derivation = copy._derivation;
00086 }
00087
00088
00089
00090
00091
00092
00093
00094
00095 void CPPStructType::
00096 append_derivation(CPPType *base, CPPVisibility vis, bool is_virtual) {
00097 if (base != NULL) {
00098 Base b;
00099 b._base = base;
00100 b._vis = vis;
00101 b._is_virtual = is_virtual;
00102
00103 _derivation.push_back(b);
00104 }
00105 }
00106
00107
00108
00109
00110
00111
00112 CPPScope *CPPStructType::
00113 get_scope() const {
00114 return _scope;
00115 }
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125 bool CPPStructType::
00126 is_abstract() const {
00127 VFunctions funcs;
00128 get_pure_virtual_funcs(funcs);
00129 return !funcs.empty();
00130 }
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148 void CPPStructType::
00149 check_virtual() {
00150 VFunctions funcs;
00151 get_virtual_funcs(funcs);
00152 }
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162 bool CPPStructType::
00163 is_fully_specified() const {
00164 if (_scope != NULL && !_scope->is_fully_specified()) {
00165 return false;
00166 }
00167 return CPPType::is_fully_specified();
00168 }
00169
00170
00171
00172
00173
00174
00175
00176 bool CPPStructType::
00177 is_incomplete() const {
00178 return _incomplete;
00179 }
00180
00181
00182
00183
00184
00185
00186
00187 CPPInstance *CPPStructType::
00188 get_destructor() const {
00189
00190
00191
00192 CPPScope::Functions::const_iterator fi;
00193 fi = _scope->_functions.lower_bound("~");
00194
00195 while (fi != _scope->_functions.end() &&
00196 (*fi).first[0] == '~') {
00197 CPPFunctionGroup *fgroup = (*fi).second;
00198 CPPFunctionGroup::Instances::const_iterator ii;
00199 for (ii = fgroup->_instances.begin();
00200 ii != fgroup->_instances.end();
00201 ++ii) {
00202 CPPInstance *inst = (*ii);
00203 assert(inst->_type != (CPPType *)NULL);
00204
00205 CPPFunctionType *ftype = inst->_type->as_function_type();
00206 assert(ftype != (CPPFunctionType *)NULL);
00207
00208 if ((ftype->_flags & CPPFunctionType::F_destructor) != 0) {
00209 return inst;
00210 }
00211 }
00212 ++fi;
00213 }
00214
00215 return (CPPInstance *)NULL;
00216 }
00217
00218
00219
00220
00221
00222
00223 CPPDeclaration *CPPStructType::
00224 instantiate(const CPPTemplateParameterList *actual_params,
00225 CPPScope *current_scope, CPPScope *global_scope,
00226 CPPPreprocessor *error_sink) const {
00227
00228
00229
00230
00231 if (_scope == NULL) {
00232 if (error_sink != NULL) {
00233 error_sink->warning("Ignoring template parameters for class " +
00234 get_local_name());
00235 }
00236 return (CPPDeclaration *)this;
00237 }
00238
00239 CPPScope *scope =
00240 _scope->instantiate(actual_params, current_scope, global_scope, error_sink);
00241
00242 if (scope->get_struct_type()->get_scope() != scope) {
00243
00244
00245
00246
00247
00248 CPPIdentifier *ident = new CPPIdentifier(get_fully_scoped_name());
00249
00250 return CPPType::new_type(new CPPTBDType(ident));
00251 }
00252
00253 CPPType *result = scope->get_struct_type();
00254 result = CPPType::new_type(result);
00255 if (result != (CPPType *)this) {
00256
00257
00258
00259 ((CPPStructType *)this)->_instantiations.insert(result);
00260 }
00261 return result;
00262 }
00263
00264
00265
00266
00267
00268
00269 CPPDeclaration *CPPStructType::
00270 substitute_decl(CPPDeclaration::SubstDecl &subst,
00271 CPPScope *current_scope, CPPScope *global_scope) {
00272 SubstDecl::const_iterator si = subst.find(this);
00273 if (si != subst.end()) {
00274 assert((*si).second != NULL);
00275 return (*si).second;
00276 }
00277
00278 if (_incomplete) {
00279
00280 return this;
00281 }
00282
00283 if (_subst_decl_recursive_protect) {
00284
00285
00286 CPPTypeProxy *proxy = new CPPTypeProxy;
00287 _proxies.push_back(proxy);
00288 assert(proxy != NULL);
00289 return proxy;
00290 }
00291 _subst_decl_recursive_protect = true;
00292
00293 CPPStructType *rep = new CPPStructType(*this);
00294
00295 if (_ident != NULL) {
00296 rep->_ident =
00297 _ident->substitute_decl(subst, current_scope, global_scope);
00298 }
00299
00300 if (_scope != NULL) {
00301 rep->_scope =
00302 _scope->substitute_decl(subst, current_scope, global_scope);
00303 if (rep->_scope != _scope) {
00304 rep->_scope->set_struct_type(rep);
00305
00306
00307
00308 CPPScope *pscope = rep->_scope->get_parent_scope();
00309
00310 if (pscope != (CPPScope *)NULL &&
00311 pscope->_name.has_templ()) {
00312
00313
00314
00315 if (!_ident->_names.empty() && !_ident->_names.back().has_templ()) {
00316 if (rep->is_template()) {
00317 rep->_template_scope = (CPPTemplateScope *)NULL;
00318 CPPNameComponent nc(get_simple_name());
00319 nc.set_templ(pscope->_name.get_templ());
00320 rep->_ident = new CPPIdentifier(nc);
00321 }
00322 }
00323 }
00324 }
00325 }
00326
00327 bool unchanged =
00328 (rep->_ident == _ident && rep->_scope == _scope);
00329
00330 for (int i = 0; i < (int)_derivation.size(); i++) {
00331 rep->_derivation[i]._base =
00332 _derivation[i]._base->substitute_decl(subst, current_scope, global_scope)->as_type();
00333 if (rep->_derivation[i]._base != _derivation[i]._base) {
00334 unchanged = false;
00335 }
00336 }
00337
00338 if (unchanged) {
00339 delete rep;
00340 rep = this;
00341 }
00342
00343 subst.insert(SubstDecl::value_type(this, rep));
00344
00345 _subst_decl_recursive_protect = false;
00346
00347
00348 Proxies::iterator pi;
00349 for (pi = _proxies.begin(); pi != _proxies.end(); ++pi) {
00350 (*pi)->_actual_type = rep;
00351 }
00352
00353 assert(rep != NULL);
00354 rep = CPPType::new_type(rep)->as_struct_type();
00355 assert(rep != NULL);
00356 if (rep != this) {
00357 _instantiations.insert(rep);
00358
00359 }
00360 return rep;
00361 }
00362
00363
00364
00365
00366
00367
00368 void CPPStructType::
00369 output(ostream &out, int indent_level, CPPScope *scope, bool complete) const {
00370 if (!complete && _ident != NULL) {
00371
00372 if (cppparser_output_class_keyword) {
00373 out << _type << " ";
00374 }
00375 out << _ident->get_local_name(scope);
00376
00377 if (is_template()) {
00378 CPPTemplateScope *tscope = get_template_scope();
00379 out << "< ";
00380 tscope->_parameters.output(out, scope);
00381 out << " >";
00382 }
00383
00384 } else if (!complete && !_typedefs.empty()) {
00385
00386 out << _typedefs.front()->get_local_name(scope);
00387
00388 } else {
00389 if (is_template()) {
00390 get_template_scope()->_parameters.write_formal(out, scope);
00391 indent(out, indent_level);
00392 }
00393 if (_ident != NULL) {
00394 out << _type << " " << _ident->get_local_name(scope);
00395 } else {
00396 out << _type;
00397 }
00398
00399
00400 if (!_derivation.empty()) {
00401 Derivation::const_iterator di = _derivation.begin();
00402 out << ": " << *di;
00403 ++di;
00404 while (di != _derivation.end()) {
00405 out << ", " << *di;
00406 ++di;
00407 }
00408 }
00409
00410 out << " {\n";
00411 _scope->write(out, indent_level + 2, _scope);
00412 indent(out, indent_level) << "}";
00413 }
00414 }
00415
00416
00417
00418
00419
00420
00421 CPPDeclaration::SubType CPPStructType::
00422 get_subtype() const {
00423 return ST_struct;
00424 }
00425
00426
00427
00428
00429
00430
00431 CPPStructType *CPPStructType::
00432 as_struct_type() {
00433 return this;
00434 }
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449 void CPPStructType::
00450 get_virtual_funcs(VFunctions &funcs) const {
00451
00452 Derivation::const_iterator di;
00453 for (di = _derivation.begin(); di != _derivation.end(); ++di) {
00454 VFunctions vf;
00455 CPPStructType *base = (*di)._base->as_struct_type();
00456 if (base != NULL) {
00457 base->get_virtual_funcs(vf);
00458 funcs.splice(funcs.end(), vf);
00459 }
00460 }
00461
00462
00463
00464 VFunctions::iterator vfi, vfnext;
00465 vfi = funcs.begin();
00466 while (vfi != funcs.end()) {
00467 vfnext = vfi;
00468 ++vfnext;
00469
00470 CPPInstance *inst = (*vfi);
00471 assert(inst->_type != (CPPType *)NULL);
00472 CPPFunctionType *base_ftype = inst->_type->as_function_type();
00473 assert(base_ftype != (CPPFunctionType *)NULL);
00474
00475 if ((base_ftype->_flags & CPPFunctionType::F_destructor) != 0) {
00476
00477
00478 CPPInstance *destructor = get_destructor();
00479 if (destructor != (CPPInstance *)NULL) {
00480
00481 funcs.erase(vfi);
00482 destructor->_storage_class |=
00483 (CPPInstance::SC_virtual | CPPInstance::SC_inherited_virtual);
00484 }
00485
00486 } else {
00487
00488 string fname = inst->get_local_name();
00489 CPPScope::Functions::const_iterator fi;
00490 fi = _scope->_functions.find(fname);
00491
00492 if (fi != _scope->_functions.end()) {
00493 CPPFunctionGroup *fgroup = (*fi).second;
00494
00495
00496 bool match_found = false;
00497 CPPFunctionGroup::Instances::const_iterator ii;
00498 for (ii = fgroup->_instances.begin();
00499 ii != fgroup->_instances.end() && !match_found;
00500 ++ii) {
00501 CPPInstance *new_inst = (*ii);
00502 assert(new_inst->_type != (CPPType *)NULL);
00503
00504 CPPFunctionType *new_ftype = new_inst->_type->as_function_type();
00505 assert(new_ftype != (CPPFunctionType *)NULL);
00506
00507 if (new_ftype->is_equivalent_function(*base_ftype)) {
00508
00509
00510 funcs.erase(vfi);
00511 match_found = true;
00512
00513
00514
00515
00516
00517 new_inst->_storage_class |=
00518 (CPPInstance::SC_virtual | CPPInstance::SC_inherited_virtual);
00519 }
00520 }
00521 }
00522 }
00523 vfi = vfnext;
00524 }
00525
00526
00527 CPPScope::Functions::const_iterator fi;
00528 for (fi = _scope->_functions.begin();
00529 fi != _scope->_functions.end();
00530 ++fi) {
00531 CPPFunctionGroup *fgroup = (*fi).second;
00532 CPPFunctionGroup::Instances::const_iterator ii;
00533 for (ii = fgroup->_instances.begin();
00534 ii != fgroup->_instances.end();
00535 ++ii) {
00536 CPPInstance *inst = (*ii);
00537 if ((inst->_storage_class & CPPInstance::SC_virtual) != 0) {
00538
00539 funcs.push_back(inst);
00540 }
00541 }
00542 }
00543 }
00544
00545
00546
00547
00548
00549
00550
00551
00552 void CPPStructType::
00553 get_pure_virtual_funcs(VFunctions &funcs) const {
00554
00555 VFunctions vfuncs;
00556 get_virtual_funcs(vfuncs);
00557
00558
00559
00560 VFunctions::iterator vfi;
00561 for (vfi = vfuncs.begin(); vfi != vfuncs.end(); ++vfi) {
00562 CPPInstance *inst = (*vfi);
00563 if ((inst->_storage_class & CPPInstance::SC_pure_virtual) != 0) {
00564 funcs.push_back(inst);
00565 }
00566 }
00567 }
00568
00569
00570
00571
00572
00573
00574
00575 bool CPPStructType::
00576 is_equal(const CPPDeclaration *other) const {
00577 return CPPDeclaration::is_equal(other);
00578
00579
00580
00581
00582
00583
00584
00585 }
00586
00587
00588
00589
00590
00591
00592
00593
00594 bool CPPStructType::
00595 is_less(const CPPDeclaration *other) const {
00596 return CPPDeclaration::is_less(other);
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608 }
00609