00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "config.h"
00020
00021 #include "EDoc/Function.h"
00022 #include "EDoc/Type.h"
00023 #include "EDoc/FunctionType.h"
00024 #include "EDoc/Dictionary.h"
00025 #include "EDoc/PersistenceIFace.h"
00026 #include "EDoc/exceptions.h"
00027 #include "EDoc/Logger.h"
00028 #include "EDoc/utils.h"
00029 #include "EDoc/PStack.h"
00030 #include "EDoc/StackRef.h"
00031 #include "EDoc/NotificationIFace.h"
00032
00033 #include "EDoc/persistence_data.h"
00034 #include "IndexedDictionary.h"
00035
00036 #include <sstream>
00037
00038 #ifdef HAVE_STRING_H
00039 #include <string.h>
00040 #endif
00041
00042 namespace EDoc
00043 {
00044
00045 uint8_t Function::GetRecordType() const
00046 {
00047 return VALUE_RECORD_TYPE_FUNCTION;
00048 }
00049
00050 Function::Function(Dictionary& dict_in, std::string key_name_in) :
00051 StringIdentifiedObject(dict_in, key_name_in),
00052 is_public(false),
00053 is_inline(false),
00054 is_implicit(false),
00055 has_exception_spec(false),
00056 function_pointer_type(NULL),
00057 loc(&dict_in),
00058 exceptions_enabled(true),
00059 processed_implementations(0),
00060 translation_unit(NULL),
00061 implementation(&dict),
00062 calculated_propogating_exceptions(false),
00063 visible(true),
00064 subst_exception(NULL),
00065 total_calls(-1),
00066 circular(NULL),
00067 on_processed(NULL),
00068 on_processed_data(NULL)
00069 {
00070 }
00071
00072 Function::Function(Dictionary& dict_in, int32_t index_in) :
00073 StringIdentifiedObject(dict_in, index_in),
00074 is_public(false),
00075 is_inline(false),
00076 is_implicit(false),
00077 has_exception_spec(false),
00078 function_pointer_type(NULL),
00079 loc(&dict_in),
00080 exceptions_enabled(true),
00081 processed_implementations(0),
00082 translation_unit(NULL),
00083 implementation(&dict),
00084 calculated_propogating_exceptions(false),
00085 visible(true),
00086 subst_exception(NULL),
00087 total_calls(-1),
00088 circular(NULL),
00089 on_processed(NULL),
00090 on_processed_data(NULL)
00091 {
00092 }
00093
00094 Function::~Function()
00095 {
00096 RemoveFromCircular();
00097 delete subst_exception;
00098 subst_exception = NULL;
00099 }
00100
00101 void Function::RemoveFromCircular()
00102 {
00103 if (circular)
00104 {
00105
00106 std::set<Function*>::iterator it = circular->find(this);
00107 EDOC_ASSERT(it != circular->end(), "");
00108 circular->erase(it);
00109
00110
00111 if (circular->size() == 0)
00112 {
00113 delete circular;
00114 }
00115 circular = NULL;
00116 }
00117 }
00118
00119 Function& Function::operator=(const Function& right)
00120 {
00121
00122 if (this == &right)
00123 {
00124 return *this;
00125 }
00126
00127 EDOC_Finer("Assign-Merging primitives.");
00128 link_name = right.link_name;
00129 full_name = right.full_name;
00130 is_public = right.is_public;
00131 is_inline = right.is_inline;
00132 is_implicit = right.is_implicit;
00133 translation_unit = right.translation_unit;
00134
00135 has_exception_spec = right.has_exception_spec;
00136 calculated_propogating_exceptions =
00137 right.calculated_propogating_exceptions;
00138
00139 Erase(propogating_exceptions);
00140
00141 loc = right.loc;
00142
00143 Erase(exception_spec);
00144 for (size_t i = 0; i < right.exception_spec.size(); i++)
00145 {
00146 exception_spec.push_back(
00147 dict.types.AlwaysGet(*right.exception_spec[i]));
00148 }
00149
00150 Erase(address_taken);
00151 for (size_t i = 0; i < right.address_taken.size(); i++)
00152 {
00153 address_taken.push_back(Location(&dict));
00154 address_taken.back() = right.address_taken[i];
00155 }
00156
00157 Erase(derived_virtuals);
00158 for (size_t i = 0; i < right.derived_virtuals.size(); i++)
00159 {
00160 derived_virtuals.push_back(
00161 dict.functions.AlwaysGet(
00162 *right.derived_virtuals[i]));
00163 }
00164
00165 function_pointer_type = NULL;
00166 if (right.function_pointer_type)
00167 {
00168 function_pointer_type = dict.function_types.AlwaysGet(
00169 *right.function_pointer_type);
00170 }
00171
00172 exceptions_enabled = right.exceptions_enabled;
00173
00174 processed_implementations = right.processed_implementations;
00175
00176 EDOC_Finer("Assign-Merging : Merging implementations.");
00177 EDOC_Finer("Right implementation is: " << right.implementation);
00178 implementation = right.implementation;
00179 EDOC_Finer("Our implementation is: " << implementation);
00180
00181 populated = right.populated;
00182
00183
00184 Erase(referenced_in_files);
00185 EDOC_FOREACH_CONST(FilePList, it, right.referenced_in_files)
00186 {
00187 referenced_in_files.push_back(
00188 dict.files.AlwaysGet(*(*it)));
00189 }
00190
00191 visible = right.visible;
00192 return *this;
00193 }
00194
00195 void Function::Read(PersistenceIFace& file, IndexedDictionary& idict)
00196 {
00197 size_t size = 0;
00198
00199 link_name = file.ReadString(KEY_LINK_NAME);
00200 full_name = file.ReadString(KEY_FULL_NAME);
00201 is_public = file.ReadBoolean(KEY_IS_PUBLIC);
00202 is_inline = file.ReadBoolean(KEY_IS_INLINE);
00203 is_implicit = file.ReadBoolean(KEY_IS_IMPLICIT);
00204 translation_unit = dict.GetIndexedTranslationUnit(
00205 file.ReadUInt32(KEY_TRANSLATION_UNIT));
00206 loc.Read(file, idict);
00207
00208 has_exception_spec = file.ReadBoolean(KEY_HAS_EXCEPTION_SPEC);
00209 if (has_exception_spec)
00210 {
00211 size = file.ReadUInt32(KEY_EXCEPTION_SPEC_LS);
00212 for (size_t i = 0; i < size; i++)
00213 {
00214 exception_spec.push_back(
00215 idict.types.AlwaysGet(file.ReadUInt32(KEY_EXCEPTION_SPEC_LI)));
00216 }
00217 }
00218
00219 size = file.ReadUInt32(KEY_DERIVED_VIRT_LS);
00220 for (size_t i = 0; i < size; i++)
00221 {
00222 derived_virtuals.push_back(
00223 idict.functions.AlwaysGet(
00224 file.ReadUInt32(KEY_DERIVED_VIRT_LI)));
00225 }
00226
00227 size = file.ReadUInt32(KEY_ADDRESS_TAKEN_LS);
00228 for (size_t i = 0; i < size; i++)
00229 {
00230 Location l(&dict);
00231 l.Read(file, idict);
00232 address_taken.push_back(loc);
00233 }
00234 if (address_taken.size())
00235 {
00236 function_pointer_type = idict.function_types.AlwaysGet(
00237 file.ReadUInt32(KEY_FUNCTION_TYPE));
00238 }
00239
00240
00241 size = file.ReadUInt32(KEY_REFERENCE_FILES_LS);
00242 for (size_t i = 0; i < size; i++)
00243 {
00244 referenced_in_files.push_back(
00245 idict.files.AlwaysGet(file.ReadUInt32(KEY_REFERENCE_FILE)));
00246 }
00247
00248 exceptions_enabled = file.ReadBoolean(KEY_EXCEPTIONS_ENABLED);
00249
00250
00251 processed_implementations = file.ReadUInt32(KEY_PROCESSED_IMPLEMENTATION);
00252 if (processed_implementations)
00253 {
00254 EDOC_Finer("Reading implementation.");
00255 implementation.Read(file, idict);
00256 EDOC_Finer("Done reading implementation.");
00257 }
00258
00259
00260
00261
00262
00263
00264
00265 populated = true;
00266 if (is_public && !is_inline)
00267 {
00268 SetKeyName(link_name);
00269 }
00270 else
00271 {
00272
00273
00274
00275
00276 if (referenced_in_files.size() != 1)
00277 {
00278 EDOC_THROW_EXCEPTION(FileIOException,
00279 "All private functions should be referenced in exactly "
00280 "1 translation unit.", "");
00281 }
00282
00283 std::ostringstream stream;
00284 stream << link_name << ":" << translation_unit->GetID() << ":"
00285 << translation_unit->GetName();
00286 SetKeyName(stream.str());
00287 }
00288 }
00289
00290 void Function::Write(PersistenceIFace& file) const
00291 {
00292 file.WriteString(KEY_LINK_NAME, link_name);
00293 file.WriteString(KEY_FULL_NAME, full_name);
00294 file.WriteBoolean(KEY_IS_PUBLIC, is_public);
00295 file.WriteBoolean(KEY_IS_INLINE, is_inline);
00296 file.WriteBoolean(KEY_IS_IMPLICIT, is_implicit);
00297 file.WriteUInt32Debug(KEY_TRANSLATION_UNIT,
00298 dict.GetTranslationUnitIndex(translation_unit),
00299 translation_unit->GetName());
00300 loc.Write(file);
00301
00302 file.WriteBoolean(KEY_HAS_EXCEPTION_SPEC, has_exception_spec);
00303 if (has_exception_spec)
00304 {
00305 file.WriteUInt32(KEY_EXCEPTION_SPEC_LS, exception_spec.size());
00306 for (size_t i = 0; i < exception_spec.size(); i++)
00307 {
00308 file.WriteUInt32Debug(KEY_EXCEPTION_SPEC_LI,
00309 exception_spec[i]->GetIndex(),
00310 exception_spec[i]->GetDeclaredName());
00311 }
00312 }
00313
00314 file.WriteUInt32(KEY_DERIVED_VIRT_LS,
00315 derived_virtuals.size());
00316 for (size_t i = 0; i < derived_virtuals.size(); i++)
00317 {
00318 file.WriteUInt32Debug(KEY_DERIVED_VIRT_LI,
00319 derived_virtuals[i]->GetIndex(),
00320 derived_virtuals[i]->GetDeclaredName());
00321 }
00322
00323
00324 file.WriteUInt32(KEY_ADDRESS_TAKEN_LS, address_taken.size());
00325 for (size_t i = 0; i < address_taken.size(); i++)
00326 {
00327 address_taken[i].Write(file);
00328 }
00329
00330 if (address_taken.size())
00331 {
00332 file.WriteUInt32Debug(KEY_FUNCTION_TYPE,
00333 function_pointer_type->GetIndex(),
00334 function_pointer_type->GetKeyName());
00335 }
00336
00337 file.WriteUInt32(KEY_REFERENCE_FILES_LS, referenced_in_files.size());
00338 EDOC_FOREACH_CONST(FilePList, it, referenced_in_files)
00339 {
00340 file.WriteUInt32Debug(KEY_REFERENCE_FILE,
00341 (*it)->GetIndex(),
00342 (*it)->GetKeyName());
00343 }
00344
00345 file.WriteBoolean(KEY_EXCEPTIONS_ENABLED, exceptions_enabled);
00346
00347 file.WriteUInt32(KEY_PROCESSED_IMPLEMENTATION, processed_implementations);
00348 if (processed_implementations)
00349 {
00350 implementation.Write(file);
00351 }
00352 }
00353
00354 std::ostream& Function::Print(std::ostream& out, std::string prefix) const
00355 {
00356 out << prefix << "Link Name: " << link_name << std::endl;
00357 out << prefix << "Declared Name: " << full_name << std::endl;
00358 if (is_public)
00359 {
00360 out << prefix << "Is Public: True" << std::endl;
00361 }
00362 else
00363 {
00364 out << prefix << "Is Public: False" << std::endl;
00365 }
00366
00367 if (is_inline)
00368 {
00369 out << prefix << "Is Inline: True" << std::endl;
00370 }
00371 else
00372 {
00373 out << prefix << "Is Inline: False" << std::endl;
00374 }
00375
00376 if (is_implicit)
00377 {
00378 out << prefix << "Is Implicit: True" << std::endl;
00379 }
00380 else
00381 {
00382 out << prefix << "Is Implicit: False" << std::endl;
00383 }
00384
00385 if (has_exception_spec)
00386 {
00387 out << prefix << "Has Throw Spec: True" << std::endl;
00388 out << prefix << "Throw spec: " << GetSpecString() << std::endl;
00389 }
00390 else
00391 {
00392 out << prefix << "Has Throw Spec: False" << std::endl;
00393 }
00394
00395 for (size_t i = 0; i < derived_virtuals.size(); i++)
00396 {
00397 out << prefix << "Virtual Call through: "
00398 << derived_virtuals[i]->GetDeclaredName() << " "
00399 << derived_virtuals[i]->GetSpecString() << std::endl;
00400 }
00401
00402 for (size_t i = 0; i < address_taken.size(); i++)
00403 {
00404 out << prefix << "Address taken at: ";
00405 address_taken[i].SingleLinePrint(out);
00406 out << std::endl;
00407 }
00408 if (address_taken.size())
00409 {
00410 out << prefix << "Function Pointer Type: "
00411 << function_pointer_type->GetKeyName() << std::endl;
00412 }
00413
00414 loc.Print(out, prefix) << std::endl;
00415
00416 if (exceptions_enabled)
00417 {
00418 out << prefix << "Exceptions enabled: True" << std::endl;
00419 }
00420 else
00421 {
00422 out << prefix << "Exceptions enabled: False" << std::endl;
00423 }
00424
00425 out << prefix << "Implementation processed: "
00426 << processed_implementations << std::endl;
00427
00428 out << prefix << GetDeclaredName() << GetSpecString() << std::endl;
00429 if (processed_implementations)
00430 {
00431 implementation.Print(out, prefix);
00432 }
00433
00434 if (calculated_propogating_exceptions)
00435 {
00436 out << prefix << "Calculated Propogating Exceptions: True" << std::endl;
00437 }
00438 else
00439 {
00440 out << prefix << "Calculated Propogating Exceptions: False" << std::endl;
00441 }
00442
00443 EDOC_FOREACH_CONST(PropExcepList, it, propogating_exceptions)
00444 {
00445 out << prefix << INDENT_STR << "P: " << it->exception->type.value->GetDeclaredName() << std::endl;
00446 }
00447
00448 out << prefix << "total_calls: " << total_calls << std::endl;
00449 if (circular)
00450 {
00451 out << prefix << "Part of circular callgraph along with:" << std::endl;
00452 EDOC_FOREACH_CONST(std::set<Function*>, it, *circular)
00453 {
00454 out << prefix << INDENT_STR
00455 << (*it)->GetDeclaredName() << " "
00456 << (*it)->GetSpecString() << std::endl;
00457 }
00458 }
00459 else
00460 {
00461 out << prefix << "NOT part of circular callgraph (or not yet calculated)." << std::endl;
00462 }
00463 return out;
00464 }
00465
00466
00467
00468
00469 #define EDOC_MERGE_ERROR(Message) \
00470 EDOC_Error("Function Name: " << GetKeyName() \
00471 << "\nMessage: " << Message); \
00472 EDOC_THROW_EXCEPTION(MergeException, "Failed merging function.", Message);
00473
00474
00475 void Function::Merge(const StringIdentifiedObject& right_in)
00476 {
00477 const Function& right(dynamic_cast<const Function&>(right_in));
00478
00479
00480
00481
00482 if (!populated)
00483 {
00484 EDOC_Finer("This function has not been populated so doing an "
00485 "assign merge from the right function.");
00486 *this = right;
00487 return;
00488 }
00489
00490 EDOC_Finer("Doing complex merge of function.");
00491 if (GetKeyName() != right.GetKeyName())
00492 {
00493 EDOC_MERGE_ERROR("Unable to merge two types with different names. "
00494 "Left: " << GetKeyName() << ", right: "
00495 << right.GetKeyName());
00496
00497 }
00498
00499
00500
00501
00502
00503 if (link_name != right.link_name)
00504 {
00505 EDOC_MERGE_ERROR("Unable to merge two functions with different names. "
00506 "Left: " << link_name << ", right: "
00507 << right.link_name);
00508
00509 }
00510
00511 if (is_public != right.is_public)
00512 {
00513 EDOC_MERGE_ERROR("Unable to merge two functions when one is public "
00514 "and the other is private to a translation unit.");
00515 }
00516
00517 if (is_inline != right.is_inline)
00518 {
00519 EDOC_MERGE_ERROR("Unable to merge two functions when one is inlined "
00520 "and the other is not.");
00521 }
00522
00523 if (processed_implementations && right.processed_implementations &&
00524 (exceptions_enabled != right.exceptions_enabled))
00525 {
00526 EDOC_MERGE_ERROR("Unable to merge two functions which have two "
00527 "implementations where one implementation has been processed "
00528 "with exceptions enabled and the other without. "
00529 << "Left Function: " << GetKeyName()
00530 << ", Right Function: " << right.GetKeyName()
00531 << ", Left Declared Name: " << GetDeclaredName()
00532 << ", Right Declared Name: " << right.GetDeclaredName()
00533 << ", Left Location: " << loc
00534 << ", Right Location: " << right.loc
00535 << ", Left Ref in Files: " << GetRefInFilesString()
00536 << ", Right Ref in Files: " << right.GetRefInFilesString());
00537 }
00538
00539 if (function_pointer_type && right.function_pointer_type &&
00540 (function_pointer_type->GetKeyName() !=
00541 right.function_pointer_type->GetKeyName()))
00542 {
00543 EDOC_MERGE_ERROR("Cant merge two functions with different types."
00544 " left: " << function_pointer_type->GetKeyName()
00545 << ", right: " << right.function_pointer_type->GetKeyName());
00546 }
00547
00548
00549
00550 if (!full_name.size())
00551 {
00552 full_name = right.full_name;
00553 }
00554
00555
00556
00557
00558 if (!processed_implementations && right.processed_implementations)
00559 {
00560 exceptions_enabled = right.exceptions_enabled;
00561 }
00562
00563
00564
00565 bool exception_specs_differ = false;
00566 if (has_exception_spec != right.has_exception_spec)
00567 {
00568 exception_specs_differ = true;
00569 }
00570
00571
00572 if (!exception_specs_differ &&
00573 (exception_spec.size() != right.exception_spec.size()))
00574 {
00575 exception_specs_differ = true;
00576 }
00577 for (size_t i = 0; !exception_specs_differ && (i < exception_spec.size());
00578 i++)
00579 {
00580 bool found = false;
00581 for (size_t j = 0; j < right.exception_spec.size(); j++)
00582 {
00583 if (right.exception_spec[j]->GetNormalisedName() ==
00584 exception_spec[i]->GetNormalisedName())
00585 {
00586 found = true;
00587 break;
00588 }
00589 }
00590
00591 if (!found)
00592 {
00593 exception_specs_differ = true;
00594 }
00595 }
00596
00597
00598 if (exception_specs_differ)
00599 {
00600 EDOC_NOTIFICATION(WDIFF_THROW,
00601 "Function: " << GetKeyName()
00602 << ", Declared Name: " << GetDeclaredName()
00603 << ", Left Spec: " << GetSpecString()
00604 << ", Right Spec: " << right.GetSpecString(),
00605 this, loc.file, loc.line, right.loc.file, right.loc.line,
00606 NULL, NULL, NULL, NULL);
00607
00608
00609
00610
00611
00612
00613 EDOC_Warning("Merging two functions with different exception specs."
00614 << "\nLeft Spec: " << GetSpecString()
00615 << "\nRight Spec: " << right.GetSpecString()
00616 << "\nFunction Name: " << GetKeyName());
00617
00618 has_exception_spec = true;
00619 std::vector<Type*> merged_spec;
00620
00621
00622 for (size_t i = 0; i < exception_spec.size(); i++)
00623 {
00624 bool found = false;
00625 for (size_t j = 0; j < right.exception_spec.size(); j++)
00626 {
00627 if (right.exception_spec[j]->GetNormalisedName() ==
00628 exception_spec[i]->GetNormalisedName())
00629 {
00630 found = true;
00631 break;
00632 }
00633 }
00634
00635 if (found)
00636 {
00637 merged_spec.push_back(exception_spec[i]);
00638 }
00639 }
00640 exception_spec = merged_spec;
00641
00642 EDOC_Warning("Resulting merged spec is: " << GetSpecString());
00643 }
00644
00645
00646
00647
00648 if (!right.is_implicit)
00649 {
00650
00651 is_implicit = false;
00652 }
00653
00654
00655 for (size_t i = 0; i < right.derived_virtuals.size(); i++)
00656 {
00657 bool found = false;
00658 for (size_t j = 0; j < derived_virtuals.size(); j++)
00659 {
00660 if (right.derived_virtuals[i]->GetKeyName() ==
00661 derived_virtuals[j]->GetKeyName())
00662 {
00663 found = true;
00664 break;
00665 }
00666 }
00667
00668 if (!found)
00669 {
00670 derived_virtuals.push_back(
00671 dict.functions.AlwaysGet(*right.derived_virtuals[i]));
00672 }
00673 }
00674
00675
00676 for (size_t i = 0; i < right.address_taken.size(); i++)
00677 {
00678 bool found = false;
00679 for (size_t j = 0; j < address_taken.size(); j++)
00680 {
00681 if (right.address_taken[i] == address_taken[j])
00682 {
00683 found = true;
00684 break;
00685 }
00686 }
00687
00688
00689 if (!found)
00690 {
00691
00692
00693 address_taken.push_back(Location(&dict));
00694 address_taken.back() = right.address_taken[i];
00695 }
00696 }
00697
00698
00699
00700 if (address_taken.size() && !function_pointer_type)
00701 {
00702 function_pointer_type = dict.function_types.AlwaysGet(
00703 *right.function_pointer_type);
00704 }
00705
00706
00707
00708
00709 if (!loc)
00710 {
00711 loc = right.loc;
00712 }
00713
00714
00715
00716
00717 if (right.processed_implementations)
00718 {
00719 translation_unit = right.translation_unit;
00720 }
00721
00722
00723
00724
00725
00726 if (implementation.Merge(right.implementation))
00727 {
00728
00729
00730
00731 if (processed_implementations && right.processed_implementations)
00732 {
00733 EDOC_Finer("Merging Left implementation: " << implementation);
00734 EDOC_Finer("Merging Right implementation: "
00735 << right.implementation);
00736
00737
00738
00739
00740
00741
00742 EDOC_NOTIFICATION(WDIFF_IMPL,
00743 "Function: " << GetKeyName()
00744 << ", Declared Name: " << GetDeclaredName(),
00745 this, loc.file, loc.line, right.loc.file, right.loc.line,
00746 NULL, NULL, NULL, NULL);
00747 implementation.Merge(right.implementation);
00748
00749 EDOC_Warning("Failed merging function: " << right.GetKeyName()
00750 << ", with function: " << GetKeyName()
00751 << " as their implementations differ.");
00752 EDOC_Warning("Left implementation: " << implementation);
00753 EDOC_Warning("Right implementation: " << right.implementation);
00754 EDOC_Warning("Left referenced in files: " << GetRefInFilesString());
00755 EDOC_Warning("Right referenced in files: "
00756 << right.GetRefInFilesString());
00757 EDOC_Warning("Left declared at location: " << loc);
00758 EDOC_Warning("Right declared at location: " << right.loc);
00759 }
00760
00761 processed_implementations++;
00762 }
00763 else if (!processed_implementations && right.processed_implementations)
00764 {
00765
00766
00767 processed_implementations++;
00768 }
00769
00770
00771
00772
00773 EDOC_FOREACH_CONST(FilePList, it, right.referenced_in_files)
00774 {
00775 PushBackUnique(referenced_in_files,
00776 dict.files.AlwaysGet(*(*it)));
00777 }
00778
00779
00780 populated = true;
00781 }
00782
00783 std::string Function::GetSpecString() const
00784 {
00785 std::ostringstream stream;
00786
00787 if (has_exception_spec)
00788 {
00789 stream << "throws(";
00790 for (size_t i = 0; i < exception_spec.size(); i++)
00791 {
00792 if (i != 0)
00793 {
00794 stream << ", ";
00795 }
00796 if (exception_spec[i]->IsPopulated())
00797 {
00798 stream << exception_spec[i]->GetDeclaredName();
00799 }
00800 else
00801 {
00802 stream << "(UNPOPULATED: " << exception_spec[i]->GetKeyName()
00803 <<")";
00804 }
00805 }
00806 stream << ")";
00807 }
00808
00809 return stream.str();
00810 }
00811
00812 void Function::ExpandCallGraph()
00813 {
00814 if (processed_implementations)
00815 {
00816 implementation.ExpandCallGraph(*this);
00817 }
00818
00819 for (size_t j = 0; j < derived_virtuals.size(); j++)
00820 {
00821 EDOC_Finer("Adding POSSIBLE call for function: "
00822 << GetKeyName()
00823 << " to child virtual function: "
00824 << derived_virtuals[j]->GetKeyName());
00825 implementation.AddPossCall(FunctionLoc(dict, derived_virtuals[j],
00826 *dict.UNKNOWN_LOCATION));
00827 }
00828 }
00829
00830 std::list<const PropogatingException*> Function::GetVisiblePropExceptions() const
00831 {
00832 std::list<const PropogatingException*> ret;
00833 EDOC_FOREACH_CONST(PropExcepList, it, propogating_exceptions)
00834 {
00835 if (it->IsVisible())
00836 {
00837 ret.push_back(&(*it));
00838 }
00839 else
00840 {
00841 EDOC_Info("Exception is not visible: "
00842 << it->exception->type.value->GetDeclaredName());
00843 if (!it->visible)
00844 {
00845 EDOC_Info("At prop level.");
00846 }
00847
00848 if (!it->exception->visible)
00849 {
00850 EDOC_Info("At orig level.");
00851 }
00852
00853 if (!it->exception->type.value->visible)
00854 {
00855 EDOC_Info("At type level.");
00856 }
00857 }
00858 }
00859
00860 return ret;
00861 }
00862
00863 bool Function::IsMain() const
00864 {
00865 return link_name == "main";
00866 }
00867
00868 bool Function::IsStaticInitialiser() const
00869 {
00870
00871 const char* STATIC_BASE_NAME =
00872 "_Z41__static_initialization_and_destruction_0ii";
00873 size_t static_base_name_len = strlen(STATIC_BASE_NAME);
00874
00875 return !strncmp(link_name.c_str(),
00876 STATIC_BASE_NAME, static_base_name_len);
00877 }
00878
00879 bool Function::IsDestructor() const
00880 {
00881
00882 return full_name.find('~') != std::string::npos;
00883 }
00884
00885
00886 #define EDOC_REPLACE(DataType, Data, From, To, Count) \
00887 if ((void*)Data == From) {Data = (DataType*)To; Count++;}
00888
00889 size_t Function::ReplaceReferences(PStack& stack, void* remove,
00890 void* replace)
00891 {
00892 size_t count = 0;
00893 if (!stack.Push(this))
00894 {
00895 return count;
00896 }
00897
00898 for (size_t i = 0; i < exception_spec.size(); i++)
00899 {
00900 EDOC_REPLACE(Type, exception_spec[i], remove, replace, count);
00901 }
00902
00903 for (size_t i = 0; i < derived_virtuals.size(); i++)
00904 {
00905 EDOC_REPLACE(Function, derived_virtuals[i],
00906 remove, replace, count);
00907 }
00908
00909 for (size_t i = 0; i < address_taken.size(); i++)
00910 {
00911 count += address_taken[i].ReplaceReferences(stack, remove, replace);
00912 }
00913
00914 EDOC_REPLACE(FunctionType, function_pointer_type, remove, replace, count);
00915
00916 count += loc.ReplaceReferences(stack, remove, replace);
00917
00918 if (processed_implementations)
00919 {
00920 count += implementation.ReplaceReferences(stack, remove, replace);
00921 }
00922
00923 EDOC_FOREACH(PropExcepList, it, propogating_exceptions)
00924 {
00925 count += it->ReplaceReferences(stack, remove, replace);
00926 }
00927
00928 for (size_t i = 0; i < filtered_exceptions.size(); i++)
00929 {
00930 count += filtered_exceptions[i].ReplaceReferences(stack,
00931 remove, replace);
00932 }
00933
00934 EDOC_FOREACH(FilePList, it, referenced_in_files)
00935 {
00936 EDOC_REPLACE(File, (*it), remove, replace, count);
00937 }
00938
00939 if (circular)
00940 {
00941 EDOC_FOREACH(std::set<Function*>, it, *circular)
00942 {
00943 EDOC_ASSERT((void*)(*it) != remove,
00944 "Replacing a function pointer after it has been populated "
00945 "into a circular callgraph is not currently supported.");
00946 }
00947 }
00948
00949 return count;
00950 }
00951
00952 void Function::Validate(PStack& stack, const Dictionary& dict_in) const
00953 {
00954
00955
00956
00957
00958 StackRef ref(stack, this);
00959 if (!ref)
00960 {
00961 return;
00962 }
00963
00964 EDOC_ASSERT(&dict == &dict_in,
00965 "Current dict: " << &dict
00966 << "\nRequired dict: " << &dict_in
00967 << "\nKey: " << key_name
00968 << "\nIndex: " << index);
00969 EDOC_ASSERT(populated, GetKeyName() << ", address: " << (void*)this);
00970
00971 EDOC_ASSERT(translation_unit, "");
00972
00973 EDOC_ASSERT(GetKeyName().size(), GetKeyName() << ", address: "
00974 << (void*)this);
00975 EDOC_ASSERT(dict_in.functions.Get(GetKeyName()) == this, GetKeyName()
00976 << ", address: " << (void*)this);
00977
00978 for (size_t i = 0; i < exception_spec.size(); i++)
00979 {
00980 exception_spec[i]->Validate(stack, dict_in);
00981 }
00982
00983 for (size_t i = 0; i < derived_virtuals.size(); i++)
00984 {
00985 derived_virtuals[i]->Validate(stack, dict_in);
00986 }
00987
00988 for (size_t i = 0; i < address_taken.size(); i++)
00989 {
00990 address_taken[i].Validate(stack, dict_in);
00991 }
00992
00993 if (address_taken.size())
00994 {
00995 EDOC_ASSERT(function_pointer_type, "");
00996 function_pointer_type->Validate(stack, dict_in);
00997 }
00998 else
00999 {
01000 EDOC_ASSERT(!function_pointer_type, "");
01001 }
01002
01003 loc.Validate(stack, dict_in);
01004
01005
01006 implementation.Validate(stack, dict_in);
01007
01008 bool got_filename = false;
01009 std::string filename = "";
01010 EDOC_FOREACH_CONST(PropExcepList, it, propogating_exceptions)
01011 {
01012 it->Validate(stack, dict_in);
01013
01014
01015 if (!got_filename)
01016 {
01017 filename = it->func.loc.file->GetName();
01018 if (filename.size())
01019 {
01020 got_filename = true;
01021 }
01022 }
01023 else
01024 {
01025 EDOC_ASSERT(it->func.loc.file->GetName() == filename, GetKeyName()
01026 << ", address: " << (void*)this);
01027 }
01028 }
01029
01030 for (size_t i = 0; i < filtered_exceptions.size(); i++)
01031 {
01032 filtered_exceptions[i].Validate(stack, dict_in);
01033 }
01034
01035 EDOC_FOREACH_CONST(FilePList, it, referenced_in_files)
01036 {
01037 (*it)->Validate(stack, dict_in);
01038 }
01039
01040
01041
01042
01043
01044
01045
01046
01047
01048
01049
01050
01051
01052
01053
01054
01055
01056 if (circular)
01057 {
01058 EDOC_FOREACH_CONST(std::set<Function*>, it, *circular)
01059 {
01060 EDOC_ASSERT((*it)->circular == circular, "");
01061 (*it)->Validate(stack, dict_in);
01062 }
01063 }
01064 }
01065
01066 std::string Function::GetRefInFilesString() const
01067 {
01068 std::ostringstream stream;
01069 EDOC_FOREACH_CONST(FilePList, it, referenced_in_files)
01070 {
01071 stream << "File: "
01072 << (*it)->GetKeyName()
01073 << std::endl;
01074 }
01075
01076 return stream.str();
01077 }
01078
01079 std::list<EDoc::PropogatingException*> Function::GetPropogatingExceptions()
01080 {
01081 std::list<EDoc::PropogatingException*> ret;
01082 EDOC_FOREACH(PropExcepList, it, propogating_exceptions)
01083 {
01084 ret.push_back(&(*it));
01085 }
01086
01087 return ret;
01088 }
01089
01090 Exception& Function::GetSubstException()
01091 {
01092 if (!subst_exception)
01093 {
01094 subst_exception = new Exception(&dict);
01095 subst_exception->type.loc = *dict.UNKNOWN_LOCATION;
01096 subst_exception->type.value = const_cast<Type*>(dict.SUBSTITUTION_EXCEPTION_TYPE);
01097
01098
01099 subst_exception->visible = true;
01100
01101
01102
01103 subst_exception->function = this;
01104 }
01105
01106 return *subst_exception;
01107 }
01108
01109 }
01110