PageRenderTime 111ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 2ms

/lib/pinot/src/control.cpp

https://bitbucket.org/gkakaron/copeswingapp
C++ | 7818 lines | 6475 code | 589 blank | 754 comment | 2184 complexity | 75f0d08c41dc9dbf8392b8cc776ddda0 MD5 | raw file
Possible License(s): GPL-3.0, LGPL-2.1
  1. // $Id: control.cpp,v 1.88 2006/03/15 06:19:48 shini Exp $
  2. //
  3. // This software is subject to the terms of the IBM Jikes Compiler
  4. // License Agreement available at the following URL:
  5. // http://ibm.com/developerworks/opensource/jikes.
  6. // Copyright (C) 1996, 2004 IBM Corporation and others. All Rights Reserved.
  7. // You must accept the terms of that agreement to use this software.
  8. //
  9. #include "control.h"
  10. #include "scanner.h"
  11. #include "parser.h"
  12. #include "semantic.h"
  13. #include "error.h"
  14. #include "bytecode.h"
  15. #include "case.h"
  16. #include "option.h"
  17. #include <fstream>
  18. #include <iomanip>
  19. #include <dlfcn.h>
  20. #include <stdlib.h>
  21. #ifdef HAVE_JIKES_NAMESPACE
  22. namespace Jikes { // Open namespace Jikes block
  23. #endif
  24. int counter1, counter2, counter3;
  25. int nSingleton, nCoR, nBridge, nStrategy, nState, nFlyweight, nComposite, nMediator, nTemplate, nFactoryMethod, nAbstractFactory, nVisitor, nDecorator, nObserver, nProxy, nAdapter, nFacade;
  26. bool PINOT_DEBUG;
  27. SymbolSet mediators;
  28. int nMediatorFacadeDual = 0, nFlyweightGoFVersion = 0, nImmutable = 0;
  29. /**
  30. * Utility functions
  31. */
  32. ContainerType *Utility::IdentifyContainerType(VariableSymbol *vsym)
  33. {
  34. TypeSymbol *type = vsym->Type();
  35. if (type->Primitive())
  36. return NULL;
  37. if (type->IsArray())
  38. // can be 2D, 3D, etc.
  39. return new ArrayContainer(vsym);
  40. if (strcmp(type->fully_qualified_name->value, "java/util/Vector") == 0)
  41. return new VectorContainer(vsym);
  42. else if (strcmp(type->fully_qualified_name->value, "java/util/ArrayList") == 0)
  43. return new ArrayListContainer(vsym);
  44. else if (strcmp(type->fully_qualified_name->value, "java/util/LinkedList") == 0)
  45. return new ArrayListContainer(vsym);
  46. if (type->supertypes_closure)
  47. {
  48. Symbol *sym= type->supertypes_closure->FirstElement();
  49. while(sym)
  50. {
  51. if (strcmp(sym->TypeCast()->fully_qualified_name->value, "java/util/Map") == 0)
  52. return new MapContainer(vsym);
  53. else if (strcmp(sym->TypeCast()->fully_qualified_name->value, "java/util/Collection") == 0)
  54. return new CollectionContainer(vsym);
  55. sym = type->supertypes_closure->NextElement();
  56. }
  57. }
  58. return NULL;
  59. }
  60. void Utility::RemoveJavaBaseClass(SymbolSet& set)
  61. {
  62. Symbol *sym = set.FirstElement();
  63. while(sym)
  64. {
  65. if (strcmp(sym->TypeCast()->fully_qualified_name->value, "java/lang/Object") == 0)
  66. {
  67. set.RemoveElement(sym);
  68. break;
  69. }
  70. sym = set.NextElement();
  71. }
  72. }
  73. void Utility::RemoveBuiltinInterfaces(SymbolSet& set)
  74. {
  75. SymbolSet temp;
  76. Symbol *sym = set.FirstElement();
  77. while(sym)
  78. {
  79. if (sym->TypeCast()->file_symbol->IsJava())
  80. temp.AddElement(sym);
  81. sym = set.NextElement();
  82. }
  83. set.Intersection(temp);
  84. }
  85. TypeSymbol *Utility::GetTypeSymbol(Symbol *sym)
  86. {
  87. if (sym->Kind() == Symbol::TYPE)
  88. return sym->TypeCast();
  89. else if (sym->Kind() == Symbol::VARIABLE)
  90. return sym->VariableCast()->Type();
  91. else if (sym->Kind() == Symbol::METHOD)
  92. return sym->MethodCast()->Type();
  93. else
  94. return NULL;
  95. }
  96. AstExpression *Utility::RemoveCasting(AstExpression *expr)
  97. {
  98. if (expr->kind == Ast::CAST)
  99. return RemoveCasting(expr->CastExpressionCast()->expression);
  100. else if (expr->kind == Ast::PARENTHESIZED_EXPRESSION)
  101. return RemoveCasting(expr->ParenthesizedExpressionCast()->expression);
  102. else
  103. return expr;
  104. }
  105. void Utility::Intersection(vector<signed>& a, vector<signed>& b, vector<signed>& c)
  106. {
  107. for (unsigned i = 0; i < a.size(); i++)
  108. for (unsigned j = 0; j < b.size(); j++)
  109. if (a[i] == b[j])
  110. c.push_back(a[i]);
  111. }
  112. void Utility::RemoveDuplicates(vector<signed>& a)
  113. {
  114. vector<signed> b;
  115. for (unsigned i = 0; i < a.size(); i++)
  116. {
  117. unsigned j = 0;
  118. while ((j < b.size()) && (a[i] != b[j])) j++;
  119. if (j == b.size())
  120. b.push_back(a[i]);
  121. }
  122. a.swap(b);
  123. }
  124. bool Utility::Aliasing(VariableSymbol *v1, VariableSymbol *v2)
  125. {
  126. if (!v1->aliases)
  127. return false;
  128. else if (v1->aliases->IsElement(v2))
  129. return true;
  130. else
  131. {
  132. Symbol *sym = v1->aliases->FirstElement();
  133. while(sym)
  134. {
  135. // reach two-hops only
  136. if (sym->VariableCast()->aliases && sym->VariableCast()->aliases->IsElement(v2))
  137. return true;
  138. sym = v1->aliases->NextElement();
  139. }
  140. return false;
  141. }
  142. }
  143. bool isCached(wchar_t* name, vector<wchar_t*>* cache)
  144. {
  145. bool flag = false;
  146. if (cache)
  147. {
  148. unsigned i = 0;
  149. while ((!flag) && (i < cache -> size()))
  150. {
  151. if (wcscmp((*cache)[i], name) == 0)
  152. flag = true;
  153. else
  154. i++;
  155. }
  156. }
  157. return flag;
  158. }
  159. bool intersection(vector<wchar_t*>* list1, vector<wchar_t*>* list2)
  160. {
  161. bool flag = false;
  162. if (list1 && list2)
  163. {
  164. unsigned i = 0, j;
  165. while (!flag && (i < list1 -> size()))
  166. {
  167. j = 0;
  168. while (!flag && (j < list2 -> size()))
  169. {
  170. if (wcscmp((*list1)[i], (*list2)[j]) == 0)
  171. flag = true;
  172. else
  173. j++;
  174. }
  175. if (!flag)
  176. i++;
  177. }
  178. }
  179. return flag;
  180. }
  181. void printVector(vector<wchar_t*>* v)
  182. {
  183. if (v)
  184. {
  185. unsigned i;
  186. for (i = 0; i < v -> size(); i++)
  187. {
  188. if (i > 0)
  189. Coutput << " ";
  190. Coutput << (*v)[i];
  191. }
  192. Coutput << endl;
  193. }
  194. }
  195. /**
  196. * GoF patterns
  197. */
  198. void PrintSingletonXMI(TypeSymbol *class_sym , VariableSymbol *instance_sym, MethodSymbol *method_sym);
  199. void FindPrototype(MethodBodyTable* mb_table, GenTable* gen_table, AssocTable* assoc_table)
  200. {
  201. vector<wchar_t*>* prototypes = NULL;
  202. prototypes = gen_table -> getSuccessors(L"Cloneable", GenTable::IMPL);
  203. if (prototypes)
  204. {
  205. unsigned i;
  206. for (i = 0; i < prototypes -> size(); i++)
  207. {
  208. int j;
  209. for (j = 0; j < assoc_table -> getSize(); j++)
  210. {
  211. if ((assoc_table -> getKindAt(j) == Assoc::MR)
  212. && (wcscmp(assoc_table -> getTypeAt(j), (*prototypes)[i]) == 0))
  213. {
  214. wchar_t* factory = assoc_table -> getClassNameAt(j);
  215. wchar_t* method_name = assoc_table -> getMethodNameAt(j);
  216. wchar_t* var_name = assoc_table -> getName(Assoc::CF, Assoc::PRIVATE, (*prototypes)[i], factory);
  217. AstMethodDeclaration* method_declaration = dynamic_cast<AstMethodDeclaration*>(mb_table -> getAstLocation(factory, method_name));
  218. AstMethodBody* method_body = method_declaration -> method_body_opt;
  219. Coutput << L"Prototype Factory: " << factory << endl
  220. << L"Make Method: " << method_name << endl
  221. << L"Prototype Var: " << var_name <<endl << endl;
  222. Coutput << L"AST of " << method_name << endl;
  223. method_body -> Print();
  224. if ((method_body -> NumStatements() == 1)
  225. && (method_body -> Statement(0) -> kind == Ast::RETURN))
  226. {
  227. AstReturnStatement* return_statement = dynamic_cast<AstReturnStatement*>(method_body -> Statement(0));
  228. if (return_statement -> expression_opt -> kind == Ast::CAST)
  229. {
  230. AstCastExpression* cast_expression = dynamic_cast<AstCastExpression*>(return_statement -> expression_opt);
  231. AstMethodInvocation* method_invocation = dynamic_cast<AstMethodInvocation*>(cast_expression -> expression);
  232. if ((wcscmp(method_invocation -> identifier_token_string, L"clone") == 0)
  233. && (wcscmp(dynamic_cast<AstName*>(method_invocation -> base_opt) -> identifier_token_string, var_name) == 0))
  234. Coutput << L"Yoohoo" << endl;
  235. }
  236. }
  237. Coutput << endl << endl;
  238. }
  239. }
  240. }
  241. }
  242. }
  243. void FindSingleton1(ClassSymbolTable *cs_table, StoragePool *ast_pool)
  244. {
  245. if (PINOT_DEBUG)
  246. Coutput << "Identifying the Singleton Pattern" << endl;
  247. for (unsigned c = 0; c < cs_table -> size(); c++)
  248. {
  249. TypeSymbol *unit_type = (*cs_table)[c];
  250. if (PINOT_DEBUG)
  251. Coutput << "Analyzing class: " << unit_type->fully_qualified_name->value << endl;
  252. //if (unit_type->Anonymous()) break;
  253. bool instantiable = true; //for Singleton pattern, either class is abtract or ctor is private
  254. VariableSymbol *instance = NULL;
  255. MethodSymbol *GetInstance = NULL;
  256. if (unit_type -> ACC_ABSTRACT())
  257. instantiable = false;
  258. for (unsigned i = 0; i < unit_type->NumVariableSymbols(); i++)
  259. {
  260. VariableSymbol *vsym = unit_type->VariableSym(i);
  261. if (vsym->ACC_PRIVATE() && vsym->ACC_STATIC() && (vsym->Type() == unit_type))
  262. {
  263. instance = vsym;
  264. break;
  265. }
  266. }
  267. for (unsigned i = 0; (instantiable || !GetInstance) && (i < unit_type->NumMethodSymbols()); i++)
  268. {
  269. MethodSymbol *msym = unit_type->MethodSym(i);
  270. if (msym->declaration)
  271. {
  272. if (msym->declaration->kind == Ast::CONSTRUCTOR)
  273. {
  274. if (msym->ACC_PRIVATE())
  275. instantiable = false;
  276. }
  277. else if (msym->declaration->kind == Ast::METHOD)
  278. {
  279. if (msym->ACC_PUBLIC() && msym->ACC_STATIC() && (msym->Type() == unit_type))
  280. GetInstance = msym;
  281. }
  282. }
  283. }
  284. if (!instantiable && instance && GetInstance)
  285. {
  286. // Do the behavioral analysis
  287. SingletonAnalysis singleton(instance, GetInstance, ast_pool);
  288. //Coutput << unit_type->file_symbol->FileName() << endl;
  289. if (singleton.ReturnsSingleton())
  290. {
  291. Coutput << ((GetInstance-> ACC_SYNCHRONIZED()) ? "" : "") << "Singleton Pattern." << endl
  292. << unit_type->Utf8Name() << " is a Singleton class" << endl
  293. << instance->Utf8Name() << " is the Singleton instance" << endl
  294. << GetInstance->Utf8Name() << " creates and returns " << instance->Utf8Name() << endl
  295. << "File location: " << unit_type->file_symbol->FileName() << endl
  296. << ((GetInstance->ACC_SYNCHRONIZED()) ? "Double-checked Locking not used.\n" : "\n") << endl;
  297. nSingleton++;
  298. }
  299. singleton.CleanUp();
  300. }
  301. }
  302. }
  303. void FindSingleton(ClassSymbolTable *cs_table, MethodSymbolTable* ms_table)
  304. {
  305. vector<TypeSymbol*> candidates_t;
  306. for (unsigned i = 0; i<ms_table->size(); i++)
  307. {
  308. MethodSymbol *method = (*ms_table)[i];
  309. if (method -> declaration -> kind == Ast::CONSTRUCTOR)
  310. {
  311. if (method -> ACC_PRIVATE())
  312. {
  313. TypeSymbol *unit_type = method -> containing_type;
  314. candidates_t.push_back(unit_type);
  315. }
  316. }
  317. }
  318. unsigned c;
  319. for (c = 0; c < cs_table -> size(); c++)
  320. {
  321. TypeSymbol *unit_type = (*cs_table)[c];
  322. if (unit_type -> ACC_ABSTRACT())
  323. {
  324. candidates_t.push_back(unit_type);
  325. }
  326. }
  327. if (candidates_t.size() > 0)
  328. {
  329. unsigned i;
  330. for (i = 0; i < candidates_t.size(); i++)
  331. {
  332. AstClassBody *class_body = candidates_t[i] -> declaration;
  333. // find the class variable
  334. VariableSymbol *instance_sym = NULL;
  335. for (unsigned j = 0; !instance_sym && (j < class_body -> NumClassVariables()); j++)
  336. {
  337. AstFieldDeclaration* field_decl = class_body -> ClassVariable(j);
  338. TypeSymbol *type = field_decl -> type -> symbol;
  339. if ((type == candidates_t[i]) && (field_decl -> NumVariableDeclarators() == 1))
  340. {
  341. AstVariableDeclarator* vd = field_decl -> VariableDeclarator(0);
  342. if (vd -> symbol -> ACC_PRIVATE())
  343. instance_sym = vd -> symbol;
  344. }
  345. }
  346. // find the get_instance method
  347. MethodSymbol *get_method_sym = NULL;
  348. for (unsigned j = 0; !get_method_sym && (j < class_body -> NumMethods()); j++)
  349. {
  350. AstMethodDeclaration* method = class_body -> Method(j);
  351. if ((method -> method_symbol)
  352. && (method -> method_symbol -> Type() == candidates_t[i])
  353. && (method -> method_symbol -> ACC_STATIC())
  354. && (method -> method_symbol -> ACC_PUBLIC()))
  355. get_method_sym = method -> method_symbol;
  356. }
  357. if (instance_sym && get_method_sym)
  358. {
  359. AstMethodDeclaration *method_declaration = get_method_sym -> declaration -> MethodDeclarationCast();
  360. AstMethodBody *method_body = method_declaration -> method_body_opt;
  361. wchar_t *instance_name = const_cast<wchar_t*>(instance_sym -> Name());
  362. if (method_body -> returnsVar(instance_name))
  363. {
  364. EnvTable *env = new EnvTable();
  365. env -> addEnvironment(instance_name, Env::INIT);
  366. method_body -> simulate(env);
  367. if (env -> getState(instance_name) == Env::INIT)
  368. {
  369. /*
  370. char* file_name = method_sym -> containing_type -> file_symbol -> FileName();
  371. TypeSymbol *class_sym = NULL;
  372. for (unsigned i = 0; !class_sym && (i < candidates_t.size()); i++)
  373. if (wcscmp(candidates_t[i] -> Name(), class_name) == 0)
  374. class_sym = candidates_t[i];
  375. VariableSymbol *instance_sym = NULL;
  376. for (unsigned j = 0; !instance_sym && (j < class_sym -> declaration -> NumClassVariables()); j++)
  377. {
  378. AstFieldDeclaration* field_decl = class_sym -> declaration -> ClassVariable(j);
  379. for (unsigned vi = 0; vi < field_decl -> NumVariableDeclarators(); vi++)
  380. {
  381. AstVariableDeclarator* vd = field_decl -> VariableDeclarator(vi);
  382. if (wcscmp(vd -> symbol -> Name(), instance_name) == 0)
  383. instance_sym = vd -> symbol;
  384. }
  385. }
  386. */
  387. //PrintSingletonXMI(class_sym , instance_sym, method_sym);
  388. Coutput << ((get_method_sym-> ACC_SYNCHRONIZED()) ? L"Multithreaded " : L"")
  389. << L"Singleton Pattern."
  390. << endl
  391. << candidates_t[i] -> Utf8Name() << " is a Singleton class"
  392. << endl
  393. << instance_sym -> Utf8Name() << " is the Singleton instance"
  394. << endl
  395. << get_method_sym -> Utf8Name() << " returns a " << instance_sym -> Utf8Name()
  396. << endl
  397. << "File location: " << candidates_t[i] -> file_symbol -> FileName()
  398. << endl
  399. << ((get_method_sym-> ACC_SYNCHRONIZED()) ? L"Double-checked Locking not used.\n" : L"\n")
  400. << endl;
  401. nSingleton++;
  402. }
  403. else
  404. {
  405. /*
  406. Coutput << L"Singleton Pattern"
  407. << endl
  408. << class_name << L" is a Singleton class"
  409. << endl
  410. << instance_name << L" is the Singleton instance"
  411. << endl
  412. << get_method << L" returns a " << instance_name
  413. << endl
  414. << L"File location: " << file_name
  415. << endl;
  416. Coutput << L"Warning: " << instance_name << L" is modified more than once." << endl << endl;
  417. */
  418. }
  419. delete env;
  420. }
  421. else
  422. {
  423. /*
  424. Coutput << L"Singleton Pattern"
  425. << endl
  426. << class_name << L" is a Singleton class"
  427. << endl
  428. << instance_name << L" is the Singleton instance"
  429. << endl
  430. << get_method << L" returns a " << instance_name
  431. << endl
  432. << L"File location: " << file_name
  433. << endl;
  434. Coutput << L"Warning: " << instance_name << L" is not returned in " << get_method << endl << endl;
  435. */
  436. }
  437. }
  438. }
  439. }
  440. }
  441. void FindChainOfResponsibility(ClassSymbolTable *cs_table, MethodSymbolTable* ms_table, DelegationTable *d_table, StoragePool *ast_pool)
  442. {
  443. if (PINOT_DEBUG)
  444. Coutput << "Identifying Cor and Decorator" << endl;
  445. SymbolSet CoR_cache;
  446. SymbolSet D_cache;
  447. vector<MethodSymbol*> cache;
  448. int i;
  449. for (i = 0; i< d_table -> size(); i++)
  450. {
  451. DelegationEntry *entry = d_table -> Entry(i);
  452. if (PINOT_DEBUG)
  453. Coutput << "Analyzing delegation: " << entry->enclosing->Utf8Name() << " -> " << entry->method->Utf8Name() << endl;
  454. if (entry-> vsym
  455. && (entry->from->IsSubtype(entry->vsym->Type()) || entry->vsym->Type()->IsSubtype(entry->from))
  456. && (!entry->vsym->IsLocal() || entry->from->Shadows(entry->vsym))
  457. && ((strcmp(entry -> method -> Utf8Name(), entry -> enclosing -> Utf8Name()) == 0) || (entry->method == entry->enclosing))
  458. && (strcmp(entry->enclosing->SignatureString(), entry->method->SignatureString()) == 0)
  459. )
  460. {
  461. unsigned j = 0;
  462. for (; (j < cache.size()) && (cache[j] != entry->enclosing) ; j++);
  463. if (j == cache.size())
  464. {
  465. ChainAnalysis chain_analysis(entry->vsym, entry->enclosing, ast_pool);
  466. ChainAnalysis::ResultTag result = chain_analysis.AnalyzeCallChain();
  467. if (result == ChainAnalysis::CoR)
  468. {
  469. Coutput << "Chain of Responsibility Pattern." << endl;
  470. Coutput << entry -> from -> Utf8Name() << " is a Chain of Responsibility Handler class" << endl;
  471. Coutput << entry -> enclosing -> Utf8Name() << " is a handle operation" << endl;
  472. Coutput << entry -> vsym -> Utf8Name() << " of type " << entry -> vsym -> Type() -> Utf8Name() << " propogates the request" << endl;
  473. char* file_name = entry -> enclosing -> containing_type -> file_symbol -> FileName();
  474. Coutput << L"File Location: " << file_name << endl << endl;
  475. cache.push_back(entry->enclosing);
  476. CoR_cache.AddElement(entry -> vsym -> Type());
  477. //nCoR++;
  478. }
  479. else if (result == ChainAnalysis::DECORATOR)
  480. {
  481. Coutput << "Decorator Pattern." << endl;
  482. Coutput << entry -> from -> Utf8Name() << " is a Decorator class" << endl;
  483. Coutput << entry -> enclosing -> Utf8Name() << " is a decorate operation" << endl;
  484. Coutput << entry -> vsym -> Utf8Name() << " of type " << entry -> vsym -> Type() -> Utf8Name() << " is the Decoratee class" << endl;
  485. char* file_name = entry -> enclosing -> containing_type -> file_symbol -> FileName();
  486. Coutput << L"File Location: " << file_name << endl << endl;
  487. cache.push_back(entry->enclosing);
  488. D_cache.AddElement(entry -> vsym -> Type());
  489. //nDecorator++;
  490. }
  491. chain_analysis.CleanUp();
  492. }
  493. }
  494. }
  495. nCoR += CoR_cache.Size();
  496. CoR_cache.Print();
  497. nDecorator += D_cache.Size();
  498. D_cache.Print();
  499. }
  500. void FindBridge(ClassSymbolTable *cs_table, DelegationTable *d_table)
  501. {
  502. multimap<TypeSymbol*,TypeSymbol*> cache;
  503. multimap<TypeSymbol*,TypeSymbol*> negatives;
  504. int i;
  505. for (i = 0; i < d_table -> size(); i++)
  506. {
  507. DelegationEntry *entry = d_table -> Entry(i);
  508. if (//(entry -> from -> ACC_ABSTRACT()) &&
  509. entry->from->subtypes
  510. && entry->from->subtypes->Size()
  511. && entry->to->ACC_INTERFACE()
  512. && entry->from->file_symbol->IsJava()
  513. && entry->to->file_symbol->IsJava()
  514. && (!cs_table -> Converge(entry -> from, entry -> to)))
  515. {
  516. multimap<TypeSymbol*,TypeSymbol*>::iterator p = cache.begin();
  517. for (; (p != cache.end()) && ((p -> first != entry -> from) || (p -> second != entry -> to)); p++);
  518. if ((p == cache.end()) && !d_table -> DelegatesSuccessors(entry -> from, entry -> to))
  519. {
  520. nBridge++;
  521. cache.insert(pair<TypeSymbol*,TypeSymbol*>(entry -> from, entry -> to));
  522. Coutput << "Bridge Pattern." << endl;
  523. Coutput << entry -> from -> Utf8Name()
  524. << " is abstract.\n"
  525. << entry -> to -> Utf8Name()
  526. << " is an interface.\n"
  527. << entry -> from -> Utf8Name()
  528. << " delegates "
  529. << entry -> to -> Utf8Name()
  530. << "."
  531. << endl
  532. << "File Location: "
  533. << entry -> from -> file_symbol -> FileName()
  534. << ",\n "
  535. << entry -> to -> file_symbol -> FileName()
  536. << endl;
  537. /*
  538. Coutput << "Subclasses of " << entry -> from -> Utf8Name() << ": ";
  539. cs_table -> PrintSubclasses(entry -> from);
  540. Coutput << "Subtypes of " << entry -> to -> Utf8Name() << ": ";
  541. cs_table -> PrintSubtypes(entry -> to);
  542. Coutput << "Subinterfaces of " << entry -> to -> Utf8Name() << ": ";
  543. cs_table -> PrintSubinterfaces(entry -> to);
  544. d_table -> Delegates(entry -> to, entry -> from);
  545. d_table -> ShowDelegations(entry -> from, entry -> to);
  546. */
  547. Coutput << endl;
  548. }
  549. }
  550. }
  551. }
  552. void FindFlyweight(MethodBodyTable* mb_table, GenTable* gen_table, AssocTable* assoc_table)
  553. {
  554. // Collecting possible flyweight pools
  555. vector<wchar_t*>* pools = NULL;
  556. int i;
  557. for (i = 0; i < assoc_table -> getSize(); i++)
  558. {
  559. if ((assoc_table -> getKindAt(i) == Assoc::IM)
  560. && (assoc_table -> getModeAt(i) == Assoc::PRIVATE)
  561. && (wcscmp(assoc_table -> getTypeAt(i), L"Hashtable") == 0))
  562. {
  563. wchar_t* class_name = assoc_table -> getClassNameAt(i);
  564. if (!pools)
  565. {
  566. pools = new vector<wchar_t*>();
  567. pools -> push_back(class_name);
  568. }
  569. else if (!isCached(class_name, pools))
  570. {
  571. pools -> push_back(class_name);
  572. }
  573. }
  574. }
  575. // Look for possible flyweight factories
  576. for (i = 0; i < assoc_table -> getSize(); i++)
  577. {
  578. if ((assoc_table -> getKindAt(i) == Assoc::MP)
  579. && (isCached(assoc_table ->getTypeAt(i), pools)))
  580. {
  581. wchar_t* package_name = assoc_table -> getPackageNameAt(i);
  582. wchar_t* flyweight_factory = assoc_table -> getClassNameAt(i);
  583. wchar_t* get_flyweight = assoc_table -> getMethodNameAt(i);
  584. AstMethodDeclaration *method_declaration = dynamic_cast<AstMethodDeclaration*>
  585. (mb_table -> getAstLocation(flyweight_factory, get_flyweight));
  586. AstMethodBody *method_body = method_declaration -> method_body_opt;
  587. // Given:
  588. // - type of flyweight class
  589. // - flyweight pool type and var_name
  590. wchar_t* flyweight = method_declaration -> getReturnType();
  591. wchar_t* pool = assoc_table ->getTypeAt(i);
  592. wchar_t* pool_name = assoc_table -> getNameAt(i);
  593. if (method_body
  594. && (!method_declaration -> isPrimitiveType(flyweight))
  595. && (wcscmp(pool, flyweight_factory) != 0))
  596. {
  597. //Coutput << "package name: " << package_name << endl
  598. // << "class name: " << flyweight_factory << endl
  599. // << "method name: " << get_flyweight << endl;
  600. // Check for variables of type "flyweight" declared in this method
  601. vector<wchar_t*>* vars = method_body -> getVariables(flyweight);
  602. if (vars && vars -> size() == 1)
  603. {
  604. wchar_t* temp = (*vars)[0];
  605. //Then make sure that this var is returned by the method
  606. if (method_body -> returnsVar(temp))
  607. {
  608. // If not, reject this class as a flyweight factory.
  609. // Look for a specific statechart on the var that gets returned from this method.
  610. // (1) SET --yes--> RETURN
  611. // (2) SET --no --> CREATE ----> SET ----> RETURN
  612. Statechart* statechart = method_body -> getStatechart(temp);
  613. //int i = 0;
  614. if ((statechart -> getStateKindAt(0) == State::SET)
  615. && (isCached( pool_name, statechart -> getStateParticipantsAt(0)))
  616. && (statechart -> getStateKindAt(1) == State::CONDITION)
  617. && (statechart -> getStateKindAt(2) == State::CREATE)
  618. && ((statechart -> getStateKindAt(3) == State::SET))
  619. && (isCached( pool_name, statechart -> getStateParticipantsAt(3)))
  620. && ((statechart -> getStateKindAt(4) == State::RETURN)))
  621. {
  622. Coutput << "Flyweight Pattern." << endl;
  623. Coutput << flyweight_factory
  624. << " is a Flyweight factory class. "
  625. << endl;
  626. Coutput << pool
  627. << " is a flyweight object pool."
  628. << endl;
  629. Coutput << get_flyweight
  630. << " returns a flyweight object."
  631. << endl;
  632. if (method_declaration -> isSynchronized())
  633. Coutput << "Consider using Double-checked Locking." << endl;
  634. Coutput << "File location: " << gen_table -> getFileName(flyweight_factory, package_name) << endl;
  635. Coutput << endl << endl;
  636. nFlyweight++;
  637. }
  638. }
  639. }
  640. }
  641. }
  642. }
  643. }
  644. void FindFlyweight1(MethodSymbolTable *ms_table)
  645. {
  646. if (PINOT_DEBUG)
  647. Coutput << "Identifying the Flyweight pattern" << endl;
  648. for (unsigned i=0; i<ms_table->size(); i++)
  649. {
  650. MethodSymbol *msym = (*ms_table)[i];
  651. if (PINOT_DEBUG)
  652. Coutput << "Analyzing method: " << msym->Utf8Name() << endl;
  653. TypeSymbol *unit_type = msym->containing_type;
  654. if ((msym->declaration->kind==Ast::METHOD)
  655. && msym->declaration->MethodDeclarationCast()->method_body_opt
  656. && msym->Type()->file_symbol
  657. && !unit_type->IsFamily(msym->Type())
  658. )
  659. {
  660. FlyweightAnalysis flyweight(msym);
  661. msym->declaration->MethodDeclarationCast()->method_body_opt->Accept(flyweight);
  662. //flyweight.DumpSummary();
  663. if (flyweight.IsFlyweightFactory())
  664. {
  665. nFlyweight++;
  666. nFlyweightGoFVersion++;
  667. Coutput << "Flyweight Pattern." << endl;
  668. Coutput << unit_type->Utf8Name() << " is a flyweight factory." << endl;
  669. Coutput << flyweight.GetFlyweightPool()->Utf8Name() << " is the flyweight pool." << endl;
  670. Coutput << msym->Utf8Name()
  671. << " is the factory method, producing flyweight objects of type "
  672. << msym->Type()->Utf8Name() << endl;
  673. Coutput << "File location: " << unit_type->file_symbol->FileName() << endl << endl;
  674. }
  675. }
  676. }
  677. }
  678. void FindFlyweight2(ClassSymbolTable *cs_table, WriteAccessTable *w_table, ReadAccessTable *r_table)
  679. {
  680. // This strategy looks for a variant flyweight implementation, where
  681. // flyweight factories and pools are not necessary:
  682. //
  683. // 1. classes that are defined immutable
  684. // - class declared "final"
  685. // - allows instantiation, thus public ctors (unlike java.lang.Math)
  686. // - but internal fields should all be private and not written/modified by any non-private methods.
  687. //
  688. // 2. flyweight pools are represented as individual variable declarations
  689. // - such variables are typically declared "static final" and are initialized (pre-populated)
  690. unsigned c;
  691. for (c= 0; c < cs_table -> size(); c++)
  692. {
  693. TypeSymbol *unit_type = (*cs_table)[c];
  694. if (unit_type->ACC_FINAL())
  695. {
  696. AstClassBody *class_body = unit_type->declaration;
  697. if (!class_body -> default_constructor)
  698. {
  699. unsigned i, j;
  700. for (i=0; (i < class_body->NumConstructors()) && !class_body->Constructor(i)->constructor_symbol->ACC_PRIVATE(); i++)
  701. ;
  702. for (j=0; (j < unit_type->NumVariableSymbols()) && unit_type->VariableSym(j)->ACC_PRIVATE(); j++)
  703. ;
  704. if ((i == class_body->NumConstructors()) && (j == unit_type->NumVariableSymbols()))
  705. {
  706. bool flag = false;
  707. unsigned m, v;
  708. for (v = 0; !flag && (v < unit_type->NumVariableSymbols()); v++)
  709. {
  710. if (!unit_type->VariableSym(v)->ACC_FINAL())
  711. {
  712. for (m=0; !flag && (m < class_body->NumMethods()); m++)
  713. {
  714. if (class_body->Method(m)->method_symbol->ACC_PUBLIC())
  715. flag = w_table->IsWrittenBy(unit_type->VariableSym(v), class_body->Method(m)->method_symbol);
  716. }
  717. }
  718. }
  719. if (!flag)
  720. {
  721. nFlyweight++;
  722. Coutput << "Flyweight Pattern." << endl;
  723. Coutput << unit_type->Utf8Name() << " is immutable." << endl;
  724. Coutput << "File location: " << unit_type->file_symbol->FileName() << endl << endl;
  725. nImmutable++;
  726. }
  727. }
  728. }
  729. }
  730. else
  731. {
  732. unsigned i;
  733. for (i=0; i < unit_type->NumVariableSymbols(); i++)
  734. {
  735. if (unit_type->VariableSym(i)->Type()->file_symbol
  736. && unit_type->VariableSym(i)->ACC_STATIC()
  737. && unit_type->VariableSym(i)->ACC_FINAL()
  738. //&& (unit_type != unit_type->VariableSym(i)->Type())
  739. )
  740. {
  741. if (unit_type->VariableSym(i)->ACC_PUBLIC() && unit_type->VariableSym(i)->declarator->variable_initializer_opt)
  742. {
  743. nFlyweight++;
  744. Coutput << "Flyweight Pattern." << endl;
  745. Coutput << unit_type->Utf8Name() << " is a flyweight factory." << endl;
  746. //Coutput << unit_type->VariableSym(i)->Utf8Name() << " is a flyweight object (declared public-static-final)." << endl;
  747. Coutput << unit_type->VariableSym(i)->Type()->Utf8Name() << " is a flyweight object (declared public-static-final)." << " object-name: "<< unit_type -> VariableSym(i) -> Utf8Name() << endl; //angor
  748. Coutput << "File location: " << unit_type->file_symbol->FileName() << endl << endl;
  749. goto done;
  750. }
  751. else
  752. {
  753. VariableSymbol *vsym = unit_type->VariableSym(i);
  754. MethodSymbol *msym = NULL;
  755. multimap<VariableSymbol*,MethodSymbol*>::iterator p;
  756. for (p = r_table -> begin(); p != r_table -> end(); p++)
  757. {
  758. //Find the method that returns this static-final flyweight object.
  759. //NOTE: this approach does not analyze method body, just the fact that a flyweight object can be returned.
  760. //VariableSymbol *t1 = p->first;
  761. //MethodSymbol *t2 = p->second;
  762. if (strcmp(vsym->Type()->fully_qualified_name->value, "java/lang/String")
  763. && (p -> first == vsym))
  764. msym = p->second;
  765. else if (Utility::Aliasing(p->first, vsym))
  766. msym = p->second;
  767. }
  768. if (msym)
  769. {
  770. nFlyweight++;
  771. Coutput << "Flyweight Pattern." << endl;
  772. Coutput << unit_type->Utf8Name() << " is a flyweight factory." << endl;
  773. //Coutput << vsym->Utf8Name() << " is a flyweight object." << endl; //pinot
  774. Coutput << vsym->Type()->Utf8Name() << " is a flyweight object." <<" object-name: "<<vsym->Utf8Name()<< endl; //angor
  775. Coutput << msym->Utf8Name() << " is the getFlyweight method." << endl;
  776. Coutput << "File location: " << unit_type->file_symbol->FileName() << endl << endl;
  777. goto done;
  778. }
  779. }
  780. }
  781. }
  782. done: ;
  783. }
  784. }
  785. }
  786. bool Connectivity(MethodSymbol* start, TypeSymbol *end, MethodSymbolTable *ms_table)
  787. {
  788. if (!start->invokers || !end->subtypes || (end->subtypes->Size()==0))
  789. return false;
  790. ms_table->ClearMarks();
  791. Symbol *sym = end->subtypes->FirstElement();
  792. while(sym)
  793. {
  794. TypeSymbol *type = sym->TypeCast();
  795. for (unsigned i = 0; i < type->NumMethodSymbols(); i++)
  796. {
  797. if (type->MethodSym(i)->declaration)
  798. {
  799. if ((type->MethodSym(i)->declaration->ConstructorDeclarationCast()
  800. && type->MethodSym(i)->declaration->ConstructorDeclarationCast()->constructor_body)
  801. || (type->MethodSym(i)->declaration->MethodDeclarationCast()
  802. && type->MethodSym(i)->declaration->MethodDeclarationCast()->method_body_opt))
  803. type->MethodSym(i)->mark = 'B';
  804. }
  805. }
  806. sym = end->subtypes->NextElement();
  807. }
  808. if (start->mark == 'B')
  809. {
  810. Coutput << start->Utf8Name() << " is called by " << start->containing_type->Utf8Name() << "::" << start->Utf8Name() << " is the pivot point." <<endl;
  811. return true;
  812. }
  813. SymbolSet set(0);
  814. sym = start->invokers->FirstElement();
  815. while(sym)
  816. {
  817. MethodSymbol *msym = sym->MethodCast();
  818. if (msym->mark == 'B')
  819. {
  820. Coutput << start->Utf8Name() << " is called by " << msym->containing_type->Utf8Name() << "::" << msym->Utf8Name() << " is the pivot point." <<endl;
  821. return true;
  822. }
  823. else
  824. {
  825. msym->mark = 'R';
  826. if (msym->invokers)
  827. set.Union(*msym->invokers);
  828. }
  829. sym = start->invokers->NextElement();
  830. }
  831. while(set.Size())
  832. {
  833. sym = set.FirstElement();
  834. while(sym)
  835. {
  836. MethodSymbol *msym = sym->MethodCast();
  837. if (msym->mark == 'B')
  838. {
  839. Coutput << msym->containing_type->Utf8Name() << "::" << msym->Utf8Name() << " is the pivot point." <<endl;
  840. return true;
  841. }
  842. else if (msym->mark == 'R')
  843. set.RemoveElement(msym);
  844. else if (msym->mark == 'W')
  845. {
  846. msym->mark = 'R';
  847. set.RemoveElement(msym);
  848. if (msym->invokers)
  849. set.Union(*msym->invokers);
  850. }
  851. sym = set.NextElement();
  852. }
  853. }
  854. return false;
  855. }
  856. bool DelegatesSuccessors(TypeSymbol *t1, TypeSymbol *t2)
  857. {
  858. // pre-condition: t1 is concrete, while t2 is abstract
  859. if (t2->subtypes)
  860. {
  861. Symbol *sym = t2->subtypes->FirstElement();
  862. while (sym)
  863. {
  864. // checks for delegations to concrete classes.
  865. // the reason is to make sure that concrete strategies are not drectly exposed to the context class.
  866. if (!sym->TypeCast()->ACC_ABSTRACT() && sym->TypeCast()->call_dependents && sym->TypeCast()->call_dependents->IsElement(t1))
  867. return true;
  868. sym = t2->subtypes->NextElement();
  869. }
  870. }
  871. return false;
  872. }
  873. void FindStrategy(ClassSymbolTable *cs_table, DelegationTable *d_table, WriteAccessTable *w_table, ReadAccessTable *r_table, MethodSymbolTable *ms_table)
  874. {
  875. multimap<TypeSymbol*,TypeSymbol*> cache;
  876. int i;
  877. for (i = 0; i < d_table -> size(); i++)
  878. {
  879. DelegationEntry *entry = d_table -> Entry(i);
  880. if ((!entry -> from -> ACC_ABSTRACT())
  881. && (!entry -> from -> Anonymous())
  882. && (entry -> to -> ACC_ABSTRACT())
  883. && (entry -> to -> file_symbol -> IsJava())
  884. && (entry -> base_opt)
  885. && !entry->from->IsFamily(entry->to)
  886. )
  887. {
  888. multimap<TypeSymbol*,TypeSymbol*>::iterator p = cache.begin();
  889. for (; (p != cache.end()) && ((p -> first != entry -> from) || (p -> second != entry -> to)) ; p++);
  890. if ((p == cache.end())
  891. && (!DelegatesSuccessors(entry -> from, entry -> to))
  892. )
  893. {
  894. VariableSymbol *vsym = NULL;
  895. //
  896. // Change THIS
  897. // entry->base_opt should be unwrapped to vsym/this/super/class.
  898. //
  899. if (entry -> base_opt -> kind == Ast::NAME)
  900. vsym = entry -> base_opt -> symbol -> VariableCast();
  901. else if (entry -> base_opt -> kind == Ast::CALL)
  902. {
  903. AstMethodInvocation *call = (entry -> base_opt -> MethodInvocationCast() -> resolution_opt)
  904. ? entry -> base_opt -> MethodInvocationCast() -> resolution_opt -> MethodInvocationCast()
  905. : entry -> base_opt -> MethodInvocationCast();
  906. MethodSymbol *msym = (MethodSymbol*) call -> symbol;
  907. multimap<VariableSymbol*,MethodSymbol*>::iterator p;
  908. //
  909. // Change THIS
  910. // a var can be returned by multiple methods.
  911. //
  912. for (p = r_table -> begin(); !vsym && (p != r_table -> end()); p++)
  913. {
  914. if (p -> second == msym)
  915. vsym = p -> first;
  916. }
  917. }
  918. if (vsym
  919. && ((! vsym-> IsLocal())
  920. ||(vsym = entry -> from -> Shadows(vsym))))
  921. {
  922. if ((entry -> from == vsym -> ContainingType())
  923. || ((entry -> from -> IsInner()) && (entry -> from -> ContainingType() == vsym -> ContainingType())))
  924. {
  925. cache.insert(pair<TypeSymbol*,TypeSymbol*>(entry->from, entry -> to));
  926. // check if State pattern is implemented.
  927. MethodSymbol *dsym = NULL;
  928. // if previous didn't work, try the following
  929. if (!dsym)
  930. {
  931. multimap<VariableSymbol*, MethodSymbol*>::iterator p;
  932. for (p = w_table->begin(); !dsym && p!=w_table->end();p++)
  933. {
  934. //VariableSymbol *t1 = p->first;
  935. //MethodSymbol *t2 = p->second;
  936. if (p->first==vsym)
  937. {
  938. if (Connectivity(p->second, entry->to, ms_table)
  939. )
  940. dsym = p->second;
  941. }
  942. }
  943. }
  944. if (dsym)
  945. {
  946. nState++;
  947. Coutput << "State Pattern." << endl;
  948. Coutput << entry -> from -> Utf8Name()
  949. << " is the Context class."
  950. << endl
  951. << entry -> to -> Utf8Name()
  952. << " is the State interface."
  953. << endl;
  954. Coutput << "Concrete State classes: ";
  955. entry->to->subtypes->Print();
  956. Coutput << "Delegation through "
  957. << vsym -> Utf8Name()
  958. << " of type "
  959. << vsym -> Type() -> Utf8Name()
  960. << endl
  961. << dsym -> Utf8Name()
  962. << " changes the state variable "
  963. << vsym -> Utf8Name()
  964. << endl;
  965. Coutput << dsym->Utf8Name()
  966. << " is invoked by ";
  967. dsym->callers->Print();
  968. Coutput << "File Location: "
  969. << entry -> from -> file_symbol -> FileName()
  970. << ",\n "
  971. << entry -> to -> file_symbol -> FileName()
  972. << endl
  973. << endl;
  974. }
  975. else
  976. {
  977. nStrategy++;
  978. Coutput << "Strategy Pattern." << endl;
  979. Coutput << entry -> from -> Utf8Name()
  980. << " is the Context class."
  981. << endl
  982. << entry -> to -> Utf8Name()
  983. << " is the Strategy interface."
  984. << endl;
  985. Coutput << "Concrete Strategy classes: ";
  986. entry->to->subtypes->Print();
  987. Coutput << "Delegation through "
  988. << vsym -> Utf8Name()
  989. << " of type "
  990. << vsym -> Type() -> Utf8Name()
  991. << endl
  992. << "File Location: "
  993. << entry -> from -> file_symbol -> FileName()
  994. << ",\n "
  995. << entry -> to -> file_symbol -> FileName()
  996. << endl
  997. << endl;
  998. }
  999. }
  1000. }
  1001. }
  1002. }
  1003. }
  1004. }
  1005. void FindStrategy1(ClassSymbolTable *cs_table, DelegationTable *d_table, WriteAccessTable *w_table, ReadAccessTable *r_table, MethodSymbolTable *ms_table)
  1006. {
  1007. multimap<TypeSymbol*,TypeSymbol*> cache;
  1008. unsigned c;
  1009. for (c = 0; c < cs_table->size(); c++)
  1010. {
  1011. TypeSymbol *context = (*cs_table)[c];
  1012. if (!context->ACC_ABSTRACT() && !context->Anonymous() && (!context->subtypes || !context->subtypes->Size()))
  1013. {
  1014. for (unsigned i = 0; i < context->NumVariableSymbols(); i++)
  1015. {
  1016. VariableSymbol *vsym = context->VariableSym(i);
  1017. if (vsym->Type()->file_symbol
  1018. && vsym->Type()->file_symbol->IsJava()
  1019. && vsym->Type()->ACC_ABSTRACT()
  1020. && !vsym->Type()->IsFamily(context)
  1021. && !vsym->Type()->IsArray()
  1022. //&& !vsym->Type()->IsSelfContaining()
  1023. )
  1024. {
  1025. MethodSymbol *dsym = NULL;
  1026. multimap<VariableSymbol*, MethodSymbol*>::iterator p;
  1027. bool flag = false;
  1028. for (p = w_table->begin(); !dsym && p!=w_table->end();p++)
  1029. {
  1030. //VariableSymbol *t1 = p->first;
  1031. //MethodSymbol *t2 = p->second;
  1032. if (p->first==vsym)
  1033. {
  1034. flag = true;
  1035. if (p->second->declaration
  1036. && p->second->declaration->MethodDeclarationCast()
  1037. && Connectivity(p->second, vsym->Type(), ms_table))
  1038. dsym = p->second;
  1039. }
  1040. }
  1041. if (dsym)
  1042. {
  1043. nState++;
  1044. Coutput << "State Pattern." << endl;
  1045. Coutput << context->Utf8Name() << " is the Context class." << endl
  1046. << vsym->Type()->Utf8Name() << " is the State interface." << endl;
  1047. Coutput << "Concrete State classes: ";
  1048. vsym->Type()->subtypes->Print();
  1049. Coutput << "Delegation through " << vsym->Utf8Name() << " of type " << vsym->Type()->Utf8Name() << endl
  1050. << dsym->Utf8Name() << " changes the state variable " << vsym->Utf8Name() << endl;
  1051. Coutput << dsym->Utf8Name() << " is invoked by ";
  1052. dsym->invokers->Print();
  1053. Coutput << "File Location: "
  1054. << context->file_symbol->FileName() << ",\n "
  1055. << vsym->Type()->file_symbol->FileName()
  1056. << endl
  1057. << endl;
  1058. }
  1059. else if (flag)
  1060. {
  1061. nStrategy++;
  1062. Coutput << "Strategy Pattern." << endl;
  1063. Coutput << context->Utf8Name() << " is the Context class." << endl
  1064. << vsym->Type()->Utf8Name() << " is the Strategy interface." << endl;
  1065. Coutput << "Concrete Strategy classes: ";
  1066. vsym->Type()->subtypes->Print();
  1067. Coutput << "Delegation through " << vsym->Utf8Name() << " of type " << vsym->Type()->Utf8Name() << endl;
  1068. Coutput << "File Location: "
  1069. << context->file_symbol->FileName() << ",\n "
  1070. << vsym->Type()->file_symbol->FileName()
  1071. << endl
  1072. << endl;
  1073. }
  1074. }
  1075. }
  1076. }
  1077. }
  1078. }
  1079. void FindComposite(ClassSymbolTable *cs_table, DelegationTable *d_table)
  1080. {
  1081. unsigned c;
  1082. for (c = 0; c < cs_table -> size(); c++)
  1083. {
  1084. if (!(*cs_table)[c] -> ACC_ABSTRACT() && (*cs_table)[c]->supertypes_closure && (*cs_table)[c]->supertypes_closure->Size())
  1085. {
  1086. TypeSymbol *unit_type = (*cs_table)[c];
  1087. AstClassBody* class_body = unit_type -> declaration;
  1088. for (unsigned i = 0; i < class_body -> NumInstanceVariables(); i++)
  1089. {
  1090. AstFieldDeclaration* field_decl = class_body -> InstanceVariable(i);
  1091. for (unsigned vi = 0; (vi < field_decl -> NumVariableDeclarators()); vi++)
  1092. {
  1093. AstVariableDeclarator* vd = field_decl -> VariableDeclarator(vi);
  1094. ContainerType *container_type = Utility::IdentifyContainerType(vd->symbol);
  1095. //TypeSymbol *contained_type = unit_type->IsOnetoMany(vd->symbol, d_table);
  1096. if (!container_type)
  1097. break;
  1098. if (container_type->kind == ContainerType::ARRAY)
  1099. {
  1100. if ((unit_type != vd->symbol->Type()->base_type)
  1101. && unit_type -> IsSubtype(vd->symbol->Type()->base_type))
  1102. {
  1103. nComposite++;
  1104. Coutput << "Composite Pattern." << endl;
  1105. Coutput << unit_type->Utf8Name() << " is the composite class." << endl;
  1106. Coutput << vd->symbol->Utf8Name() << " is the composite instance." << endl;
  1107. Coutput << vd->symbol->Type()->base_type->Utf8Name() << " is the component class." << endl;
  1108. Coutput << "File Location: " << unit_type->file_symbol->FileName() << endl;
  1109. if (vd->symbol->Type()->base_type->file_symbol->IsClassOnly() && getenv("PINOT_HOME"))
  1110. Coutput << "$PINOT_HOME/lib/rt.jar" << vd->symbol->Type()->base_type->fully_qualified_name->value << ".class" << endl << endl;
  1111. else
  1112. Coutput << "File Location: " << vd->symbol->Type()->base_type->file_symbol->FileName() << endl << endl;
  1113. }
  1114. }
  1115. else
  1116. {
  1117. SymbolSet set;
  1118. set.Union(*unit_type->supertypes_closure);
  1119. int ct = 0;
  1120. for (int i = 0; i < d_table -> size(); i++)
  1121. {
  1122. DelegationEntry *entry = d_table -> Entry(i);
  1123. if (entry->vsym
  1124. && (entry->vsym == vd->symbol)
  1125. && container_type->IsPutMethod(entry->call->symbol->MethodCast()))
  1126. {
  1127. TypeSymbol *type = container_type->GetPutType(entry->call);
  1128. if (type && type->supertypes_closure)
  1129. {
  1130. type->supertypes_closure->AddElement(type);
  1131. set.Intersection(*type->supertypes_closure);
  1132. type->supertypes_closure->RemoveElement(type);
  1133. ct++;
  1134. }
  1135. }
  1136. }
  1137. if (ct == 0)
  1138. break;
  1139. //remove java/lang/Object from set
  1140. Utility::RemoveBuiltinInterfaces(set);
  1141. if (set.Size() == 0)
  1142. break;
  1143. nComposite++;
  1144. Coutput << "Composite pattern." << endl;
  1145. Coutput << unit_type->Utf8Name() << " is the composite class." << endl;
  1146. Coutput << vd->symbol->Utf8Name() << " is the composite instance." << endl;
  1147. Coutput << set.FirstElement()->TypeCast()->Utf8Name() << " is the component class." << endl;
  1148. Coutput << "File Location: " << unit_type->file_symbol->FileName() << endl;
  1149. Coutput << "File Location: " << set.FirstElement()->TypeCast()->file_symbol->FileName() << endl << endl;
  1150. /*
  1151. if ((contained_type != unit_type) && contained_type && unit_type -> IsSubtype(contained_type))
  1152. {
  1153. nComposite++;
  1154. Coutput << "Composite pattern." << endl;
  1155. Coutput << unit_type -> Utf8Name() << " is the composite class." << endl;
  1156. Coutput << vd -> symbol -> Utf8Name() << " is the composite instance." << endl;
  1157. Coutput << contained_type -> Utf8Name() << " is the component class." << endl;
  1158. Coutput << "File Location: " << unit_type -> file_symbol -> FileName() << endl;
  1159. Coutput << "File Location: " << contained_type -> file_symbol -> FileName() << endl << endl;
  1160. }
  1161. */
  1162. }
  1163. delete container_type;
  1164. }
  1165. }
  1166. }
  1167. }
  1168. }
  1169. void FindMediator(ClassSymbolTable *cs_table, DelegationTable *d_table)
  1170. {
  1171. unsigned c;
  1172. for (c = 0; c < cs_table -> size(); c++)
  1173. {
  1174. TypeSymbol *unit_type = (*cs_table)[c];
  1175. if (!unit_type -> ACC_INTERFACE()
  1176. && !unit_type -> IsInner()
  1177. && !unit_type -> ACC_PRIVATE())
  1178. {
  1179. SymbolSet colleagues;
  1180. SymbolSet observers;
  1181. SymbolSet *dset = unit_type -> references;
  1182. Symbol *sym = (dset) ? dset->FirstElement() : NULL;
  1183. while (sym)
  1184. {
  1185. TypeSymbol *type = sym -> TypeCast();
  1186. if (!type->Primitive()
  1187. && type -> ACC_ABSTRACT()
  1188. && !type -> ACC_INTERFACE()
  1189. && type -> references
  1190. && (unit_type != type)
  1191. && type -> file_symbol-> IsJava()
  1192. && type -> references -> IsElement(unit_type)
  1193. && unit_type -> IsOnetoMany(type))
  1194. {
  1195. if (d_table -> IsBidirectional(unit_type, type) == 3)
  1196. colleagues.AddElement(type);
  1197. else if (d_table -> IsBidirectional(unit_type, type) > 0)
  1198. observers.AddElement(type);
  1199. }
  1200. sym = dset->NextElement();
  1201. }
  1202. if (!colleagues.IsEmpty())
  1203. {
  1204. nMediator++;
  1205. Coutput << "Mediator pattern." << endl;
  1206. Coutput << unit_type -> Utf8Name() << " is a Mediator class." << endl;
  1207. Symbol *sym = NULL;
  1208. Coutput << "Colleagues: ";
  1209. sym = colleagues.FirstElement();
  1210. while (sym)
  1211. {
  1212. Coutput << sym -> TypeCast() -> Utf8Name() << " ";
  1213. sym = colleagues.NextElement();
  1214. }
  1215. Coutput << endl;
  1216. Coutput << "File Location: " << unit_type -> file_symbol -> FileName() << endl << endl;
  1217. colleagues.SetEmpty();
  1218. }
  1219. else if (!observers.IsEmpty())
  1220. {
  1221. nObserver++;
  1222. Coutput << "Observer pattern." << endl;
  1223. Coutput << unit_type -> Utf8Name() << " is a Subject class." << endl;
  1224. Symbol *sym = NULL;
  1225. Coutput << "Observers: ";
  1226. sym = observers.FirstElement();
  1227. while (sym)
  1228. {
  1229. Coutput << sym -> TypeCast() -> Utf8Name() << " ";
  1230. sym = observers.NextElement();
  1231. }
  1232. Coutput << endl;
  1233. Coutput << "File Location: " << unit_type -> file_symbol -> FileName() << endl << endl;
  1234. observers.SetEmpty();
  1235. }
  1236. }
  1237. }
  1238. }
  1239. bool IsJavaContainer(VariableSymbol *vsym)
  1240. {
  1241. if (strcmp(vsym->Type()->fully_qualified_name->value, "java/util/Iterator") == 0)
  1242. return true;
  1243. if (vsym->Type()->supertypes_closure)
  1244. {
  1245. Symbol *sym = vsym->Type()->supertypes_closure->FirstElement();
  1246. while (sym)
  1247. {
  1248. TypeSymbol *type = sym->TypeCast();
  1249. if (strcmp(type->fully_qualified_name->value, "java/util/Iterator") == 0)
  1250. return true;
  1251. sym = vsym->Type()->supertypes_closure->NextElement();
  1252. }
  1253. }
  1254. return false;
  1255. }
  1256. VariableSymbol *IteratorVar(AstExpression *expression)
  1257. {
  1258. /*
  1259. 1 - java.util.Iterator
  1260. 2 - array index
  1261. 3 - recursion
  1262. */
  1263. AstExpression *resolved = Utility::RemoveCasting(expression);
  1264. if (resolved->kind == Ast::CALL)
  1265. {
  1266. AstMethodInvocation *call = resolved->MethodInvocationCast();
  1267. if (call->base_opt
  1268. && call->base_opt->symbol->VariableCast()
  1269. && IsJavaContainer(call->base_opt->symbol->VariableCast())
  1270. && (strcmp(call->symbol->MethodCast()->Utf8Name(), "next") == 0))
  1271. return call -> base_opt -> NameCast() -> symbol -> VariableCast();
  1272. }
  1273. else if (resolved -> kind == Ast::ARRAY_ACCESS)
  1274. {
  1275. if (resolved -> ArrayAccessCast()->base-> kind == Ast::NAME)
  1276. return resolved -> ArrayAccessCast()->base->symbol->VariableCast();
  1277. }
  1278. else if ((resolved->kind == Ast::NAME) && (resolved->NameCast()->symbol->Kind()==Symbol::VARIABLE))
  1279. {
  1280. return resolved->NameCast()->symbol ->VariableCast();
  1281. }
  1282. return 0;
  1283. }
  1284. VariableSymbol *ListVar(VariableSymbol *vsym)
  1285. {
  1286. if (!vsym->declarator->variable_initializer_opt
  1287. || !vsym->declarator->variable_initializer_opt->ExpressionCast())
  1288. return NULL;
  1289. AstExpression *var_initializer = Utility::RemoveCasting(vsym->declarator->variable_initializer_opt->ExpressionCast());
  1290. // vsym -> IsLocal()
  1291. // vsym is an iterator that implements java.util.Iterator
  1292. if (strcmp( vsym->Type()->fully_qualified_name->value, "java/util/Iterator") == 0)
  1293. {
  1294. if (vsym -> declarator -> variable_initializer_opt -> kind == Ast::CALL)
  1295. {
  1296. AstMethodInvocation *init_call = vsym -> declarator -> variable_initializer_opt -> MethodInvocationCast();
  1297. // iterator initialized at declaration
  1298. if (strcmp(init_call -> symbol -> MethodCast() -> Utf8Name(), "iterator") == 0)
  1299. return (init_call->base_opt->symbol->Kind() == Symbol::VARIABLE)
  1300. ? init_call->base_opt->symbol->VariableCast()
  1301. : 0;
  1302. // iterator initialized later in an assignment statement
  1303. // vsym->owner is a Symbol, but if vsym is local then the owner is a MethodSymbol
  1304. // verify assignment statement
  1305. // if vsym is not local (which should be rare), and is initialized somewhere else (e.g. in other methods, also rare)
  1306. }
  1307. }
  1308. else if (strcmp( vsym->Type()->fully_qualified_name->value, "java/util/ListIterator") == 0)
  1309. {
  1310. if (vsym -> declarator -> variable_initializer_opt -> kind == Ast::CALL)
  1311. {
  1312. AstMethodInvocation *init_call = vsym -> declarator -> variable_initializer_opt -> MethodInvocationCast();
  1313. // iterator initialized at declaration
  1314. if (strcmp(init_call -> symbol -> MethodCast() -> Utf8Name(), "listIterator") == 0)
  1315. return init_call -> base_opt -> NameCast() -> symbol -> VariableCast();
  1316. // iterator initialized later in an assignment statement
  1317. // vsym->owner is a Symbol, but if vsym is local then the owner is a MethodSymbol
  1318. // verify assignment statement
  1319. // if vsym is not local (which should be rare), and is initialized somewhere else (e.g. in other methods, also rare)
  1320. }
  1321. }
  1322. else if ((vsym->declarator->variable_initializer_opt->kind == Ast::NAME)
  1323. && (vsym->declarator->variable_initializer_opt->NameCast()->symbol->Kind()==Symbol::VARIABLE))
  1324. {
  1325. return vsym->declarator->variable_initializer_opt->NameCast()->symbol->VariableCast();
  1326. }
  1327. else if (var_initializer->kind == Ast::CALL)
  1328. {
  1329. AstMethodInvocation *init_call = var_initializer->MethodInvocationCast();
  1330. if (init_call->base_opt && init_call->base_opt->symbol->VariableCast())
  1331. {
  1332. if (((strcmp(init_call->base_opt->symbol->VariableCast()->Type()->fully_qualified_name->value, "java/util/Vector") == 0)
  1333. && (strcmp(init_call->symbol->MethodCast()->Utf8Name(), "elementAt") == 0))
  1334. || ((strcmp(init_call->base_opt->symbol->VariableCast()->Type()->fully_qualified_name->value, "java/util/ArrayList") == 0)
  1335. && (strcmp(init_call->symbol->MethodCast()->Utf8Name(), "get") == 0))
  1336. )
  1337. return init_call->base_opt->symbol->VariableCast();
  1338. else if ((strcmp(init_call->base_opt->symbol->VariableCast()->Type()->fully_qualified_name->value, "java/util/Iterator") == 0)
  1339. && (strcmp(init_call->symbol->MethodCast()->Utf8Name(), "next") == 0))
  1340. {
  1341. VariableSymbol *iterator = init_call->base_opt->symbol->VariableCast();
  1342. AstMethodInvocation *i_init_call = iterator->declarator->variable_initializer_opt->MethodInvocationCast();
  1343. // iterator initialized at declaration
  1344. if (strcmp(i_init_call->symbol->MethodCast()->Utf8Name(), "iterator") == 0)
  1345. return i_init_call->base_opt->symbol->VariableCast();
  1346. }
  1347. }
  1348. }
  1349. return NULL;
  1350. }
  1351. void FindObserver(ClassSymbolTable *cs_table, DelegationTable *d_table)
  1352. {
  1353. vector<TypeSymbol*> cache;
  1354. unsigned c;
  1355. for (c = 0; c < cs_table ->size(); c++)
  1356. {
  1357. TypeSymbol *unit_type = (*cs_table)[c];
  1358. if (!unit_type -> ACC_INTERFACE())
  1359. {
  1360. for (unsigned i = 0; i < unit_type -> declaration-> NumInstanceVariables(); i++)
  1361. {
  1362. AstFieldDeclaration* field_decl = unit_type -> declaration -> InstanceVariable(i);
  1363. for (unsigned vi = 0; vi < field_decl -> NumVariableDeclarators(); vi++)
  1364. {
  1365. AstVariableDeclarator* vd = field_decl -> VariableDeclarator(vi);
  1366. TypeSymbol *generic_type = unit_type -> IsOnetoMany(vd -> symbol, d_table) ;
  1367. if (generic_type && generic_type -> file_symbol)
  1368. {
  1369. for (int j = 0; j < d_table -> size(); j++)
  1370. {
  1371. DelegationEntry* entry = d_table -> Entry(j);
  1372. if ((unit_type == entry -> enclosing -> containing_type) && (generic_type == entry -> to))
  1373. {
  1374. /*
  1375. if ((unit_type == generic_type) && (entry -> vsym == vd -> symbol) && (entry -> enclosing == entry -> method) && (entry -> enclosing -> callers -> Size() > 1))
  1376. {
  1377. nObserver++;
  1378. Coutput << "Observer Pattern." << endl
  1379. << unit_type -> Utf8Name() << " is an observer iterator." << endl
  1380. << generic_type -> Utf8Name() << " is the generic type for the listeners." << endl
  1381. << entry -> enclosing -> Utf8Name() << " is the notify method." << endl
  1382. << entry -> method -> Utf8Name() << " is the update method." << endl;
  1383. Coutput << "Subject class(es):";
  1384. entry -> enclosing -> callers -> Print();
  1385. Coutput << "File Location: " << unit_type->file_symbol->FileName() << endl << endl;
  1386. }
  1387. */
  1388. if (!entry->enclosing->callers
  1389. || (!entry->enclosing->callers -> IsElement(generic_type)
  1390. //&& !entry->enclosing->callers -> IsElement(unit_type)
  1391. )
  1392. )
  1393. {
  1394. VariableSymbol *iterator = 0;
  1395. ControlAnalysis controlflow(entry -> call);
  1396. if (entry -> enclosing -> declaration -> MethodDeclarationCast()
  1397. && entry -> enclosing -> declaration -> MethodDeclarationCast() -> method_body_opt)
  1398. entry -> enclosing -> declaration -> MethodDeclarationCast() -> method_body_opt -> Accept(controlflow);
  1399. if (controlflow.result
  1400. && controlflow.IsRepeated()
  1401. && entry -> base_opt
  1402. && (iterator = IteratorVar(entry->base_opt))
  1403. && ((iterator == vd->symbol)
  1404. || (vd->symbol == unit_type -> Shadows(iterator))
  1405. || (vd -> symbol == ListVar(iterator))))
  1406. {
  1407. // push-model observer pattern
  1408. nObserver++;
  1409. Coutput << "Observer Pattern." << endl
  1410. << unit_type -> Utf8Name() << " is an observer iterator." << endl
  1411. << generic_type -> Utf8Name() << " is the generic type for the listeners." << endl
  1412. << entry -> enclosing -> Utf8Name() << " is the notify method." << endl
  1413. << entry -> method -> Utf8Name() << " is the update method." << endl;
  1414. Coutput << "Subject class(es):";
  1415. if (entry -> enclosing -> callers)
  1416. entry -> enclosing -> callers -> Print();
  1417. else
  1418. Coutput << endl;
  1419. Coutput << "File Location: " << unit_type->file_symbol->FileName() << endl << endl;
  1420. }
  1421. }
  1422. }
  1423. else if ((generic_type == entry -> enclosing -> containing_type) && (unit_type == entry -> to))
  1424. {
  1425. unsigned j = 0;
  1426. for (; (j < cache.size()) && (cache[j] != unit_type) ; j++);
  1427. if (j == cache.size())
  1428. {
  1429. cache.push_back(unit_type);
  1430. nMediator++;
  1431. Coutput << "Mediator Pattern." << endl;
  1432. Coutput << unit_type -> Utf8Name() << " is the mediator class." << endl
  1433. << vd -> symbol -> Utf8Name() << " controls a list of colleagues of type "
  1434. << generic_type -> Utf8Name() << "." << endl;
  1435. Coutput << entry -> method -> Utf8Name()
  1436. << " invokes the mediator. " << endl;
  1437. Coutput << "Subtype(s) of colleague(s): ";
  1438. generic_type -> subtypes -> Print();
  1439. Coutput << "File Location: " << unit_type->file_symbol->FileName() << endl << endl;
  1440. }
  1441. }
  1442. }
  1443. }
  1444. }
  1445. }
  1446. }
  1447. }
  1448. }
  1449. void FindMediator2(ClassSymbolTable *cs_table)
  1450. {
  1451. map<TypeSymbol*, SymbolSet*> cache;
  1452. vector<TypeSymbol*> ordered_cache;
  1453. unsigned c;
  1454. for (c = 0; c < cs_table ->size(); c++)
  1455. {
  1456. TypeSymbol *unit_type = (*cs_table)[c];
  1457. // check if this facade class can be serving as a mediator for some of the hidden classes.
  1458. unsigned i = 0;
  1459. while (i < unit_type->NumMethodSymbols())
  1460. {
  1461. MethodSymbol *msym = unit_type->MethodSym(i);
  1462. if (msym->callers && msym->invokees)
  1463. {
  1464. Symbol *sym1 = msym->callers->FirstElement();
  1465. while (sym1)
  1466. {
  1467. TypeSymbol *caller = sym1->TypeCast();
  1468. Symbol *sym2 = msym->invokees->FirstElement();
  1469. while(sym2)
  1470. {
  1471. TypeSymbol *callee = sym2->MethodCast()->containing_type;
  1472. if (caller->file_symbol
  1473. && caller->file_symbol->IsJava()
  1474. && caller->call_dependents
  1475. && callee->file_symbol
  1476. && callee->file_symbol->IsJava()
  1477. && callee->call_dependents
  1478. && !caller->call_dependents->IsElement(callee)
  1479. && !callee->call_dependents->IsElement(caller)
  1480. && (caller != unit_type)
  1481. && (callee != unit_type)
  1482. )
  1483. {
  1484. if (!unit_type->mediator_colleagues)
  1485. unit_type->mediator_colleagues = new SymbolSet(0);
  1486. unit_type->mediator_colleagues->AddElement(caller);
  1487. unit_type->mediator_colleagues->AddElement(callee);
  1488. /* trying to get rid of STL map
  1489. map<TypeSymbol*, SymbolSet*>::iterator m = cache.find(unit_type);
  1490. if (m == cache.end())
  1491. {
  1492. SymbolSet *set = new SymbolSet(0);
  1493. set->AddElement(caller);
  1494. set->AddElement(callee);
  1495. cache.insert(pair<TypeSymbol*, SymbolSet*>(unit_type, set));
  1496. }
  1497. else
  1498. {
  1499. m->second->AddElement(caller);
  1500. m->second->AddElement(callee);
  1501. }
  1502. */
  1503. }
  1504. sym2 = msym->invokees->NextElement();
  1505. }
  1506. sym1 = msym->callers->NextElement();
  1507. }
  1508. }
  1509. i++;
  1510. }
  1511. }
  1512. // Print results
  1513. /*
  1514. nMediator += cache.size();
  1515. map<TypeSymbol*, SymbolSet*>::iterator pattern;
  1516. for (pattern = cache.begin(); pattern != cache.end(); pattern++)
  1517. {
  1518. Coutput << "Mediator Pattern." << endl;
  1519. Coutput << "Mediator: " << pattern->first->Utf8Name() << endl;
  1520. Coutput << "Colleagues: ";
  1521. pattern->second->Print();
  1522. Coutput << "FileLocation: " << pattern->first->file_symbol->FileName() << endl << endl;
  1523. mediators.AddElement(pattern->first);
  1524. }
  1525. */
  1526. for (c = 0; c < cs_table ->size(); c++)
  1527. {
  1528. if ((*cs_table)[c]->mediator_colleagues)
  1529. {
  1530. nMediator++;
  1531. Coutput << "Mediator Pattern." << endl;
  1532. Coutput << "Mediator: " << (*cs_table)[c]->Utf8Name() << endl;
  1533. Coutput << "Colleagues: ";
  1534. (*cs_table)[c]->mediator_colleagues->Print();
  1535. Coutput << "FileLocation: " << (*cs_table)[c]->file_symbol->FileName() << endl << endl;
  1536. mediators.AddElement((*cs_table)[c]);
  1537. }
  1538. }
  1539. }
  1540. void FindTemplateMethod(DelegationTable *d_table)
  1541. {
  1542. vector<TypeSymbol*> cache;
  1543. for (int i = 0; i < d_table -> size(); i++)
  1544. {
  1545. DelegationEntry* entry = d_table -> Entry(i);
  1546. /*
  1547. if (strcmp(entry -> method -> Utf8Name(), "handleConnect") == 0)
  1548. entry->method->declaration->MethodDeclarationCast()->Print();
  1549. if (strcmp(entry -> method -> Utf8Name(), "target") == 0)
  1550. entry->method->declaration->MethodDeclarationCast()->Print();
  1551. */
  1552. unsigned j = 0;
  1553. for (; (j < cache.size()) && (cache[j] != entry -> from) ; j++);
  1554. if (j == cache.size())
  1555. {
  1556. if ((entry -> enclosing -> containing_type == entry -> method -> containing_type)
  1557. //&& entry -> enclosing -> ACC_PUBLIC()
  1558. && entry -> enclosing -> ACC_FINAL()
  1559. && (entry -> enclosing -> declaration -> kind == Ast::METHOD)
  1560. && (entry -> method -> declaration -> kind == Ast::METHOD)
  1561. && (entry -> from == entry -> to))
  1562. {
  1563. AstMethodDeclaration* method_declaration = entry -> method -> declaration -> MethodDeclarationCast();
  1564. if (entry -> method -> ACC_ABSTRACT()
  1565. || (method_declaration -> method_body_opt == 0)
  1566. || ((method_declaration -> method_body_opt -> Statement(0) -> kind == Ast::RETURN)
  1567. && (method_declaration -> method_body_opt -> Statement(0) -> ReturnStatementCast() -> expression_opt == 0 ))
  1568. )
  1569. {
  1570. nTemplate++;
  1571. cache.push_back(entry -> from);
  1572. Coutput << "Template Method Pattern." << endl;
  1573. Coutput << entry -> from -> Utf8Name() << " is the template class" << endl;
  1574. Coutput << entry -> enclosing -> Utf8Name() << " is the template method" << endl;
  1575. Coutput << entry -> method -> Utf8Name() << " is a primitive method" << endl;
  1576. Coutput << "File Location: " << entry -> from -> file_symbol -> FileName() << endl << endl;
  1577. }
  1578. }
  1579. }
  1580. }
  1581. }
  1582. void FindFactory(ClassSymbolTable *cs_table, MethodSymbolTable *ms_table, StoragePool *ast_pool)
  1583. {
  1584. SymbolSet abstract_factories;
  1585. map<TypeSymbol*, TypeSymbol*> inheritance;
  1586. map<TypeSymbol*, SymbolSet*> concrete_factories;
  1587. for (unsigned i=0; i<ms_table->size(); i++)
  1588. {
  1589. MethodSymbol *method = (*ms_table)[i];
  1590. if (!method -> containing_type -> ACC_ABSTRACT()
  1591. && method->declaration
  1592. //&& method -> declaration -> kind == Ast::METHOD
  1593. && !method -> ACC_PRIVATE()
  1594. && !method -> Type() -> IsArray()
  1595. && method -> Type() -> file_symbol
  1596. && method->declaration->MethodDeclarationCast()
  1597. && method->declaration->MethodDeclarationCast()->method_body_opt)
  1598. {
  1599. FactoryAnalysis factory(method, ast_pool);
  1600. MethodSymbol *abstract_factory_method= NULL;
  1601. if ((abstract_factory_method = method -> GetVirtual())
  1602. && (factory.IsFactoryMethod()))
  1603. {
  1604. abstract_factories.AddElement(abstract_factory_method->containing_type);
  1605. inheritance.insert(pair<TypeSymbol*,TypeSymbol*>(method->containing_type, abstract_factory_method->containing_type));
  1606. map<TypeSymbol*, SymbolSet*>::iterator ci = concrete_factories.find(method->containing_type);
  1607. if (ci == concrete_factories.end())
  1608. {
  1609. SymbolSet *set = new SymbolSet();
  1610. set->Union(factory.types);
  1611. concrete_factories.insert(pair<TypeSymbol*, SymbolSet*>(method->containing_type, set));
  1612. }
  1613. else
  1614. {
  1615. ci->second->Union(factory.types);
  1616. }
  1617. Coutput << "Factory Method Pattern." << endl
  1618. << abstract_factory_method -> containing_type -> Utf8Name() << " is a Factory Method class." << endl;
  1619. Coutput << method -> containing_type -> Utf8Name()
  1620. << " is a concrete Factory Method class."
  1621. << endl
  1622. << method -> Utf8Name()
  1623. << " is a factory method returns ";
  1624. factory.types.Print();
  1625. Coutput << " which extends "
  1626. << method -> Type() -> Utf8Name()
  1627. << endl
  1628. << "File Location: " << method->containing_type->file_symbol->FileName()
  1629. << endl << endl;
  1630. }
  1631. factory.CleanUp();
  1632. }
  1633. }
  1634. nFactoryMethod += abstract_factories.Size();
  1635. //check for family of products, Abstract Factory
  1636. Symbol *sym = abstract_factories.FirstElement();
  1637. while(sym)
  1638. {
  1639. vector<SymbolSet*> sets;
  1640. TypeSymbol *type = sym->TypeCast();
  1641. map<TypeSymbol*, TypeSymbol*>::iterator ii;
  1642. for (ii = inheritance.begin(); ii != inheritance.end(); ii++)
  1643. {
  1644. if (ii->second == type)
  1645. sets.push_back((concrete_factories.find(ii->first))->second);
  1646. }
  1647. //check mutual isolation between sets
  1648. bool flag = false;
  1649. for (unsigned i=0; i<sets.size() && !flag; i++)
  1650. for (unsigned j=0; j<sets.size() && !flag; j++)
  1651. if (i != j)
  1652. flag = sets[i]->Intersects(*sets[j]);
  1653. if (!flag)
  1654. nAbstractFactory++;
  1655. Coutput << "Abstract Factory Pattern." << endl
  1656. << sym->TypeCast()->file_symbol->Utf8Name() << " is the creator class." << endl <<endl;
  1657. sym = abstract_factories.NextElement();
  1658. }
  1659. }
  1660. void FindVisitor(ClassSymbolTable *cs_table, MethodSymbolTable *ms_table)
  1661. {
  1662. multimap<TypeSymbol*, TypeSymbol*> cache;
  1663. for (unsigned i=0; i<ms_table->size(); i++)
  1664. {
  1665. MethodSymbol *method = (*ms_table)[i];
  1666. // Recognizing the Accept(Visitor v) declaration.
  1667. if ((method -> declaration -> kind == Ast::METHOD)
  1668. && method -> ACC_PUBLIC()
  1669. )
  1670. {
  1671. bool flag1 = false;
  1672. unsigned i = 0;
  1673. while (!flag1 && (i < method -> NumFormalParameters()))
  1674. {
  1675. if (method -> FormalParameter(i) -> Type() -> ACC_ABSTRACT()
  1676. && method -> FormalParameter(i) -> Type() -> file_symbol
  1677. && method -> FormalParameter(i) -> Type() -> file_symbol -> IsJava()
  1678. && !method -> containing_type -> IsFamily(method -> FormalParameter(i) -> Type())
  1679. )
  1680. {
  1681. multimap<TypeSymbol*, TypeSymbol*>::iterator p = cache.begin();
  1682. while ((p != cache.end())
  1683. && (!method -> containing_type -> IsSubtype(p -> first) && !method -> FormalParameter(i) -> Type() -> IsSubtype(p -> second)))
  1684. p++;
  1685. if (p == cache.end())
  1686. {
  1687. VariableSymbol *vsym = method -> FormalParameter(i);
  1688. AstMethodDeclaration *method_declaration = method -> declaration -> MethodDeclarationCast();
  1689. if (method_declaration -> method_body_opt)
  1690. {
  1691. AstMethodBody *block = method_declaration -> method_body_opt;
  1692. bool flag2 = false;
  1693. unsigned j = 0;
  1694. while (!flag2 && (j < block -> NumStatements()))
  1695. {
  1696. if ((block -> Statement(j) -> kind == Ast::EXPRESSION_STATEMENT)
  1697. && (block -> Statement(j) -> ExpressionStatementCast() -> expression -> kind == Ast::CALL))
  1698. {
  1699. // analyze the visitor.Accept(this) invocation
  1700. AstMethodInvocation *call = (j < block -> NumStatements())
  1701. ? block -> Statement(j) -> ExpressionStatementCast() -> expression -> MethodInvocationCast()
  1702. : NULL;
  1703. if (call
  1704. && call -> base_opt
  1705. && (call -> base_opt -> kind == Ast::NAME)
  1706. && (call -> base_opt-> NameCast() -> symbol -> VariableCast() == vsym))
  1707. {
  1708. bool flag3 = false;
  1709. unsigned k = 0;
  1710. while (!flag3 && (k < call -> arguments -> NumArguments()))
  1711. {
  1712. if ((call -> arguments -> Argument(k) -> kind == Ast::THIS_EXPRESSION)
  1713. || ((call -> arguments -> Argument(k) -> kind == Ast::NAME)
  1714. && (call -> arguments -> Argument(k) -> NameCast() -> symbol -> VariableCast())
  1715. && (!call -> arguments -> Argument(k) -> NameCast() -> symbol -> VariableCast() -> IsLocal())))
  1716. {
  1717. nVisitor++;
  1718. flag1 = flag2 = flag3 = true;
  1719. Coutput << "Visitor Pattern."
  1720. << endl
  1721. << method -> FormalParameter(i) -> Type() -> Utf8Name()
  1722. << " is an abstract Visitor class."
  1723. << endl
  1724. << method -> containing_type -> Utf8Name()
  1725. << " is a Visitee class."
  1726. << endl;
  1727. TypeSymbol *super_visitee = method -> IsVirtual();
  1728. if (super_visitee)
  1729. {
  1730. cache.insert(pair<TypeSymbol*, TypeSymbol*>(super_visitee, method -> FormalParameter(i) -> Type()));
  1731. Coutput << super_visitee -> Utf8Name()
  1732. << " is an abstract Visitee class."
  1733. << endl;
  1734. super_visitee -> subtypes -> Print();
  1735. }
  1736. else
  1737. {
  1738. cache.insert(pair<TypeSymbol*, TypeSymbol*>(method -> containing_type, method -> FormalParameter(i) -> Type()));
  1739. }
  1740. Coutput << method->Utf8Name() << " is the accept method." << endl;
  1741. Coutput << call -> symbol -> MethodCast() -> Utf8Name() << " is the visit method." << endl;
  1742. if (call -> arguments -> Argument(k) -> kind == Ast::THIS_EXPRESSION)
  1743. Coutput << "THIS pointer is exposed to visitor ";
  1744. else
  1745. Coutput << call -> arguments -> Argument(k) -> NameCast() -> symbol -> VariableCast() -> Utf8Name()
  1746. << " is exposed to visitor ";
  1747. Coutput << method -> FormalParameter(i) -> Type() -> Utf8Name() << endl;
  1748. Coutput << "File Location: "
  1749. << method -> containing_type -> file_symbol -> FileName()
  1750. << endl << endl;
  1751. }
  1752. k++;
  1753. }
  1754. }
  1755. }
  1756. j++;
  1757. }
  1758. }
  1759. }
  1760. }
  1761. i++;
  1762. }
  1763. }
  1764. }
  1765. }
  1766. void FindProxy(ClassSymbolTable *cs_table, DelegationTable *d_table)
  1767. {
  1768. unsigned c;
  1769. for (c = 0; c < cs_table ->size(); c++)
  1770. {
  1771. TypeSymbol *unit_type = (*cs_table)[c];
  1772. SymbolSet *parents = unit_type -> supertypes_closure;
  1773. SymbolSet *instances = unit_type -> instances;
  1774. if (!unit_type->Anonymous() && parents && parents -> Size() && instances)
  1775. {
  1776. Symbol *sym1 = instances -> FirstElement();
  1777. bool flag = false;
  1778. while (!flag && sym1)
  1779. {
  1780. VariableSymbol *vsym = sym1 -> VariableCast();
  1781. TypeSymbol *real = vsym -> Type();
  1782. if (!real -> Primitive() && !real -> IsArray() && vsym->concrete_types)
  1783. {
  1784. Symbol *sym2 = parents -> FirstElement();
  1785. while(!flag && sym2)
  1786. {
  1787. TypeSymbol *type = sym2 ->TypeCast();
  1788. if ((real != unit_type)
  1789. && !type -> Primitive()
  1790. && (strcmp(type->fully_qualified_name->value, "java/lang/Object") != 0)
  1791. && type -> file_symbol
  1792. //&& type -> file_symbol -> IsJava()
  1793. && real -> IsFamily(type)) // use IsFamily
  1794. {
  1795. SymbolSet real_set(0);
  1796. if ((real == type) && type -> subtypes && type -> subtypes -> Size())
  1797. {
  1798. Symbol *sym3 = type -> subtypes -> FirstElement();
  1799. while (sym3)
  1800. {
  1801. real = sym3 -> TypeCast();
  1802. if ((unit_type != real)
  1803. && !real ->Anonymous()
  1804. && real->call_dependents
  1805. && real->call_dependents->IsElement(unit_type))
  1806. {
  1807. real->call_dependents->RemoveElement(unit_type);
  1808. if (!unit_type->call_dependents || !unit_type->call_dependents->Intersects(*real->call_dependents))
  1809. real_set.AddElement(real);
  1810. real->call_dependents->AddElement(unit_type);
  1811. }
  1812. sym3 = type -> subtypes -> NextElement();
  1813. }
  1814. }
  1815. else if (real->call_dependents && real -> call_dependents -> IsElement(unit_type))
  1816. {
  1817. real->call_dependents->RemoveElement(unit_type);
  1818. if (!unit_type->call_dependents || !unit_type->call_dependents->Intersects(*real->call_dependents))
  1819. real_set.AddElement(real);
  1820. real->call_dependents->AddElement(unit_type);
  1821. }
  1822. if (real_set.Size())
  1823. {
  1824. flag = true;
  1825. nProxy++;
  1826. Coutput << "Proxy Pattern." << endl
  1827. << unit_type -> Utf8Name() << " is a proxy."<< endl
  1828. << type -> Utf8Name() << " is a proxy interface." << endl
  1829. << "The real object(s):";
  1830. Symbol *sym = real_set.FirstElement();
  1831. while (sym)
  1832. {
  1833. TypeSymbol *item = sym -> TypeCast();
  1834. if (strcmp(item -> Utf8Name(), type -> Utf8Name()) == 0)
  1835. Coutput << " " << item -> fully_qualified_name -> value;
  1836. else
  1837. Coutput << " " << item -> Utf8Name();
  1838. sym = real_set.NextElement();
  1839. }
  1840. Coutput << endl;
  1841. Coutput << "File Location: " << unit_type -> file_symbol -> FileName() << endl << endl;
  1842. }
  1843. else
  1844. sym2 = parents -> NextElement();
  1845. }
  1846. else
  1847. sym2 = parents -> NextElement();
  1848. }
  1849. if (!flag)
  1850. sym1 = instances -> NextElement();
  1851. }
  1852. else
  1853. sym1 = instances -> NextElement();
  1854. }
  1855. }
  1856. }
  1857. }
  1858. void FindAdapter(ClassSymbolTable *cs_table)
  1859. {
  1860. unsigned c;
  1861. for (c = 0; c < cs_table->size(); c++)
  1862. {
  1863. TypeSymbol *unit_type = (*cs_table)[c];
  1864. if (!unit_type -> ACC_INTERFACE()
  1865. && !unit_type -> ACC_ABSTRACT()
  1866. && unit_type -> supertypes_closure && (unit_type -> supertypes_closure -> Size() > 1)
  1867. && unit_type -> instances)
  1868. {
  1869. Symbol *sym = unit_type -> instances -> FirstElement();
  1870. while (sym)
  1871. {
  1872. TypeSymbol *ref_type = sym->VariableCast() -> Type();
  1873. if (!ref_type -> IsArray()
  1874. && !ref_type -> Primitive()
  1875. && (unit_type != ref_type)
  1876. //&& !ref_type -> ACC_INTERFACE()
  1877. //&& !ref_type -> ACC_ABSTRACT()
  1878. && !unit_type -> IsFamily(ref_type)
  1879. && ref_type -> file_symbol
  1880. && ref_type -> file_symbol -> IsJava()
  1881. && ref_type -> call_dependents
  1882. && ref_type -> call_dependents -> IsElement(unit_type))
  1883. {
  1884. SymbolSet unit_dependents(0);
  1885. if (unit_type->call_dependents)
  1886. unit_dependents.Union(*unit_type->call_dependents);
  1887. unsigned q;
  1888. for (q = 0; q < cs_table->size(); q++)
  1889. {
  1890. TypeSymbol *type = (*cs_table)[q];
  1891. if (unit_type->supertypes_closure->IsElement(type) && type->call_dependents)
  1892. unit_dependents.Union(*type->call_dependents);
  1893. }
  1894. ref_type -> call_dependents -> RemoveElement(unit_type);
  1895. if ((!unit_dependents.Intersects(*ref_type->call_dependents))
  1896. && sym->VariableCast()->concrete_types)
  1897. {
  1898. nAdapter++;
  1899. Coutput << "Adapter Pattern." << endl
  1900. << "Adapting classes: ";
  1901. unit_type->supertypes_closure->Print();
  1902. Coutput << unit_type -> Utf8Name()
  1903. << " is an adapter class." << endl
  1904. << ref_type -> Utf8Name()
  1905. << " is the adaptee class." << endl
  1906. << "File Location: " << unit_type -> file_symbol -> FileName() << endl
  1907. << "File Location: " << ref_type->file_symbol->FileName() << endl << endl;
  1908. }
  1909. ref_type -> call_dependents -> AddElement(unit_type);
  1910. }
  1911. sym = unit_type -> instances -> NextElement();
  1912. }
  1913. }
  1914. }
  1915. }
  1916. void FindFacade(ClassSymbolTable *cs_table)
  1917. {
  1918. unsigned p;
  1919. for (p = 0; p < cs_table->size(); p++)
  1920. {
  1921. TypeSymbol *unit_type = (*cs_table)[p];
  1922. SymbolSet all_dependents(0), hidden_types(0);
  1923. if (!unit_type -> ACC_ABSTRACT()
  1924. && unit_type -> call_dependents
  1925. && unit_type -> associates)
  1926. {
  1927. Symbol *sym = unit_type -> associates -> FirstElement();
  1928. while(sym)
  1929. {
  1930. TypeSymbol *type = sym -> TypeCast();
  1931. if (type -> file_symbol
  1932. && type -> file_symbol -> IsJava()
  1933. && type->call_dependents
  1934. && type->call_dependents->IsElement(unit_type)
  1935. )
  1936. {
  1937. type->call_dependents->RemoveElement(unit_type);
  1938. if (!unit_type -> IsFamily(type)
  1939. && !type -> IsNested()
  1940. && (!type -> call_dependents
  1941. ||!unit_type -> call_dependents -> Intersects(*type -> call_dependents))
  1942. )
  1943. {
  1944. //if (type -> call_dependents)
  1945. // all_dependents.Union(*type -> call_dependents);
  1946. hidden_types.AddElement(type);
  1947. }
  1948. type->call_dependents->AddElement(unit_type);
  1949. }
  1950. sym = unit_type -> associates -> NextElement();
  1951. }
  1952. if ((hidden_types.Size() > 1)
  1953. //&& !unit_type -> call_dependents -> Intersects(all_dependents)
  1954. )
  1955. {
  1956. nFacade++;
  1957. Coutput << "Facade Pattern."
  1958. << endl
  1959. << unit_type -> Utf8Name()
  1960. << " is a facade class."
  1961. << endl;
  1962. Coutput << "Hidden types: " << hidden_types.FirstElement()->TypeCast() -> Utf8Name();
  1963. while (sym = hidden_types.NextElement())
  1964. Coutput << " " << sym -> TypeCast() -> Utf8Name();
  1965. Coutput << endl;
  1966. Coutput << "Facade access types: " << unit_type->call_dependents->FirstElement()->TypeCast() -> Utf8Name();
  1967. while (sym = unit_type->call_dependents->NextElement())
  1968. {
  1969. if ((sym != unit_type) && !sym->TypeCast()->IsNested())
  1970. Coutput << " " << sym -> TypeCast() -> Utf8Name();
  1971. }
  1972. Coutput << endl;
  1973. Coutput << "File Location: " << unit_type -> file_symbol -> FileName()
  1974. << endl << endl;
  1975. if (mediators.IsElement(unit_type))
  1976. nMediatorFacadeDual++;
  1977. }
  1978. }
  1979. }
  1980. }
  1981. void FindThreadSafeInterface(DelegationTable *d_table)
  1982. {
  1983. for (int i = 0; i < d_table -> size(); i++)
  1984. {
  1985. DelegationEntry *entry = d_table -> Entry(i);
  1986. if (entry -> enclosing -> ACC_PRIVATE()
  1987. && (!entry -> base_opt || (entry -> base_opt -> kind == Ast::THIS_CALL))
  1988. && (entry -> enclosing == entry -> method))
  1989. {
  1990. Coutput << entry -> enclosing -> Utf8Name() << " is a private recursive function." << endl;
  1991. Coutput << entry -> from -> file_symbol -> FileName() << endl;
  1992. }
  1993. }
  1994. }
  1995. /***
  1996. * XMI functions
  1997. */
  1998. void PrintSingletonXMI(TypeSymbol *class_sym , VariableSymbol *instance_sym, MethodSymbol *method_sym)
  1999. {
  2000. static ofstream fd("singleton.xmi");
  2001. static int uid = 0;
  2002. static int uuid = 32768;
  2003. assert(fd.is_open());
  2004. if (uid == 0)
  2005. {
  2006. uid++;
  2007. fd << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << endl;
  2008. fd << "<XMI xmi.version=\"1.0\">" << endl;
  2009. fd << " <XMI.header>" << endl;
  2010. fd << " <XMI.documentation>" << endl;
  2011. fd << " <XMI.exporter>Novosoft UML Library</XMI.exporter>" << endl;
  2012. fd << " <XMI.exporterVersion>0.4.20</XMI.exporterVersion>" << endl;
  2013. fd << " </XMI.documentation>" << endl;
  2014. fd << " <XMI.metamodel xmi.name=\"UML\" xmi.version=\"1.3\"/>" << endl;
  2015. fd << " </XMI.header>" << endl;
  2016. fd << " <XMI.content>" << endl;
  2017. fd << " <Model_Management.Model xmi.id=\"xmi." << uid++ << "\" xmi.uuid=\"-87--19-7--58-2b323e:102f1204eed:-8000\">" << endl;
  2018. fd << " <Foundation.Core.ModelElement.name>untitledModel</Foundation.Core.ModelElement.name>" << endl;
  2019. fd << " <Foundation.Core.Namespace.ownedElement>" << endl;
  2020. }
  2021. int cuid = uid, cuuid = uuid - 1;
  2022. int iuid = cuid + 1, iuuid = cuuid - 1;
  2023. int muid = iuid + 1, muuid = iuuid - 1;
  2024. int ruid = muid + 1, ruuid = muuid - 1;
  2025. uid += 4;
  2026. uuid -= 4;
  2027. if (1)
  2028. {
  2029. fd << " <Foundation.Core.Class xmi.id=\"xmi." << cuid << "\" xmi.uuid=\"-87--19-7--58-2b323e:102f1204eed:-" << hex << cuuid << dec << "\">" << endl;
  2030. fd << " <Foundation.Core.ModelElement.name>" << class_sym -> Utf8Name() << "</Foundation.Core.ModelElement.name>" << endl;
  2031. fd << " <Foundation.Core.ModelElement.visibility xmi.value=\"public\"/>" << endl;
  2032. fd << " <Foundation.Core.GeneralizableElement.isAbstract xmi.value=\"" << ((class_sym -> ACC_ABSTRACT())?"true":"false") << "\"/>" << endl;
  2033. fd << " <Foundation.Core.Classifier.feature>" << endl;
  2034. fd << " <Foundation.Core.Attribute xmi.id=\"xmi." << iuid << "\" xmi.uuid=\"-87--19-7--58-2b323e:102f1204eed:-" << hex << iuuid << dec << "\">" << endl;
  2035. fd << " <Foundation.Core.ModelElement.name>" << instance_sym -> Utf8Name() << "</Foundation.Core.ModelElement.name>" << endl;
  2036. fd << " <Foundation.Core.ModelElement.visibility xmi.value=\"private\"/>" << endl;
  2037. fd << " <Foundation.Core.Feature.ownerScope xmi.value=\"classifier\"/>" << endl;
  2038. fd << " <Foundation.Core.Feature.owner>" << endl;
  2039. fd << " <Foundation.Core.Classifier xmi.idref=\"xmi." << cuid << "\"/>" << endl;
  2040. fd << " </Foundation.Core.Feature.owner>" << endl;
  2041. fd << " <Foundation.Core.StructuralFeature.type>" << endl;
  2042. fd << " <Foundation.Core.Classifier xmi.idref=\"xmi." << cuid << "\"/>" << endl;
  2043. fd << " </Foundation.Core.StructuralFeature.type>" << endl;
  2044. fd << " </Foundation.Core.Attribute>" << endl;
  2045. fd << " <Foundation.Core.Operation xmi.id=\"xmi." << muid << "\" xmi.uuid=\"-87--19-7--58-2b323e:102f1204eed:-" << hex << muuid << dec << "\">" << endl;
  2046. fd << " <Foundation.Core.ModelElement.name>" << method_sym -> Utf8Name() << "</Foundation.Core.ModelElement.name>" << endl;
  2047. fd << " <Foundation.Core.ModelElement.visibility xmi.value=\"public\"/>" << endl;
  2048. fd << " <Foundation.Core.Feature.ownerScope xmi.value=\"classifier\"/>" << endl;
  2049. fd << " <Foundation.Core.Operation.concurrency xmi.value=\"" << ((method_sym -> ACC_SYNCHRONIZED())?"concurrent":"sequential") << "\"/>" << endl;
  2050. fd << " <Foundation.Core.Feature.owner>" << endl;
  2051. fd << " <Foundation.Core.Classifier xmi.idref=\"xmi." << cuid << "\"/>" << endl;
  2052. fd << " </Foundation.Core.Feature.owner>" << endl;
  2053. fd << " <Foundation.Core.BehavioralFeature.parameter>" << endl;
  2054. fd << " <Foundation.Core.Parameter xmi.id=\"xmi." << ruid << "\" xmi.uuid=\"-87--19-7--58-2b323e:102f1204eed:-" << hex << ruuid << dec << "\">" << endl;
  2055. fd << " <Foundation.Core.Parameter.kind xmi.value=\"return\"/>" << endl;
  2056. fd << " <Foundation.Core.Parameter.type>" << endl;
  2057. fd << " <Foundation.Core.Classifier xmi.idref=\"xmi." << cuid << "\"/>" << endl;
  2058. fd << " </Foundation.Core.Parameter.type>" << endl;
  2059. fd << " </Foundation.Core.Parameter>" << endl;
  2060. fd << " </Foundation.Core.BehavioralFeature.parameter>" << endl;
  2061. fd << " </Foundation.Core.Operation>" << endl;
  2062. fd << " </Foundation.Core.Classifier.feature>" << endl;
  2063. fd << " </Foundation.Core.Class>" << endl;
  2064. }
  2065. if (uid == 14)
  2066. {
  2067. fd << " </Foundation.Core.Namespace.ownedElement>" << endl;
  2068. fd << " </Model_Management.Model>" << endl;
  2069. fd << " </XMI.content>" << endl;
  2070. fd << "</XMI>" << endl;
  2071. fd.close();
  2072. }
  2073. }
  2074. /*
  2075. * Data-Flow analysis
  2076. */
  2077. void CreationAnalysis::visit(AstClassCreationExpression *class_creation)
  2078. {
  2079. if (class_creation -> class_type -> symbol)
  2080. {
  2081. return_types.push_back(class_creation -> class_type -> symbol -> TypeCast());
  2082. }
  2083. }
  2084. void CreationAnalysis::visit(AstBlock* block)
  2085. {
  2086. // Assumption: isolated entry and exit
  2087. int lstmt = block -> NumStatements() - 1;
  2088. // check the last statement and see what type it returns
  2089. if ( lstmt >= 0)
  2090. {
  2091. if (block -> Statement(lstmt) -> kind == Ast::RETURN)
  2092. {
  2093. AstReturnStatement *return_stmt = block -> Statement(lstmt) -> ReturnStatementCast();
  2094. AstExpression *expression = (return_stmt -> expression_opt -> kind == Ast::CAST)
  2095. ? return_stmt -> expression_opt -> CastExpressionCast() -> expression
  2096. : return_stmt -> expression_opt;
  2097. if (expression -> kind == Ast::CLASS_CREATION)
  2098. {
  2099. expression -> ClassCreationExpressionCast() -> Accept(*this);
  2100. }
  2101. else if ((expression -> kind == Ast::NAME) && (expression -> NameCast() -> symbol -> Kind() == Symbol::VARIABLE))
  2102. {
  2103. // do the backward analysis on this returned vsym
  2104. VariableSymbol *vsym = expression->symbol->VariableCast();
  2105. if (vsym->declarator && vsym->declarator->variable_initializer_opt)
  2106. {
  2107. AstExpression *expr = (vsym->declarator->variable_initializer_opt -> kind == Ast::CAST)
  2108. ? vsym->declarator->variable_initializer_opt -> CastExpressionCast() -> expression
  2109. : vsym->declarator->variable_initializer_opt->ExpressionCast();
  2110. if (expr->kind==Ast::CLASS_CREATION)
  2111. expr->ClassCreationExpressionCast()->Accept(*this);
  2112. }
  2113. else
  2114. {
  2115. signed i = lstmt - 1;
  2116. for (; i >= 0; i--)
  2117. {
  2118. AstExpressionStatement *expression_stmt;
  2119. AstAssignmentExpression *assignment_stmt;
  2120. // should also consider variable initialization upon declaration
  2121. if ((block -> Statement(i) -> kind == Ast::EXPRESSION_STATEMENT)
  2122. && ((expression_stmt = block -> Statement(i) -> ExpressionStatementCast()) -> expression -> kind == Ast::ASSIGNMENT)
  2123. && ((assignment_stmt = expression_stmt -> expression-> AssignmentExpressionCast()) -> lhs(vsym)))
  2124. {
  2125. AstExpression *expr = (assignment_stmt -> expression -> kind == Ast::CAST)
  2126. ? assignment_stmt -> expression -> CastExpressionCast() -> expression
  2127. : assignment_stmt -> expression;
  2128. if (expr-> kind == Ast::CLASS_CREATION)
  2129. expr -> ClassCreationExpressionCast() -> Accept(*this);
  2130. //else if (expr-> kind == Ast::CALL)
  2131. //expr->MethodInvocationCast()->Accept(*this);
  2132. else if (expr-> kind == Ast::NULL_LITERAL)
  2133. return;
  2134. }
  2135. }
  2136. }
  2137. }
  2138. else if (expression -> kind == Ast::CALL)
  2139. {
  2140. AstMethodInvocation *invocation = expression -> MethodInvocationCast();
  2141. MethodSymbol *method = (invocation -> symbol -> Kind() == Symbol::METHOD)
  2142. ? invocation -> symbol -> MethodCast()
  2143. : NULL;
  2144. if (method && !cache.IsElement(method))
  2145. {
  2146. AstMethodDeclaration *declaration = (method && method -> declaration && method -> declaration -> kind == Ast::METHOD)
  2147. ? method -> declaration -> MethodDeclarationCast()
  2148. : NULL;
  2149. if (declaration && declaration -> method_body_opt)
  2150. {
  2151. cache.AddElement(method);
  2152. declaration -> method_body_opt -> Accept(*this);
  2153. }
  2154. }
  2155. }
  2156. else if (expression->kind == Ast::ASSIGNMENT)
  2157. {
  2158. if (expression->AssignmentExpressionCast()->expression->kind == Ast::CLASS_CREATION)
  2159. expression->AssignmentExpressionCast()->expression->ClassCreationExpressionCast()->Accept(*this);
  2160. }
  2161. }
  2162. else if (block->Statement(lstmt)->kind==Ast::TRY)
  2163. {
  2164. block->Statement(lstmt)->TryStatementCast()->block->Accept(*this);
  2165. }
  2166. }
  2167. }
  2168. void ControlAnalysis::visit(AstBlock* block)
  2169. {
  2170. unsigned i = 0;
  2171. for (; (i < block -> NumStatements()) && !result; i++)
  2172. {
  2173. visit(block -> Statement(i));
  2174. }
  2175. }
  2176. void ControlAnalysis::visit(AstSynchronizedStatement *synch_statement)
  2177. {
  2178. visit(synch_statement -> block);
  2179. if (!containing_stmt && result)
  2180. containing_stmt = synch_statement;
  2181. if (result)
  2182. rt_stack.push_back(synch_statement);
  2183. }
  2184. void ControlAnalysis::visit(AstIfStatement* if_statement)
  2185. {
  2186. flag = false;
  2187. cond = if_statement -> expression;
  2188. visit(if_statement -> true_statement);
  2189. if (!result && if_statement -> false_statement_opt)
  2190. {
  2191. flag = true;
  2192. visit(if_statement -> false_statement_opt);
  2193. }
  2194. if (!result)
  2195. {
  2196. flag = false;
  2197. cond = 0;
  2198. containing_stmt = 0;
  2199. }
  2200. if (!containing_stmt && result)
  2201. containing_stmt = if_statement;
  2202. if (result)
  2203. rt_stack.push_back(if_statement);
  2204. }
  2205. void ControlAnalysis::visit(AstConditionalExpression* cond_expression)
  2206. {
  2207. visit(cond_expression -> true_expression);
  2208. if (!result)
  2209. visit(cond_expression -> false_expression);
  2210. if (!containing_stmt && result)
  2211. containing_stmt = cond_expression;
  2212. if (result)
  2213. rt_stack.push_back(cond_expression);
  2214. }
  2215. void ControlAnalysis::visit(AstWhileStatement* while_statement)
  2216. {
  2217. visit(while_statement -> statement);
  2218. if (!containing_stmt && result)
  2219. containing_stmt = while_statement;
  2220. if (result)
  2221. rt_stack.push_back(while_statement);
  2222. }
  2223. void ControlAnalysis::visit(AstForStatement* for_statement)
  2224. {
  2225. visit(for_statement -> statement);
  2226. if (!containing_stmt && result)
  2227. containing_stmt = for_statement;
  2228. if (result)
  2229. rt_stack.push_back(for_statement);
  2230. }
  2231. void ControlAnalysis::visit(AstStatement *statement)
  2232. {
  2233. switch(statement -> kind)
  2234. {
  2235. case Ast::IF:
  2236. visit(statement -> IfStatementCast());
  2237. break;
  2238. case Ast::WHILE:
  2239. visit(statement -> WhileStatementCast());
  2240. break;
  2241. case Ast::FOR:
  2242. visit(statement -> ForStatementCast());
  2243. break;
  2244. case Ast::EXPRESSION_STATEMENT:
  2245. visit(statement -> ExpressionStatementCast() -> expression);
  2246. break;
  2247. case Ast::SYNCHRONIZED_STATEMENT:
  2248. visit(statement -> SynchronizedStatementCast());
  2249. break;
  2250. case Ast::BLOCK:
  2251. visit(statement -> BlockCast());
  2252. break;
  2253. default:
  2254. break;
  2255. }
  2256. }
  2257. void ControlAnalysis::visit(AstExpression *expression)
  2258. {
  2259. result = (this -> expression == expression);
  2260. if (!result)
  2261. {
  2262. switch(expression -> kind)
  2263. {
  2264. case Ast::PARENTHESIZED_EXPRESSION:
  2265. visit(expression -> ParenthesizedExpressionCast() -> expression);
  2266. break;
  2267. case Ast::CAST:
  2268. visit(expression -> CastExpressionCast() -> expression);
  2269. break;
  2270. case Ast::CONDITIONAL:
  2271. visit(expression -> ConditionalExpressionCast());
  2272. break;
  2273. default:
  2274. break;
  2275. }
  2276. }
  2277. }
  2278. bool ControlAnalysis::IsConditional()
  2279. {
  2280. for(unsigned i = 0; i < rt_stack.size(); i++)
  2281. {
  2282. if ((rt_stack[i]->kind == Ast::IF) ||(rt_stack[i]->kind == Ast::CONDITIONAL))
  2283. return true;
  2284. }
  2285. return false;
  2286. }
  2287. bool ControlAnalysis::IsRepeated()
  2288. {
  2289. for(unsigned i = 0; i < rt_stack.size(); i++)
  2290. {
  2291. if ((rt_stack[i]->kind == Ast::WHILE) ||(rt_stack[i]->kind == Ast::FOR))
  2292. return true;
  2293. }
  2294. return false;
  2295. }
  2296. bool ControlAnalysis::IsSynchronized()
  2297. {
  2298. for(unsigned i = 0; i < rt_stack.size(); i++)
  2299. {
  2300. if (rt_stack[i]->kind == Ast::SYNCHRONIZED_STATEMENT)
  2301. return true;
  2302. }
  2303. return false;
  2304. }
  2305. void FlyweightAnalysis::visit(AstBlock* block)
  2306. {
  2307. if (block->NumStatements())
  2308. {
  2309. unsigned lstmt = (block->NumStatements() == 1) ? 0 : (block->NumStatements() - 1);
  2310. for (unsigned i = 0; i < lstmt; i++) visit(block -> Statement(i));
  2311. visit(block->Statement(lstmt));
  2312. UpdateSummary();
  2313. }
  2314. }
  2315. void FlyweightAnalysis::visit(AstWhileStatement* while_statement)
  2316. {
  2317. visit(while_statement->statement);
  2318. }
  2319. void FlyweightAnalysis::visit(AstForStatement* for_statement)
  2320. {
  2321. UpdateSummary();
  2322. conditions.push_back(for_statement->end_expression_opt);
  2323. visit(for_statement->statement);
  2324. UpdateSummary();
  2325. conditions.pop_back();
  2326. }
  2327. void FlyweightAnalysis::visit(AstTryStatement* try_statement)
  2328. {
  2329. visit(try_statement->block);
  2330. }
  2331. void FlyweightAnalysis::visit(AstStatement *statement)
  2332. {
  2333. switch(statement -> kind)
  2334. {
  2335. case Ast::IF:
  2336. visit(statement -> IfStatementCast());
  2337. break;
  2338. case Ast::WHILE:
  2339. visit(statement -> WhileStatementCast());
  2340. break;
  2341. case Ast::FOR:
  2342. visit(statement -> ForStatementCast());
  2343. break;
  2344. case Ast::TRY:
  2345. visit(statement -> TryStatementCast());
  2346. break;
  2347. case Ast::EXPRESSION_STATEMENT:
  2348. visit(statement -> ExpressionStatementCast() -> expression);
  2349. break;
  2350. case Ast::SYNCHRONIZED_STATEMENT:
  2351. visit(statement -> SynchronizedStatementCast());
  2352. break;
  2353. case Ast::BLOCK:
  2354. visit(statement -> BlockCast());
  2355. break;
  2356. case Ast::RETURN:
  2357. visit(statement -> ReturnStatementCast());
  2358. break;
  2359. case Ast::LOCAL_VARIABLE_DECLARATION:
  2360. visit(statement -> LocalVariableStatementCast());
  2361. break;
  2362. default:
  2363. break;
  2364. }
  2365. }
  2366. void FlyweightAnalysis::visit(AstExpression *expression)
  2367. {
  2368. switch(expression -> kind)
  2369. {
  2370. case Ast::PARENTHESIZED_EXPRESSION:
  2371. visit(expression->ParenthesizedExpressionCast() -> expression);
  2372. break;
  2373. case Ast::CAST:
  2374. visit(expression->CastExpressionCast() -> expression);
  2375. break;
  2376. case Ast::CONDITIONAL:
  2377. visit(expression->ConditionalExpressionCast());
  2378. break;
  2379. case Ast::ASSIGNMENT:
  2380. visit(expression->AssignmentExpressionCast());
  2381. break;
  2382. case Ast::CALL:
  2383. visit(expression->MethodInvocationCast());
  2384. break;
  2385. default:
  2386. break;
  2387. }
  2388. }
  2389. void FlyweightAnalysis::visit(AstMethodInvocation* call)
  2390. {
  2391. // might want to check all participants in this method invocationo
  2392. // e.g., base_opt, call->symbol->MethodCast()>Type(), call->arguments->Argument(i), etc
  2393. if (call->NumArguments() > 1)
  2394. {
  2395. AstExpression *expression = *&call->arguments->Argument(1);
  2396. expression = (expression->kind == Ast::CAST) ? expression->CastExpressionCast()->expression : expression;
  2397. if (expression->symbol->VariableCast() && (expression->symbol->VariableCast()->Type() == flyweight))
  2398. {
  2399. statements.push_back(call);
  2400. }
  2401. }
  2402. }
  2403. void FlyweightAnalysis::visit(AstIfStatement* statement)
  2404. {
  2405. UpdateSummary();
  2406. conditions.push_back(statement->expression);
  2407. visit(statement->expression);
  2408. visit(statement->true_statement);
  2409. UpdateSummary();
  2410. conditions.pop_back();
  2411. if (statement->false_statement_opt)
  2412. visit(statement->false_statement_opt);
  2413. }
  2414. void FlyweightAnalysis::visit(AstAssignmentExpression *expression)
  2415. {
  2416. if (expression->left_hand_side->symbol->VariableCast()
  2417. && (expression->left_hand_side->symbol->VariableCast()->Type() == flyweight))
  2418. statements.push_back(expression);
  2419. else if (expression->left_hand_side->symbol->TypeCast()
  2420. && (expression->left_hand_side->symbol->TypeCast() == flyweight))
  2421. statements.push_back(expression);
  2422. // TODO also check for aliasing
  2423. }
  2424. void FlyweightAnalysis::visit(AstLocalVariableStatement* local_var)
  2425. {
  2426. if (local_var->type->symbol == flyweight)
  2427. {
  2428. for (unsigned i=0; i < local_var->NumVariableDeclarators(); i++)
  2429. visit(local_var->VariableDeclarator(i));
  2430. }
  2431. }
  2432. void FlyweightAnalysis::visit(AstVariableDeclarator* var_declarator)
  2433. {
  2434. if (var_declarator->variable_initializer_opt && (var_declarator->symbol->Type() == flyweight))
  2435. statements.push_back(var_declarator);
  2436. }
  2437. void FlyweightAnalysis::visit(AstReturnStatement* statement)
  2438. {
  2439. if (statement->expression_opt)
  2440. {
  2441. if (statement->expression_opt->symbol->VariableCast()
  2442. && (statement->expression_opt->symbol->VariableCast()->Type() == flyweight))
  2443. statements.push_back(statement);
  2444. else if (statement->expression_opt->symbol->TypeCast()
  2445. && (statement->expression_opt->symbol->TypeCast() == flyweight))
  2446. statements.push_back(statement);
  2447. }
  2448. }
  2449. void FlyweightAnalysis::UpdateSummary()
  2450. {
  2451. if (statements.size())
  2452. {
  2453. Snapshot *snapshot = new Snapshot();
  2454. snapshot->statements = new vector<Ast*>(statements);
  2455. statements.clear();
  2456. if (conditions.size())
  2457. {
  2458. snapshot->conditions = new vector<AstExpression*>(conditions);
  2459. }
  2460. snapshot->index = summary.size();
  2461. summary.push_back(snapshot);
  2462. }
  2463. }
  2464. void FlyweightAnalysis::DumpSummary()
  2465. {
  2466. Coutput << GetFlyweight->Utf8Name() << endl;
  2467. for (unsigned i = 0; i < summary.size(); i++)
  2468. {
  2469. Snapshot *snapshot = summary[i];
  2470. Coutput << "Snapshot[" << i << "]" << endl;
  2471. Coutput << "STATEMENTS:" << endl;
  2472. unsigned j;
  2473. for (j = 0; j < snapshot->statements->size(); j++)
  2474. {
  2475. if ((*snapshot->roles)[j]->vsym)
  2476. Coutput << (*snapshot->roles)[j]->vsym->Utf8Name();
  2477. else
  2478. Coutput << (*snapshot->roles)[j]->array_access->base->symbol->VariableCast()->Utf8Name()
  2479. << "[" << (*snapshot->roles)[j]->array_access->expression->symbol->VariableCast()->Utf8Name() << "]";
  2480. Coutput << ": " << (*snapshot->roles)[j]->TagName() << endl;
  2481. (*snapshot->statements)[j]->Print();
  2482. }
  2483. Coutput << "CONDITIONS:" << endl;
  2484. if (snapshot->conditions)
  2485. {
  2486. for (j = 0; j < snapshot->conditions->size(); j++)
  2487. (*snapshot->conditions)[j]->Print();
  2488. }
  2489. Coutput << endl;
  2490. }
  2491. }
  2492. char *Role::TagName()
  2493. {
  2494. switch(tag)
  2495. {
  2496. case CREATE:
  2497. return "CREATE";
  2498. case REGISTER:
  2499. return "REGISTER";
  2500. case RETRIEVE:
  2501. return "RETRIEVE";
  2502. case ALLOCATE:
  2503. return "ALLOCATE";
  2504. case RETURN:
  2505. return "RETURN";
  2506. case NIL:
  2507. return "NULL";
  2508. default:
  2509. return "N/A";
  2510. }
  2511. }
  2512. bool MapContainer::IsGetMethod(MethodSymbol *msym)
  2513. {
  2514. return (strcmp(msym->Utf8Name(), "get") == 0);
  2515. }
  2516. bool MapContainer::IsPutMethod(MethodSymbol *msym)
  2517. {
  2518. return ((strcmp(msym->Utf8Name(), "put") == 0) && (strcmp(msym->SignatureString(), "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;") == 0));
  2519. }
  2520. VariableSymbol *MapContainer::GetPutValue(AstMethodInvocation *call)
  2521. {
  2522. return (*&call->arguments->Argument(1))->CastExpressionCast()->expression->symbol->VariableCast();
  2523. }
  2524. TypeSymbol *MapContainer::GetPutType(AstMethodInvocation *call)
  2525. {
  2526. Symbol *sym = ((*&call->arguments->Argument(1))->kind == Ast::CAST)
  2527. ? (*&call->arguments->Argument(1))->CastExpressionCast()->expression->symbol
  2528. : (*&call->arguments->Argument(1))->symbol;
  2529. return Utility::GetTypeSymbol(sym);
  2530. }
  2531. bool CollectionContainer::IsPutMethod(MethodSymbol *msym)
  2532. {
  2533. // check signature too? or No. Arguments
  2534. return ((strcmp(msym->Utf8Name(), "add") == 0) && (strcmp(msym->SignatureString(), "(Ljava/lang/Object;)Z") == 0));
  2535. }
  2536. VariableSymbol *CollectionContainer::GetPutValue(AstMethodInvocation *call)
  2537. {
  2538. return (*&call->arguments->Argument(0))->CastExpressionCast()->expression->symbol->VariableCast();
  2539. }
  2540. TypeSymbol *CollectionContainer::GetPutType(AstMethodInvocation *call)
  2541. {
  2542. Symbol *sym = ((*&call->arguments->Argument(0))->kind == Ast::CAST)
  2543. ? (*&call->arguments->Argument(0))->CastExpressionCast()->expression->symbol
  2544. : (*&call->arguments->Argument(0))->symbol;
  2545. if (sym->Kind() == Symbol::TYPE)
  2546. return sym->TypeCast();
  2547. else if (sym->Kind() == Symbol::VARIABLE)
  2548. return sym->VariableCast()->Type();
  2549. else if (sym->Kind() == Symbol::METHOD)
  2550. return sym->MethodCast()->Type();
  2551. else
  2552. return NULL;
  2553. }
  2554. bool ArrayListContainer::IsPutMethod(MethodSymbol *msym)
  2555. {
  2556. if ((strcmp(msym->Utf8Name(), "add") == 0)
  2557. && ((strcmp(msym->SignatureString(), "(Ljava/lang/Object;)Z") == 0) || (strcmp(msym->SignatureString(), "(I;Ljava/lang/Object;)V") == 0)))
  2558. return true;
  2559. else
  2560. return false;
  2561. }
  2562. bool LinkedListContainer::IsPutMethod(MethodSymbol *msym)
  2563. {
  2564. if ((strcmp(msym->Utf8Name(), "add") == 0)
  2565. && ((strcmp(msym->SignatureString(), "(Ljava/lang/Object;)Z") == 0) || (strcmp(msym->SignatureString(), "(I;Ljava/lang/Object;)V") == 0)))
  2566. return true;
  2567. else if (((strcmp(msym->Utf8Name(), "addFirst") == 0) || (strcmp(msym->Utf8Name(), "addLast") == 0))
  2568. && ((strcmp(msym->SignatureString(), "(Ljava/lang/Object;)V") == 0)))
  2569. return true;
  2570. else
  2571. return false;
  2572. }
  2573. bool VectorContainer::IsPutMethod(MethodSymbol *msym)
  2574. {
  2575. if ((strcmp(msym->Utf8Name(), "add") == 0)
  2576. && ((strcmp(msym->SignatureString(), "(Ljava/lang/Object;)Z") == 0) || (strcmp(msym->SignatureString(), "(I;Ljava/lang/Object;)V") == 0)))
  2577. return true;
  2578. else if ((strcmp(msym->Utf8Name(), "addElement") == 0)
  2579. && ((strcmp(msym->SignatureString(), "(Ljava/lang/Object;)V") == 0)))
  2580. return true;
  2581. else
  2582. return false;
  2583. }
  2584. bool HashSetContainer::IsPutMethod(MethodSymbol *msym)
  2585. {
  2586. if ((strcmp(msym->Utf8Name(), "add") == 0)
  2587. && (strcmp(msym->SignatureString(), "(Ljava/lang/Object;)Z") == 0))
  2588. return true;
  2589. else
  2590. return false;
  2591. }
  2592. VariableSymbol *ArrayListContainer::GetPutValue(AstMethodInvocation *call)
  2593. {
  2594. if (call->arguments->NumArguments() == 1)
  2595. return (*&call->arguments->Argument(0))->CastExpressionCast()->expression->symbol->VariableCast();
  2596. else
  2597. return (*&call->arguments->Argument(1))->CastExpressionCast()->expression->symbol->VariableCast();
  2598. }
  2599. VariableSymbol *LinkedListContainer::GetPutValue(AstMethodInvocation *call)
  2600. {
  2601. if (call->arguments->NumArguments() == 1)
  2602. return (*&call->arguments->Argument(0))->CastExpressionCast()->expression->symbol->VariableCast();
  2603. else
  2604. return (*&call->arguments->Argument(1))->CastExpressionCast()->expression->symbol->VariableCast();
  2605. }
  2606. VariableSymbol *VectorContainer::GetPutValue(AstMethodInvocation *call)
  2607. {
  2608. if (call->arguments->NumArguments() == 1)
  2609. return (*&call->arguments->Argument(0))->CastExpressionCast()->expression->symbol->VariableCast();
  2610. else
  2611. return (*&call->arguments->Argument(1))->CastExpressionCast()->expression->symbol->VariableCast();
  2612. }
  2613. VariableSymbol *HashSetContainer::GetPutValue(AstMethodInvocation *call)
  2614. {
  2615. return (*&call->arguments->Argument(0))->CastExpressionCast()->expression->symbol->VariableCast();
  2616. }
  2617. TypeSymbol *ArrayListContainer::GetPutType(AstMethodInvocation *call)
  2618. {
  2619. AstExpression *expr = (call->arguments->NumArguments() == 1)
  2620. ? (*&call->arguments->Argument(0))
  2621. : (*&call->arguments->Argument(1));
  2622. Symbol *sym = (expr->kind == Ast::CAST)
  2623. ? expr->CastExpressionCast()->expression->symbol
  2624. : expr->symbol;
  2625. return Utility::GetTypeSymbol(sym);
  2626. }
  2627. TypeSymbol *LinkedListContainer::GetPutType(AstMethodInvocation *call)
  2628. {
  2629. AstExpression *expr = (call->arguments->NumArguments() == 1)
  2630. ? (*&call->arguments->Argument(0))
  2631. : (*&call->arguments->Argument(1));
  2632. Symbol *sym = (expr->kind == Ast::CAST)
  2633. ? expr->CastExpressionCast()->expression->symbol
  2634. : expr->symbol;
  2635. return Utility::GetTypeSymbol(sym);
  2636. }
  2637. TypeSymbol *VectorContainer::GetPutType(AstMethodInvocation *call)
  2638. {
  2639. AstExpression *expr = (call->arguments->NumArguments() == 1)
  2640. ? (*&call->arguments->Argument(0))
  2641. : (*&call->arguments->Argument(1));
  2642. Symbol *sym = (expr->kind == Ast::CAST)
  2643. ? expr->CastExpressionCast()->expression->symbol
  2644. : expr->symbol;
  2645. return Utility::GetTypeSymbol(sym);
  2646. }
  2647. TypeSymbol *HashSetContainer::GetPutType(AstMethodInvocation *call)
  2648. {
  2649. AstExpression *expr = (*&call->arguments->Argument(0));
  2650. Symbol *sym = (expr->kind == Ast::CAST)
  2651. ? expr->CastExpressionCast()->expression->symbol
  2652. : expr->symbol;
  2653. return Utility::GetTypeSymbol(sym);
  2654. }
  2655. void FlyweightAnalysis::AssignRoles()
  2656. {
  2657. for (unsigned i = 0; i < summary.size(); i++)
  2658. {
  2659. Snapshot *snapshot = summary[i];
  2660. snapshot->roles = new vector<Role*>();
  2661. for (unsigned j = 0; j < snapshot->statements->size(); j++)
  2662. {
  2663. Ast *stmt = (*snapshot->statements)[j];
  2664. if (stmt->kind == Ast::VARIABLE_DECLARATOR)
  2665. {
  2666. AstVariableDeclarator *var_declarator = stmt->VariableDeclaratorCast();
  2667. if (var_declarator->variable_initializer_opt)
  2668. {
  2669. if (var_declarator->variable_initializer_opt->kind == Ast::CLASS_CREATION)
  2670. {
  2671. //TODO: check parameters as well.
  2672. snapshot->roles->push_back(new Role(var_declarator->symbol, Role::CREATE));
  2673. }
  2674. else if ((var_declarator->variable_initializer_opt->kind == Ast::PARENTHESIZED_EXPRESSION)
  2675. && (var_declarator->variable_initializer_opt->ParenthesizedExpressionCast()->expression->kind == Ast::CAST)
  2676. && (var_declarator->variable_initializer_opt->ParenthesizedExpressionCast()->expression->CastExpressionCast()->expression->kind == Ast::CALL))
  2677. {
  2678. AstMethodInvocation *call = var_declarator->variable_initializer_opt->ParenthesizedExpressionCast()->expression->CastExpressionCast()->expression->MethodInvocationCast();
  2679. if (call->base_opt && call->base_opt->symbol->VariableCast())
  2680. {
  2681. if (!container_type)
  2682. container_type = Utility::IdentifyContainerType(call->base_opt->symbol->VariableCast());
  2683. if (container_type && container_type->IsGetMethod(call->symbol->MethodCast()))
  2684. snapshot->roles->push_back(new Role(var_declarator->symbol, Role::RETRIEVE));
  2685. }
  2686. }
  2687. else if (var_declarator->variable_initializer_opt->kind == Ast::ARRAY_ACCESS)
  2688. {
  2689. if (!container_type)
  2690. container_type = new ArrayContainer(var_declarator->variable_initializer_opt->ArrayAccessCast()->base->symbol->VariableCast());
  2691. //TODO: check for method invocation from a hashtable/collection.
  2692. snapshot->roles->push_back(new Role(var_declarator->symbol, Role::RETRIEVE));
  2693. }
  2694. else if (var_declarator->variable_initializer_opt->kind == Ast::NULL_LITERAL)
  2695. {
  2696. snapshot->roles->push_back(new Role(var_declarator->symbol, Role::NIL));
  2697. }
  2698. }
  2699. }
  2700. else if (stmt->kind == Ast::ASSIGNMENT)
  2701. {
  2702. AstAssignmentExpression *assignment = stmt->AssignmentExpressionCast();
  2703. if (assignment->left_hand_side->kind == Ast::ARRAY_ACCESS)
  2704. {
  2705. if (!container_type)
  2706. container_type = new ArrayContainer(assignment->left_hand_side->ArrayAccessCast()->base->symbol->VariableCast());
  2707. if (assignment->expression->symbol->VariableCast())
  2708. {
  2709. snapshot->roles->push_back(new Role(assignment->expression->symbol->VariableCast(), Role::REGISTER));
  2710. }
  2711. else if (assignment->expression->kind == Ast::CLASS_CREATION)
  2712. {
  2713. snapshot->roles->push_back(new Role(assignment->left_hand_side->ArrayAccessCast(), Role::ALLOCATE));
  2714. }
  2715. }
  2716. else if (assignment->left_hand_side->symbol->VariableCast())
  2717. {
  2718. if (assignment->expression->kind == Ast::CLASS_CREATION)
  2719. {
  2720. //TODO: check parameters as well.
  2721. snapshot->roles->push_back(new Role(assignment->left_hand_side->symbol->VariableCast(), Role::CREATE));
  2722. }
  2723. else if (assignment->expression->kind == Ast::ARRAY_ACCESS)
  2724. {
  2725. if (!container_type)
  2726. container_type = new ArrayContainer(assignment->expression->ArrayAccessCast()->base->symbol->VariableCast());
  2727. snapshot->roles->push_back(new Role(assignment->left_hand_side->symbol->VariableCast(), Role::RETRIEVE));
  2728. }
  2729. else if ((assignment->expression->kind == Ast::PARENTHESIZED_EXPRESSION)
  2730. && (assignment->expression->ParenthesizedExpressionCast()->expression->kind == Ast::CAST)
  2731. && (assignment->expression->ParenthesizedExpressionCast()->expression->CastExpressionCast()->expression->kind == Ast::CALL))
  2732. {
  2733. AstMethodInvocation *call = assignment->expression->ParenthesizedExpressionCast()->expression->CastExpressionCast()->expression->MethodInvocationCast();
  2734. if (call->base_opt && call->base_opt->symbol->VariableCast())
  2735. {
  2736. if (!container_type)
  2737. container_type = Utility::IdentifyContainerType(call->base_opt->symbol->VariableCast());
  2738. if (container_type && container_type->IsGetMethod(call->symbol->MethodCast()))
  2739. snapshot->roles->push_back(new Role(assignment->left_hand_side->symbol->VariableCast(), Role::RETRIEVE));
  2740. }
  2741. }
  2742. }
  2743. }
  2744. else if (stmt->kind == Ast::CALL)
  2745. {
  2746. AstMethodInvocation *call = stmt->MethodInvocationCast();
  2747. if (call->base_opt && call->base_opt->symbol->VariableCast())
  2748. {
  2749. if (!container_type)
  2750. container_type = Utility::IdentifyContainerType(call->base_opt->symbol->VariableCast());
  2751. if (container_type && container_type->IsPutMethod(call->symbol->MethodCast()))
  2752. snapshot->roles->push_back(new Role(container_type->GetPutValue(call), Role::REGISTER));
  2753. }
  2754. }
  2755. else if (stmt->kind == Ast::RETURN)
  2756. {
  2757. AstReturnStatement *return_stmt = stmt->ReturnStatementCast();
  2758. if (return_stmt->expression_opt)
  2759. {
  2760. if (return_stmt->expression_opt->symbol->VariableCast())
  2761. {
  2762. snapshot->roles->push_back(new Role(return_stmt->expression_opt->symbol->VariableCast(), Role::RETURN));
  2763. }
  2764. else if (return_stmt->expression_opt->kind == Ast::ARRAY_ACCESS)
  2765. {
  2766. snapshot->roles->push_back(new Role(return_stmt->expression_opt->ArrayAccessCast(), Role::RETURN));
  2767. }
  2768. }
  2769. traces.push_back(snapshot);
  2770. }
  2771. }
  2772. }
  2773. }
  2774. bool FlyweightAnalysis::IsFlyweightFactory()
  2775. {
  2776. AssignRoles();
  2777. n = 0;
  2778. for (unsigned t = 0; t < traces.size(); t++)
  2779. {
  2780. VariableSymbol *returned_var = NULL;
  2781. AstArrayAccess *returned_ref = NULL;
  2782. Snapshot *val_recorded = NULL;
  2783. bool create_pending = false;
  2784. for (unsigned i = traces[t]->index; i < summary.size(); i--)
  2785. {
  2786. Snapshot *snapshot = summary[i];
  2787. vector<Role*> *roles = snapshot->roles;
  2788. unsigned j = roles->size() - 1;
  2789. for (; j < roles->size(); j--)
  2790. {
  2791. Role *role = (*roles)[j];
  2792. if ((!returned_var && !returned_ref) && (role->tag == Role::RETURN))
  2793. {
  2794. if (role->vsym)
  2795. returned_var = role->vsym;
  2796. else
  2797. {
  2798. returned_ref = role->array_access;
  2799. bitmap[n] = 'E';
  2800. }
  2801. }
  2802. else if (role->tag == Role::ALLOCATE)
  2803. {
  2804. if ((returned_ref->base->symbol == role->array_access->base->symbol)
  2805. && (returned_ref->expression->symbol == returned_ref->expression->symbol))
  2806. {
  2807. bitmap[n] = 'N';
  2808. /*
  2809. Coutput << "returns new flyweight object in "
  2810. << returned_ref->base->symbol->VariableCast()->Utf8Name() << "["
  2811. << returned_ref->expression->symbol->VariableCast()->Utf8Name() << "]" << endl;
  2812. */
  2813. }
  2814. }
  2815. else if ((returned_var == role->vsym) && (role->tag == Role::REGISTER))
  2816. {
  2817. create_pending = true;
  2818. }
  2819. else if (create_pending && (returned_var == role->vsym) && (role->tag == Role::CREATE))
  2820. {
  2821. // the algorithm should reject if a CREATE occurs w/o create_pending
  2822. bitmap[n] = 'N';
  2823. //Coutput << "returns new flyweight object in " << returned_var->Utf8Name() << endl;
  2824. create_pending = false;
  2825. val_recorded = snapshot;
  2826. }
  2827. else if ((returned_var == role->vsym) && (role->tag == Role::RETRIEVE))
  2828. {
  2829. if (val_recorded && val_recorded->conditions)
  2830. {
  2831. for (unsigned k = 0; k < val_recorded->conditions->size(); k++)
  2832. {
  2833. if ((*val_recorded->conditions)[k]->kind == Ast::BINARY)
  2834. {
  2835. AstBinaryExpression *expression = (*val_recorded->conditions)[k]->BinaryExpressionCast();
  2836. if ((expression->left_expression->symbol == role->vsym)
  2837. && (expression->right_expression->kind == Ast::NULL_LITERAL)
  2838. && (expression->Tag()==AstBinaryExpression::EQUAL_EQUAL))
  2839. {
  2840. bitmap[++n] = 'E';
  2841. //Coutput << "returns existing flyweight object in " << returned_var->Utf8Name() << endl;
  2842. break;
  2843. }
  2844. }
  2845. }
  2846. }
  2847. else
  2848. {
  2849. bitmap[n] = 'E';
  2850. //Coutput << "returns existing flyweight object in " << returned_var->Utf8Name() << endl;
  2851. val_recorded = snapshot;
  2852. }
  2853. }
  2854. }
  2855. }
  2856. n++;
  2857. }
  2858. return (n==2) && (((bitmap[0] == 'E') && (bitmap[1] == 'N')) || ((bitmap[0] == 'N') && (bitmap[1] == 'E')));
  2859. }
  2860. ChainAnalysis::ResultTag ChainAnalysis::AnalyzeCallChain()
  2861. {
  2862. flatten.BuildSummary();
  2863. //flatten.DumpSummary();
  2864. for (unsigned t = 0; t < flatten.traces.size(); t++)
  2865. {
  2866. Snapshot *snapshot = flatten.traces[t];
  2867. path.clear();
  2868. path.push_back(snapshot->index);
  2869. TracePath(snapshot);
  2870. }
  2871. // analyze exec paths HERE
  2872. // for footprints, check for duplicates
  2873. for (unsigned i = 0; i < footprints.size(); i++)
  2874. for (unsigned j = 0; j < footprints.size(); j++)
  2875. if ((i != j) && (footprints[i] == footprints[j]))
  2876. return NONE;
  2877. unsigned occurrances = 0;
  2878. for (unsigned i = 0; i < paths.size(); i++)
  2879. {
  2880. vector<signed> result;
  2881. Utility::Intersection(footprints, paths[i], result);
  2882. if (result.size() == 1)
  2883. occurrances++;
  2884. }
  2885. if (occurrances == paths.size())
  2886. return DECORATOR;
  2887. else if (occurrances == 1)
  2888. // check for deferral
  2889. return CoR;
  2890. else
  2891. return NONE;
  2892. }
  2893. void ChainAnalysis::TraceBinaryExpression(AstBinaryExpression *expression, Snapshot *snapshot)
  2894. {
  2895. if (expression->left_expression->MethodInvocationCast()
  2896. && expression->left_expression->MethodInvocationCast()->base_opt
  2897. && expression->left_expression->MethodInvocationCast()->symbol->MethodCast()
  2898. && (expression->left_expression->MethodInvocationCast()->base_opt->symbol == variable)
  2899. && ((expression->left_expression->MethodInvocationCast()->symbol == method)
  2900. || (strcmp(expression->left_expression->MethodInvocationCast()->symbol->MethodCast()->Utf8Name(), method->Utf8Name()) == 0))
  2901. && (strcmp(expression->left_expression->MethodInvocationCast()->symbol->MethodCast()->SignatureString(), method->SignatureString()) == 0)
  2902. )
  2903. footprints.push_back(snapshot->index);
  2904. else if (expression->right_expression->MethodInvocationCast()
  2905. && expression->right_expression->MethodInvocationCast()->base_opt
  2906. && expression->right_expression->MethodInvocationCast()->symbol->MethodCast()
  2907. && (expression->right_expression->MethodInvocationCast()->base_opt->symbol == variable)
  2908. && ((expression->right_expression->MethodInvocationCast()->symbol == method)
  2909. || (strcmp(expression->right_expression->MethodInvocationCast()->symbol->MethodCast()->Utf8Name(), method->Utf8Name()) == 0))
  2910. && (strcmp(expression->right_expression->MethodInvocationCast()->symbol->MethodCast()->SignatureString(), method->SignatureString()) == 0)
  2911. )
  2912. footprints.push_back(snapshot->index);
  2913. else if (expression->left_expression->kind == Ast::BINARY)
  2914. TraceBinaryExpression(expression->left_expression->BinaryExpressionCast(), snapshot);
  2915. else if (expression->right_expression->kind == Ast::BINARY)
  2916. TraceBinaryExpression(expression->right_expression->BinaryExpressionCast(), snapshot);
  2917. }
  2918. void ChainAnalysis::TracePath(Snapshot *snapshot)
  2919. {
  2920. set<signed> next(snapshot->previous);
  2921. for (unsigned j = snapshot->statements->size() - 1; j < snapshot->statements->size(); j--)
  2922. {
  2923. Ast *statement = (*snapshot->statements)[j];
  2924. if (statement->kind == Ast::RETURN)
  2925. {
  2926. if (statement->ReturnStatementCast()->expression_opt)
  2927. {
  2928. AstExpression *expression = Utility::RemoveCasting(statement->ReturnStatementCast()->expression_opt);
  2929. if (expression->kind == Ast::CALL)
  2930. {
  2931. AstMethodInvocation *call = expression->MethodInvocationCast();
  2932. VariableSymbol *vsym = (call->base_opt) ? call->base_opt->symbol->VariableCast() : NULL;
  2933. MethodSymbol *msym = call->symbol->MethodCast();
  2934. if ((vsym == variable)
  2935. && ((msym == method) || (strcmp(msym->Utf8Name(), method->Utf8Name()) == 0))
  2936. && (strcmp(msym->SignatureString(), method->SignatureString()) == 0))
  2937. {
  2938. footprints.push_back(snapshot->index);
  2939. }
  2940. }
  2941. else if (expression->kind == Ast::BINARY)
  2942. {
  2943. TraceBinaryExpression(expression->BinaryExpressionCast(), snapshot);
  2944. }
  2945. }
  2946. }
  2947. else if (statement->kind == Ast::CALL)
  2948. {
  2949. AstMethodInvocation *call = statement->MethodInvocationCast();
  2950. VariableSymbol *vsym = (call->base_opt) ? call->base_opt->symbol->VariableCast() : NULL;
  2951. MethodSymbol *msym = call->symbol->MethodCast();
  2952. if ((vsym == variable)
  2953. && ((msym == method) ||(strcmp(msym->Utf8Name(), method->Utf8Name()) == 0))
  2954. && (strcmp(msym->SignatureString(), method->SignatureString()) == 0))
  2955. {
  2956. footprints.push_back(snapshot->index);
  2957. }
  2958. }
  2959. }
  2960. set<signed>::iterator p;
  2961. for (p = next.begin(); p != next.end(); p++)
  2962. {
  2963. if (*p >= 0)
  2964. {
  2965. path.push_back(*p);
  2966. TracePath(flatten.summary[*p]);
  2967. path.pop_back();
  2968. }
  2969. else
  2970. {
  2971. paths.push_back(path);
  2972. }
  2973. }
  2974. }
  2975. SymbolSet SingletonAnalysis::visited;
  2976. bool SingletonAnalysis::ReturnsSingleton()
  2977. {
  2978. visited.AddElement(method);
  2979. flatten.BuildSummary();
  2980. //flatten.DumpSummary();
  2981. for (unsigned t = 0; t < flatten.traces.size(); t++)
  2982. {
  2983. Snapshot *snapshot = flatten.traces[t];
  2984. path.clear();
  2985. path.push_back(snapshot->index);
  2986. TracePath(snapshot);
  2987. }
  2988. // footprints, remove duplicates
  2989. Utility::RemoveDuplicates(footprints);
  2990. if (fingerprints.size() == 0)
  2991. return false;
  2992. else if ((fingerprints.size() == 1) && (footprints.size() == 0))
  2993. {
  2994. return (variable->declarator->variable_initializer_opt && (variable->declarator->variable_initializer_opt->kind == Ast::CLASS_CREATION));
  2995. }
  2996. else if (footprints.size() != 1)
  2997. return false;
  2998. else
  2999. {
  3000. unsigned occurrances = 0;
  3001. for (unsigned i = 0; i < exec_paths.size(); i++)
  3002. {
  3003. vector<signed> result;
  3004. Utility::Intersection(footprints, exec_paths[i], result);
  3005. if (result.size() == 1)
  3006. occurrances++;
  3007. }
  3008. if (occurrances == exec_paths.size())
  3009. return false;
  3010. Snapshot *snapshot = flatten.summary[footprints[0]];
  3011. vector<AstExpression*> conjoints;
  3012. map<VariableSymbol*, AstExpression*> constraints;
  3013. flatten.FlattenBoolean(conjoints, snapshot->condition);
  3014. for (unsigned i = 0; i < conjoints.size(); i++)
  3015. {
  3016. // check whether there are other static variables to track
  3017. // but if "instance == null" is in conjoints, then stop checking
  3018. // otherwise, check if these additional variables are
  3019. // 1. modified so that this snapshot will never be entered again, and
  3020. // 2. these vars are not changed anywhere besides snapshot (flow-insensitive)
  3021. // consider BINARY and PRE_UNARY expressions
  3022. if (conjoints[i]->kind == Ast::BINARY)
  3023. {
  3024. AstBinaryExpression *expression = (*&conjoints[i])->BinaryExpressionCast();
  3025. if (expression->left_expression->symbol == variable)
  3026. {
  3027. if ((expression->Tag() == AstBinaryExpression::EQUAL_EQUAL)
  3028. && (expression->right_expression->kind == Ast::NULL_LITERAL))
  3029. return true;
  3030. else
  3031. return false;
  3032. }
  3033. else if (expression->left_expression->symbol->VariableCast())
  3034. {
  3035. VariableSymbol *vsym = expression->left_expression->symbol->VariableCast();
  3036. if (vsym->ACC_PRIVATE()
  3037. && vsym->ACC_STATIC()
  3038. && (strcmp(vsym->Type()->Utf8Name(), "boolean") == 0))
  3039. constraints.insert(pair<VariableSymbol*, AstExpression*>(vsym, expression));
  3040. }
  3041. }
  3042. else if (conjoints[i]->kind == Ast::PRE_UNARY)
  3043. {
  3044. AstPreUnaryExpression *pre_unary = (*&conjoints[i])->PreUnaryExpressionCast();
  3045. if (pre_unary->expression->symbol->VariableCast())
  3046. {
  3047. VariableSymbol *vsym = pre_unary->expression->symbol->VariableCast();
  3048. if (vsym->ACC_PRIVATE()
  3049. && vsym->ACC_STATIC()
  3050. && (strcmp(vsym->Type()->Utf8Name(), "boolean") == 0))
  3051. constraints.insert(pair<VariableSymbol*, AstExpression*>(vsym, pre_unary));
  3052. }
  3053. else if ((pre_unary->Tag() == AstPreUnaryExpression::NOT)
  3054. && (pre_unary->expression->kind == Ast::BINARY)
  3055. && (pre_unary->expression->BinaryExpressionCast()->left_expression->symbol == variable))
  3056. {
  3057. if ((pre_unary->expression->BinaryExpressionCast()->Tag() == AstBinaryExpression::NOT_EQUAL)
  3058. && (pre_unary->expression->BinaryExpressionCast()->right_expression->kind == Ast::NULL_LITERAL))
  3059. return true;
  3060. else
  3061. return false;
  3062. }
  3063. }
  3064. else if (conjoints[i]->symbol->VariableCast())
  3065. {
  3066. VariableSymbol *vsym = conjoints[i]->symbol->VariableCast();
  3067. if (vsym->ACC_PRIVATE()
  3068. && vsym->ACC_STATIC()
  3069. && (strcmp(vsym->Type()->Utf8Name(), "boolean") == 0))
  3070. constraints.insert(pair<VariableSymbol*, AstExpression*>(vsym, conjoints[i]));
  3071. }
  3072. }
  3073. if (constraints.size() == 0)
  3074. return false;
  3075. else
  3076. {
  3077. // analyze statements in snapshot, making sure that these control variables close the entrance to this snapshot
  3078. for (unsigned j = (*snapshot->statements).size() - 1; j < (*snapshot->statements).size(); j--)
  3079. {
  3080. Ast *statement = (*snapshot->statements)[j];
  3081. if (statement->kind == Ast::ASSIGNMENT)
  3082. {
  3083. AstAssignmentExpression *assignment = statement->AssignmentExpressionCast();
  3084. if (assignment->left_hand_side->symbol->VariableCast())
  3085. {
  3086. VariableSymbol *vsym = assignment->left_hand_side->symbol->VariableCast();
  3087. map<VariableSymbol*, AstExpression*>::iterator p = constraints.find(vsym);
  3088. if (p != constraints.end())
  3089. {
  3090. // analyze right_hand_side expression
  3091. if (assignment->expression->kind == Ast::TRUE_LITERAL)
  3092. {
  3093. if (((p->second->kind == Ast::PRE_UNARY)
  3094. && p->second->PreUnaryExpressionCast()->expression->symbol->VariableCast())
  3095. ||((p->second->kind == Ast::BINARY)
  3096. && p->second->BinaryExpressionCast()->left_expression->symbol->VariableCast()
  3097. && (p->second->BinaryExpressionCast()->right_expression->kind == Ast::FALSE_LITERAL)))
  3098. goto Ugly;
  3099. }
  3100. else if (assignment->expression->kind == Ast::FALSE_LITERAL)
  3101. {
  3102. if (p->second->symbol->VariableCast()
  3103. ||((p->second->kind == Ast::BINARY)
  3104. && p->second->BinaryExpressionCast()->left_expression->symbol->VariableCast()
  3105. && (p->second->BinaryExpressionCast()->right_expression->kind == Ast::TRUE_LITERAL)))
  3106. goto Ugly;
  3107. }
  3108. }
  3109. }
  3110. }
  3111. }
  3112. return false;
  3113. // flow-insensitive analysis in summary
  3114. Ugly: SymbolSet modified;
  3115. for (unsigned i =0; i < flatten.summary.size(); i++)
  3116. {
  3117. Snapshot *snapshot = flatten.summary[i];
  3118. if (snapshot->index != footprints[0])
  3119. {
  3120. for (unsigned j = 0; j < (*snapshot->statements).size(); j++)
  3121. {
  3122. Ast *statement = (*snapshot->statements)[j];
  3123. if (statement->kind == Ast::ASSIGNMENT)
  3124. {
  3125. AstAssignmentExpression *assignment = statement->AssignmentExpressionCast();
  3126. if (assignment->left_hand_side->symbol->VariableCast()
  3127. && (constraints.find(assignment->left_hand_side->symbol->VariableCast()) != constraints.end()))
  3128. modified.AddElement(assignment->left_hand_side->symbol->VariableCast());
  3129. // skip analysis on the right_hand_side expression
  3130. }
  3131. }
  3132. }
  3133. }
  3134. return (modified.Size() < constraints.size());
  3135. }
  3136. }
  3137. }
  3138. void SingletonAnalysis::TracePath(Snapshot* snapshot)
  3139. {
  3140. set<signed> next(snapshot->previous);
  3141. for (unsigned j = snapshot->statements->size() - 1; j < snapshot->statements->size(); j--)
  3142. {
  3143. Ast *statement = (*snapshot->statements)[j];
  3144. if (statement->kind == Ast::RETURN)
  3145. {
  3146. AstReturnStatement *return_statement = statement->ReturnStatementCast();
  3147. if (return_statement->expression_opt)
  3148. {
  3149. AstExpression *expression = Utility::RemoveCasting(return_statement->expression_opt);
  3150. if (expression->symbol->VariableCast()
  3151. && (expression->symbol->VariableCast() == variable))
  3152. {
  3153. fingerprints.push_back(snapshot->index);
  3154. }
  3155. }
  3156. }
  3157. else if (statement->kind == Ast::ASSIGNMENT)
  3158. {
  3159. AstAssignmentExpression *assignment = statement->AssignmentExpressionCast();
  3160. if (assignment->left_hand_side->symbol->VariableCast()
  3161. && (assignment->left_hand_side->symbol == variable))
  3162. {
  3163. AstExpression *expression = Utility::RemoveCasting(assignment->expression);
  3164. if (expression->kind == Ast::CLASS_CREATION)
  3165. {
  3166. for (unsigned i = 0; i < expression->ClassCreationExpressionCast()->arguments->NumArguments(); i++)
  3167. if (expression->ClassCreationExpressionCast()->arguments->Argument(i)->symbol == variable)
  3168. goto pass;
  3169. // check if this class creation negates the dominator condition
  3170. footprints.push_back(snapshot->index);
  3171. pass: ;
  3172. }
  3173. else if (expression->kind == Ast::CALL)
  3174. {
  3175. // Check: are we currnetly under the scope where condition says instance == null?
  3176. // How to check a segment of code is only executed once, regardless of flag?
  3177. AstMethodInvocation *call = expression->MethodInvocationCast();
  3178. if ((strcmp(call->symbol->MethodCast()->Utf8Name(), "newInstance") == 0)
  3179. && (((call->base_opt->kind == Ast::NAME) && (strcmp(call->base_opt->symbol->VariableCast()->Type()->Utf8Name(), "Class") == 0))
  3180. || ((call->base_opt->kind == Ast::CALL)
  3181. && (strcmp(call->base_opt->symbol->MethodCast()->Utf8Name(), "forName") == 0)
  3182. && (call->base_opt->MethodInvocationCast()->base_opt ->kind== Ast::NAME)
  3183. && (strcmp(call->base_opt->MethodInvocationCast()->base_opt->symbol->TypeCast()->Utf8Name(), "Class") == 0)))
  3184. )
  3185. {
  3186. footprints.push_back(snapshot->index);
  3187. }
  3188. else
  3189. {
  3190. FactoryAnalysis factory(call->symbol->MethodCast(), ast_pool);
  3191. if (factory.IsCreationMethod())
  3192. {
  3193. footprints.push_back(snapshot->index);
  3194. }
  3195. }
  3196. }
  3197. }
  3198. }
  3199. }
  3200. set<signed>::iterator p;
  3201. for (p = next.begin(); p != next.end(); p++)
  3202. {
  3203. if (*p >= 0)
  3204. {
  3205. path.push_back(*p);
  3206. TracePath(flatten.summary[*p]);
  3207. path.pop_back();
  3208. }
  3209. else
  3210. {
  3211. //paths.push_back('E');
  3212. exec_paths.push_back(path);
  3213. }
  3214. }
  3215. }
  3216. bool SingletonAnalysis::ReturnsSingleton1()
  3217. {
  3218. #ifdef DONT_BOTHER
  3219. visited.AddElement(method);
  3220. method->declaration->MethodDeclarationCast()->method_body_opt->Accept(flatten);
  3221. // TODO: The following should be included in Flatten.
  3222. for(unsigned i = 0; i < flatten.summary.size(); i++)
  3223. {
  3224. set<signed>::iterator p;
  3225. for (p = (flatten.summary[i]->next).begin(); p != (flatten.summary[i]->next).end(); p++)
  3226. (flatten.summary[*p]->previous).insert(i);
  3227. }
  3228. flatten.DumpSummary();
  3229. for (unsigned t = 0; t < flatten.traces.size(); t++)
  3230. {
  3231. Snapshot *return_snapshot = NULL;
  3232. int return_path = -1;
  3233. vector<unsigned> snapshots;
  3234. snapshots.push_back(flatten.traces[t]->index);
  3235. while(!snapshots.empty())
  3236. //for (unsigned i = flatten.traces[t]->index; i < flatten.summary.size(); i--)
  3237. {
  3238. Snapshot *snapshot = flatten.summary[snapshots[snapshots.size() - 1]];
  3239. snapshots.pop_back();
  3240. /*
  3241. if ((i == flatten.traces[t]->index)
  3242. || ((i < flatten.traces[t]->index)
  3243. && (flatten.TransitionFlow(snapshot->condition, flatten.summary[i + 1]->condition) != Flatten::NOTRANSITION)))
  3244. {
  3245. */
  3246. for (unsigned j = snapshot->statements->size() - 1; j < snapshot->statements->size(); j--)
  3247. {
  3248. Ast *statement = (*snapshot->statements)[j];
  3249. if (statement->kind == Ast::RETURN)
  3250. {
  3251. AstReturnStatement *return_statement = statement->ReturnStatementCast();
  3252. if (return_statement->expression_opt)
  3253. {
  3254. AstExpression *expression = Utility::RemoveCasting(return_statement->expression_opt);
  3255. if (expression->kind == Ast::NULL_LITERAL)
  3256. goto stop_trace;
  3257. else if (expression->symbol->VariableCast()
  3258. && (expression->symbol->VariableCast() == variable))
  3259. {
  3260. return_snapshot = snapshot;
  3261. return_path = paths.size();
  3262. paths.push_back('E');
  3263. }
  3264. else
  3265. return false;
  3266. }
  3267. }
  3268. else if (return_snapshot && (statement->kind == Ast::ASSIGNMENT))
  3269. {
  3270. AstAssignmentExpression *assignment = statement->AssignmentExpressionCast();
  3271. if (assignment->left_hand_side->symbol->VariableCast()
  3272. && (assignment->left_hand_side->symbol == variable))
  3273. {
  3274. AstExpression *expression = Utility::RemoveCasting(assignment->expression);
  3275. if (expression->kind == Ast::CLASS_CREATION)
  3276. {
  3277. // check if this class creation negates the dominator condition
  3278. vector<AstExpression*> conjoints;
  3279. flatten.FlattenBoolean(conjoints, snapshot->condition);
  3280. for (unsigned i = 0; i < conjoints.size(); i++)
  3281. {
  3282. if ((conjoints[i]->kind == Ast::BINARY)
  3283. && ((*&conjoints[i])->BinaryExpressionCast()->Tag() == AstBinaryExpression::EQUAL_EQUAL)
  3284. && ((*&conjoints[i])->BinaryExpressionCast()->left_expression->symbol == variable)
  3285. && ((*&conjoints[i])->BinaryExpressionCast()->right_expression->kind == Ast::NULL_LITERAL))
  3286. {
  3287. paths[return_path] = 'N';
  3288. goto stop_trace;
  3289. }
  3290. }
  3291. }
  3292. else if (expression->kind == Ast::CALL)
  3293. {
  3294. AstMethodInvocation *call = expression->MethodInvocationCast();
  3295. if ((strcmp(call->symbol->MethodCast()->Utf8Name(), "newInstance") == 0)
  3296. //&& (call->base_opt->kind == Ast::CALL)
  3297. && (strcmp(call->base_opt->symbol->MethodCast()->Utf8Name(), "forName") == 0)
  3298. //&& (call->base_opt->MethodInvocationCast()->base_opt ->kind== Ast::NAME)
  3299. && (strcmp(call->base_opt->MethodInvocationCast()->base_opt->symbol->TypeCast()->Utf8Name(), "Class") == 0))
  3300. {
  3301. paths[return_path] = 'N';
  3302. goto stop_trace;
  3303. }
  3304. }
  3305. else if (expression->kind == Ast::NULL_LITERAL)
  3306. {
  3307. paths[return_path] = 'X';
  3308. goto stop_trace;
  3309. }
  3310. }
  3311. }
  3312. }
  3313. /*
  3314. }
  3315. */
  3316. // check if it's possible to go to the previous snapshot.
  3317. set<signed>::iterator p;
  3318. for(p = (snapshot->previous).begin(); p != (snapshot->previous).end(); p++)
  3319. snapshots.push_back(*p);
  3320. }
  3321. stop_trace: return_snapshot = NULL;
  3322. return_path = -1;
  3323. }
  3324. int nc = 0, ne = 0;
  3325. for (unsigned i = 0; i < paths.size(); i++)
  3326. {
  3327. if (paths[i] == 'N')
  3328. nc++;
  3329. else if (paths[i] == 'E')
  3330. ne++;
  3331. }
  3332. if ((nc==1) && (ne == 1))
  3333. return true;
  3334. else if ((ne == 1)
  3335. && variable->declarator->variable_initializer_opt
  3336. && (variable->declarator->variable_initializer_opt->kind == Ast::CLASS_CREATION))
  3337. return true;
  3338. else
  3339. return false;
  3340. #endif
  3341. return false;
  3342. }
  3343. SymbolSet FactoryAnalysis::visited;
  3344. SymbolSet FactoryAnalysis::types;
  3345. bool FactoryAnalysis::IsFactoryMethod()
  3346. {
  3347. //Coutput << "Analyzing " << method->Utf8Name() << endl;
  3348. visited.AddElement(method);
  3349. method->declaration->MethodDeclarationCast()->method_body_opt->Accept(flatten);
  3350. //flatten.DumpSummary();
  3351. for (unsigned t = 0; t < flatten.traces.size(); t++)
  3352. {
  3353. VariableSymbol *returned_var = NULL;
  3354. for (unsigned i = flatten.traces[t]->index; i < flatten.summary.size(); i--)
  3355. {
  3356. Snapshot *snapshot = flatten.summary[i];
  3357. for (unsigned j = snapshot->statements->size() - 1; j < snapshot->statements->size(); j--)
  3358. {
  3359. Ast *stmt = (*snapshot->statements)[j];
  3360. if (stmt->kind == Ast::RETURN)
  3361. {
  3362. AstReturnStatement *return_stmt = stmt->ReturnStatementCast();
  3363. if (return_stmt->expression_opt)
  3364. {
  3365. AstExpression *expression = Utility::RemoveCasting(return_stmt->expression_opt);
  3366. if (expression->symbol->VariableCast())
  3367. returned_var = expression->symbol->VariableCast();
  3368. else if (expression->symbol->MethodCast())
  3369. {
  3370. if (expression->kind == Ast::CLASS_CREATION)
  3371. {
  3372. types.AddElement(expression->symbol->MethodCast()->Type());
  3373. break;
  3374. }
  3375. else if (expression->kind == Ast::CALL)
  3376. {
  3377. // inter-procedural
  3378. if (!visited.IsElement(expression->symbol)
  3379. && expression->symbol->MethodCast()->declaration
  3380. && expression->symbol->MethodCast()->declaration->MethodDeclarationCast()
  3381. && expression->symbol->MethodCast()->declaration->MethodDeclarationCast()->method_body_opt)
  3382. {
  3383. FactoryAnalysis defer(expression->symbol->MethodCast(), ast_pool);
  3384. if (defer.IsFactoryMethod())
  3385. break;
  3386. }
  3387. }
  3388. }
  3389. // Jikes does not compile when returning empty_statement
  3390. else if (expression->symbol->TypeCast())
  3391. {
  3392. if (expression->kind == Ast::NULL_LITERAL)
  3393. return false;
  3394. }
  3395. }
  3396. }
  3397. else if (stmt->kind == Ast::ASSIGNMENT)
  3398. {
  3399. AstAssignmentExpression *assignment = stmt->AssignmentExpressionCast();
  3400. if (assignment->left_hand_side->symbol->VariableCast()
  3401. && (assignment->left_hand_side->symbol == returned_var))
  3402. {
  3403. AstExpression *expression = Utility::RemoveCasting(assignment->expression);
  3404. if (expression->kind == Ast::CLASS_CREATION)
  3405. {
  3406. //types.AddElement(expression->symbol->MethodCast()->Type());
  3407. types.AddElement(expression->ClassCreationExpressionCast()->class_type->symbol->TypeCast());
  3408. break;
  3409. }
  3410. else if (expression->kind == Ast::NULL_LITERAL)
  3411. return false;
  3412. else if (expression->kind == Ast::CALL)
  3413. {
  3414. // inter-procedural
  3415. if (!visited.IsElement(expression->symbol)
  3416. && expression->symbol->MethodCast()->declaration
  3417. && expression->symbol->MethodCast()->declaration->MethodDeclarationCast()
  3418. && expression->symbol->MethodCast()->declaration->MethodDeclarationCast()->method_body_opt)
  3419. {
  3420. FactoryAnalysis defer(expression->symbol->MethodCast(), ast_pool);
  3421. if (defer.IsFactoryMethod())
  3422. break;
  3423. }
  3424. }
  3425. else if (expression->symbol->VariableCast())
  3426. {
  3427. // aliasing
  3428. returned_var = expression->symbol->VariableCast();
  3429. }
  3430. }
  3431. }
  3432. else if (stmt->kind == Ast::VARIABLE_DECLARATOR)
  3433. {
  3434. AstVariableDeclarator *var_declarator = stmt->VariableDeclaratorCast();
  3435. if (var_declarator->symbol == returned_var)
  3436. {
  3437. if (var_declarator->variable_initializer_opt
  3438. && var_declarator->variable_initializer_opt->ExpressionCast())
  3439. {
  3440. AstExpression *expression = Utility::RemoveCasting(var_declarator->variable_initializer_opt->ExpressionCast());
  3441. if (expression->kind == Ast::CLASS_CREATION)
  3442. {
  3443. //types.AddElement(expression->symbol->MethodCast()->Type());
  3444. types.AddElement(expression->ClassCreationExpressionCast()->class_type->symbol->TypeCast());
  3445. break;
  3446. }
  3447. else if (expression->kind == Ast::NULL_LITERAL)
  3448. return false;
  3449. else if (expression->kind == Ast::CALL)
  3450. {
  3451. // inter-procedural
  3452. if (!visited.IsElement(expression->symbol)
  3453. && expression->symbol->MethodCast()->declaration
  3454. && expression->symbol->MethodCast()->declaration->MethodDeclarationCast()
  3455. && expression->symbol->MethodCast()->declaration->MethodDeclarationCast()->method_body_opt)
  3456. {
  3457. FactoryAnalysis defer(expression->symbol->MethodCast(), ast_pool);
  3458. if (defer.IsFactoryMethod())
  3459. break;
  3460. }
  3461. }
  3462. else if (expression->symbol->VariableCast())
  3463. {
  3464. // aliasing
  3465. returned_var = expression->symbol->VariableCast();
  3466. }
  3467. }
  3468. // variable unitialized and never assigned with a value is a Jikes error
  3469. else if (!var_declarator->variable_initializer_opt)
  3470. return false;
  3471. }
  3472. }
  3473. }
  3474. }
  3475. }
  3476. return (types.Size() && !types.IsElement(method->Type()));
  3477. }
  3478. bool FactoryAnalysis::IsCreationMethod()
  3479. {
  3480. //Coutput << "Analyzing " << method->Utf8Name() << endl;
  3481. visited.AddElement(method);
  3482. method->declaration->MethodDeclarationCast()->method_body_opt->Accept(flatten);
  3483. //flatten.DumpSummary();
  3484. for (unsigned t = 0; t < flatten.traces.size(); t++)
  3485. {
  3486. VariableSymbol *returned_var = NULL;
  3487. for (unsigned i = flatten.traces[t]->index; i < flatten.summary.size(); i--)
  3488. {
  3489. Snapshot *snapshot = flatten.summary[i];
  3490. for (unsigned j = snapshot->statements->size() - 1; j < snapshot->statements->size(); j--)
  3491. {
  3492. Ast *stmt = (*snapshot->statements)[j];
  3493. if (stmt->kind == Ast::RETURN)
  3494. {
  3495. AstReturnStatement *return_stmt = stmt->ReturnStatementCast();
  3496. if (return_stmt->expression_opt)
  3497. {
  3498. AstExpression *expression = Utility::RemoveCasting(return_stmt->expression_opt);
  3499. if (expression->symbol->VariableCast())
  3500. returned_var = expression->symbol->VariableCast();
  3501. else if (expression->symbol->MethodCast())
  3502. {
  3503. if (expression->kind == Ast::CLASS_CREATION)
  3504. {
  3505. types.AddElement(expression->symbol->MethodCast()->Type());
  3506. break;
  3507. }
  3508. else if (expression->kind == Ast::CALL)
  3509. {
  3510. // inter-procedural
  3511. if (!visited.IsElement(expression->symbol)
  3512. && expression->symbol->MethodCast()->declaration
  3513. && expression->symbol->MethodCast()->declaration->MethodDeclarationCast()
  3514. && expression->symbol->MethodCast()->declaration->MethodDeclarationCast()->method_body_opt)
  3515. {
  3516. FactoryAnalysis defer(expression->symbol->MethodCast(), ast_pool);
  3517. if (defer.IsCreationMethod())
  3518. break;
  3519. }
  3520. }
  3521. }
  3522. // Jikes does not compile when returning empty_statement
  3523. else if (expression->symbol->TypeCast())
  3524. {
  3525. if (expression->kind == Ast::NULL_LITERAL)
  3526. return false;
  3527. }
  3528. }
  3529. }
  3530. else if (stmt->kind == Ast::ASSIGNMENT)
  3531. {
  3532. AstAssignmentExpression *assignment = stmt->AssignmentExpressionCast();
  3533. if (assignment->left_hand_side->symbol->VariableCast()
  3534. && (assignment->left_hand_side->symbol == returned_var))
  3535. {
  3536. AstExpression *expression = Utility::RemoveCasting(assignment->expression);
  3537. if (expression->kind == Ast::CLASS_CREATION)
  3538. {
  3539. types.AddElement(expression->symbol->MethodCast()->Type());
  3540. break;
  3541. }
  3542. else if (expression->kind == Ast::NULL_LITERAL)
  3543. return false;
  3544. else if (expression->kind == Ast::CALL)
  3545. {
  3546. // inter-procedural
  3547. if (!visited.IsElement(expression->symbol)
  3548. && expression->symbol->MethodCast()->declaration
  3549. && expression->symbol->MethodCast()->declaration->MethodDeclarationCast()
  3550. && expression->symbol->MethodCast()->declaration->MethodDeclarationCast()->method_body_opt)
  3551. {
  3552. FactoryAnalysis defer(expression->symbol->MethodCast(), ast_pool);
  3553. if (defer.IsCreationMethod())
  3554. break;
  3555. }
  3556. }
  3557. else if (expression->symbol->VariableCast())
  3558. {
  3559. // aliasing
  3560. returned_var = expression->symbol->VariableCast();
  3561. }
  3562. }
  3563. }
  3564. else if (stmt->kind == Ast::VARIABLE_DECLARATOR)
  3565. {
  3566. AstVariableDeclarator *var_declarator = stmt->VariableDeclaratorCast();
  3567. if (var_declarator->symbol == returned_var)
  3568. {
  3569. if (var_declarator->variable_initializer_opt
  3570. && var_declarator->variable_initializer_opt->ExpressionCast())
  3571. {
  3572. AstExpression *expression = var_declarator->variable_initializer_opt->ExpressionCast();
  3573. if (expression->kind == Ast::CLASS_CREATION)
  3574. {
  3575. types.AddElement(expression->symbol->MethodCast()->Type());
  3576. break;
  3577. }
  3578. else if (expression->kind == Ast::NULL_LITERAL)
  3579. return false;
  3580. else if (expression->kind == Ast::CALL)
  3581. {
  3582. // inter-procedural
  3583. if (!visited.IsElement(expression->symbol)
  3584. && expression->symbol->MethodCast()->declaration
  3585. && expression->symbol->MethodCast()->declaration->MethodDeclarationCast()
  3586. && expression->symbol->MethodCast()->declaration->MethodDeclarationCast()->method_body_opt)
  3587. {
  3588. FactoryAnalysis defer(expression->symbol->MethodCast(), ast_pool);
  3589. if (defer.IsCreationMethod())
  3590. break;
  3591. }
  3592. }
  3593. else if (expression->symbol->VariableCast())
  3594. {
  3595. // aliasing
  3596. returned_var = expression->symbol->VariableCast();
  3597. }
  3598. }
  3599. // variable unitialized and never assigned with a value is a Jikes error
  3600. else if (!var_declarator->variable_initializer_opt)
  3601. return false;
  3602. }
  3603. }
  3604. }
  3605. }
  3606. }
  3607. return ((types.Size() == 1) && types.IsElement(method->Type()));
  3608. }
  3609. void EmitExpressionAssociation(TypeSymbol * unit_type, MethodSymbol * enclosing_method, AstExpression * expression, DelegationTable * d_table, WriteAccessTable * w_table);
  3610. void EmitStatementAssociation(TypeSymbol * unit_type, MethodSymbol * enclosing_method, AstStatement * statement, DelegationTable * d_table, WriteAccessTable * w_table, ReadAccessTable *r_table);
  3611. void EmitGeneralization(GenTable * gen_table, TypeSymbol * unit_type)
  3612. {
  3613. //AstClassBody* class_body = unit_type -> declaration;
  3614. wchar_t* package_name = unit_type -> FileLoc();
  3615. wchar_t* class_name = const_cast<wchar_t*>(unit_type -> Name());
  3616. wchar_t* super_name = const_cast<wchar_t*>(unit_type -> super -> Name());
  3617. vector<wchar_t*>* interfaces = NULL;
  3618. for (unsigned k = 0; k < unit_type -> NumInterfaces(); k++)
  3619. {
  3620. if (interfaces == NULL)
  3621. interfaces = new vector<wchar_t*>();
  3622. interfaces -> push_back(const_cast<wchar_t*>(unit_type -> Interface(k) -> Name()));
  3623. }
  3624. Gen::Kind kind;
  3625. if (unit_type -> ACC_INTERFACE())
  3626. kind = Gen::INTERFACE;
  3627. else if (unit_type -> ACC_FINAL())
  3628. kind = Gen::FINAL;
  3629. else if (unit_type -> ACC_ABSTRACT())
  3630. kind = Gen::ABSTRACT;
  3631. else
  3632. kind = Gen::CLASS;
  3633. gen_table -> addGeneralization(package_name, class_name, super_name, interfaces, kind, const_cast<char*>(unit_type -> SignatureString()));
  3634. }
  3635. void EmitBlockAssociation(TypeSymbol * unit_type, MethodSymbol * enclosing_method, AstBlock * block, DelegationTable * d_table, WriteAccessTable * w_table, ReadAccessTable *r_table)
  3636. {
  3637. for (unsigned i = 0; i < block -> NumStatements(); i++)
  3638. EmitStatementAssociation(unit_type, enclosing_method, block -> Statement(i), d_table, w_table, r_table);
  3639. }
  3640. void EmitDelegation(TypeSymbol * unit_type, MethodSymbol * enclosing_method, AstMethodInvocation * expression, DelegationTable * d_table, WriteAccessTable * w_table)
  3641. {
  3642. //
  3643. // If the method call was resolved into a call to another method, use the
  3644. // resolution expression.
  3645. //
  3646. AstMethodInvocation* method_call = expression -> resolution_opt
  3647. ? expression -> resolution_opt -> MethodInvocationCast() : expression;
  3648. assert(method_call);
  3649. MethodSymbol *msym = (MethodSymbol*) method_call -> symbol;
  3650. VariableSymbol *vsym = (method_call -> base_opt
  3651. && method_call -> base_opt -> kind == Ast::NAME
  3652. && (method_call -> base_opt -> symbol -> Kind() == Symbol::VARIABLE))
  3653. ? method_call -> base_opt -> symbol -> VariableCast()
  3654. : NULL;
  3655. d_table -> InsertDelegation(unit_type, msym -> containing_type, method_call -> base_opt, vsym, msym, enclosing_method, method_call);
  3656. if (!msym -> containing_type -> call_dependents)
  3657. msym -> containing_type -> call_dependents = new SymbolSet(0);
  3658. msym -> containing_type -> call_dependents -> AddElement(unit_type);
  3659. if (!msym -> callers)
  3660. msym -> callers = new SymbolSet(0);
  3661. msym -> callers -> AddElement(unit_type);
  3662. if (!msym -> invokers)
  3663. msym -> invokers = new SymbolSet(0);
  3664. msym -> invokers -> AddElement(enclosing_method);
  3665. if (!enclosing_method -> invokees)
  3666. enclosing_method -> invokees = new SymbolSet(0);
  3667. enclosing_method -> invokees -> AddElement(msym);
  3668. if (!unit_type -> associates)
  3669. unit_type -> associates = new SymbolSet(0);
  3670. unit_type -> associates -> AddElement(msym -> containing_type);
  3671. if (method_call -> base_opt)
  3672. EmitExpressionAssociation(unit_type, enclosing_method, method_call -> base_opt, d_table, w_table);
  3673. AstArguments *args = expression -> arguments;
  3674. for (unsigned i = 0; i < args -> NumArguments(); i++)
  3675. {
  3676. if (args->Argument(i)->symbol->VariableCast())
  3677. {
  3678. if (!msym->FormalParameter(i)->aliases)
  3679. msym->FormalParameter(i)->aliases = new SymbolSet();
  3680. msym->FormalParameter(i)->aliases->AddElement(args->Argument(i)->symbol->VariableCast());
  3681. }
  3682. EmitExpressionAssociation(unit_type, enclosing_method, args -> Argument(i), d_table, w_table);
  3683. }
  3684. }
  3685. void EmitReadAccess(TypeSymbol * unit_type, MethodSymbol * enclosing_method, AstName * name, ReadAccessTable * r_table)
  3686. {
  3687. if (name -> symbol -> Kind() == Symbol::VARIABLE)
  3688. {
  3689. VariableSymbol *vsym = name -> symbol -> VariableCast();
  3690. if (vsym -> IsLocal())
  3691. vsym = unit_type -> Shadows(vsym);
  3692. if (vsym)
  3693. r_table -> InsertReadAccess(vsym, enclosing_method);
  3694. }
  3695. }
  3696. void EmitWriteAccess(TypeSymbol * unit_type, MethodSymbol * enclosing_method, AstAssignmentExpression * assignment, DelegationTable * d_table, WriteAccessTable * w_table)
  3697. {
  3698. AstExpression *left_expression = assignment->left_hand_side;
  3699. VariableSymbol *vsym = NULL;
  3700. if (left_expression->kind == Ast::DOT)
  3701. vsym = left_expression->FieldAccessCast()->symbol->VariableCast();
  3702. else if ((left_expression -> kind == Ast::NAME) && (left_expression->symbol->Kind()==Symbol::VARIABLE))
  3703. {
  3704. /*
  3705. left_expression = (left_expression->NameCast()->resolution_opt)
  3706. ? left_expression->NameCast()->resolution_opt
  3707. : left_expression;
  3708. */
  3709. vsym = left_expression -> symbol -> VariableCast();
  3710. }
  3711. #ifdef GOF_CONSOLE
  3712. if (vsym -> ContainingType() == unit_type)
  3713. Coutput << vsym -> ContainingType() -> Utf8Name()
  3714. << "::"
  3715. << enclosing_method -> Utf8Name()
  3716. << " accesses a private field "
  3717. << vsym -> Utf8Name()
  3718. << ": "
  3719. << vsym -> Type () -> Utf8Name()
  3720. << endl;
  3721. #endif
  3722. if (vsym)
  3723. {
  3724. w_table -> InsertWriteAccess(vsym, enclosing_method);
  3725. /*
  3726. AstExpression *rhs_expression = (assignment-> expression -> kind == Ast::CAST)
  3727. ? assignment-> expression -> CastExpressionCast() -> expression
  3728. : assignment-> expression;
  3729. */
  3730. AstExpression *rhs_expression = Utility::RemoveCasting(assignment-> expression);
  3731. if (vsym && rhs_expression -> kind == Ast::CLASS_CREATION)
  3732. {
  3733. if (!vsym -> concrete_types)
  3734. vsym -> concrete_types = new SymbolSet(0);
  3735. vsym -> concrete_types -> AddElement(rhs_expression -> ClassCreationExpressionCast() -> class_type -> symbol -> TypeCast());
  3736. }
  3737. if (rhs_expression->symbol->VariableCast())
  3738. {
  3739. if (!vsym->aliases)
  3740. vsym->aliases = new SymbolSet();
  3741. vsym->aliases->AddElement(rhs_expression->symbol->VariableCast());
  3742. }
  3743. }
  3744. EmitExpressionAssociation(unit_type, enclosing_method, assignment-> expression, d_table, w_table);
  3745. }
  3746. void EmitExpressionAssociation(TypeSymbol * unit_type, MethodSymbol * enclosing_method, AstExpression * expression, DelegationTable * d_table, WriteAccessTable * w_table)
  3747. {
  3748. switch(expression -> kind)
  3749. {
  3750. case Ast::CLASS_CREATION:
  3751. if (!unit_type -> associates)
  3752. unit_type -> associates = new SymbolSet(0);
  3753. if (expression->ClassCreationExpressionCast()->class_type->symbol)
  3754. unit_type -> associates -> AddElement(((AstClassCreationExpression*)expression) -> class_type -> symbol -> TypeCast());
  3755. else
  3756. unit_type->associates->AddElement(expression->ClassCreationExpressionCast()->symbol->MethodCast()->containing_type);
  3757. break;
  3758. case Ast::CALL:
  3759. EmitDelegation(unit_type, enclosing_method, (AstMethodInvocation*)expression, d_table, w_table);
  3760. break;
  3761. case Ast::ASSIGNMENT:
  3762. EmitWriteAccess(unit_type, enclosing_method, (AstAssignmentExpression*)expression, d_table, w_table);
  3763. EmitExpressionAssociation(unit_type, enclosing_method, ((AstAssignmentExpression*)expression) -> expression, d_table, w_table);
  3764. break;
  3765. case Ast::CONDITIONAL:
  3766. EmitExpressionAssociation(unit_type, enclosing_method, ((AstConditionalExpression*)expression) -> test_expression, d_table, w_table);
  3767. EmitExpressionAssociation(unit_type, enclosing_method, ((AstConditionalExpression*)expression) -> true_expression, d_table, w_table);
  3768. EmitExpressionAssociation(unit_type, enclosing_method, ((AstConditionalExpression*)expression )-> false_expression, d_table, w_table);
  3769. break;
  3770. case Ast::CAST:
  3771. EmitExpressionAssociation(unit_type, enclosing_method, ((AstCastExpression*)expression )-> expression, d_table, w_table);
  3772. break;
  3773. case Ast::PARENTHESIZED_EXPRESSION:
  3774. EmitExpressionAssociation(unit_type, enclosing_method, ((AstParenthesizedExpression*)expression )-> expression, d_table, w_table);
  3775. break;
  3776. case Ast::BINARY:
  3777. EmitExpressionAssociation(unit_type, enclosing_method, ((AstBinaryExpression*)expression )-> left_expression, d_table, w_table);
  3778. EmitExpressionAssociation(unit_type, enclosing_method, ((AstBinaryExpression*)expression )-> right_expression, d_table, w_table);
  3779. break;
  3780. default:
  3781. break;
  3782. }
  3783. }
  3784. void EmitStatementAssociation(TypeSymbol * unit_type, MethodSymbol * enclosing_method, AstStatement * statement, DelegationTable * d_table, WriteAccessTable * w_table, ReadAccessTable *r_table)
  3785. {
  3786. switch (statement -> kind)
  3787. {
  3788. case Ast::METHOD_BODY:
  3789. case Ast::BLOCK: // JLS 14.2
  3790. {
  3791. EmitBlockAssociation(unit_type, enclosing_method, (AstBlock*) statement, d_table, w_table, r_table);
  3792. }
  3793. break;
  3794. case Ast::LOCAL_VARIABLE_DECLARATION: // JLS 14.3
  3795. {
  3796. AstLocalVariableStatement *local = (AstLocalVariableStatement *)statement;
  3797. for (unsigned i = 0; i < local -> NumVariableDeclarators(); i++)
  3798. EmitStatementAssociation(unit_type, enclosing_method, local -> VariableDeclarator(i), d_table, w_table, r_table);
  3799. }
  3800. break;
  3801. case Ast::EMPTY_STATEMENT: // JLS 14.5
  3802. break;
  3803. case Ast::EXPRESSION_STATEMENT: // JLS 14.7
  3804. {
  3805. EmitExpressionAssociation(unit_type, enclosing_method, statement -> ExpressionStatementCast() -> expression, d_table, w_table);
  3806. }
  3807. break;
  3808. case Ast::IF: // JLS 14.8
  3809. {
  3810. AstIfStatement* if_statement = (AstIfStatement*) statement;
  3811. EmitExpressionAssociation(unit_type, enclosing_method, if_statement -> expression, d_table, w_table);
  3812. EmitBlockAssociation(unit_type, enclosing_method, if_statement -> true_statement, d_table, w_table, r_table);
  3813. if (if_statement -> false_statement_opt)
  3814. EmitBlockAssociation(unit_type, enclosing_method, if_statement -> false_statement_opt, d_table, w_table, r_table);
  3815. }
  3816. break;
  3817. case Ast::SWITCH: // JLS 14.9
  3818. {
  3819. AstSwitchStatement *cp = statement -> SwitchStatementCast();
  3820. EmitExpressionAssociation(unit_type, enclosing_method, cp -> expression, d_table, w_table);
  3821. EmitBlockAssociation(unit_type, enclosing_method, cp-> switch_block, d_table, w_table, r_table);
  3822. }
  3823. break;
  3824. case Ast::SWITCH_BLOCK: // JLS 14.9
  3825. {
  3826. EmitBlockAssociation(unit_type, enclosing_method, statement -> BlockCast(), d_table, w_table, r_table);
  3827. }
  3828. break;
  3829. case Ast::SWITCH_LABEL:
  3830. break;
  3831. case Ast::WHILE: // JLS 14.10
  3832. {
  3833. AstWhileStatement* wp = statement -> WhileStatementCast();
  3834. EmitExpressionAssociation(unit_type, enclosing_method, wp -> expression, d_table, w_table);
  3835. EmitBlockAssociation(unit_type, enclosing_method, wp -> statement, d_table, w_table, r_table);
  3836. }
  3837. break;
  3838. case Ast::DO: // JLS 14.11
  3839. {
  3840. AstDoStatement* sp = statement -> DoStatementCast();
  3841. EmitExpressionAssociation(unit_type, enclosing_method, sp -> expression, d_table, w_table);
  3842. EmitBlockAssociation(unit_type, enclosing_method, sp -> statement, d_table, w_table, r_table);
  3843. }
  3844. break;
  3845. case Ast::FOR: // JLS 14.12
  3846. {
  3847. AstForStatement* for_statement = statement -> ForStatementCast();
  3848. if (for_statement -> end_expression_opt)
  3849. EmitExpressionAssociation(unit_type, enclosing_method, for_statement -> end_expression_opt, d_table, w_table);
  3850. unsigned i;
  3851. for (i = 0; i < for_statement -> NumForInitStatements(); i++)
  3852. EmitStatementAssociation(unit_type, enclosing_method, for_statement -> ForInitStatement(i), d_table, w_table, r_table);
  3853. for (i = 0; i < for_statement -> NumForUpdateStatements(); i++)
  3854. EmitStatementAssociation(unit_type, enclosing_method, for_statement -> ForUpdateStatement(i), d_table, w_table, r_table);
  3855. EmitBlockAssociation(unit_type, enclosing_method, for_statement -> statement, d_table, w_table, r_table);
  3856. }
  3857. break;
  3858. case Ast::FOREACH: // JSR 201
  3859. case Ast::BREAK: // JLS 14.13
  3860. case Ast::CONTINUE: // JLS 14.14
  3861. break;
  3862. case Ast::RETURN: // JLS 14.15
  3863. {
  3864. AstReturnStatement *rp = statement -> ReturnStatementCast();
  3865. if (rp -> expression_opt)
  3866. {
  3867. if (rp -> expression_opt -> kind == Ast::NAME)
  3868. EmitReadAccess(unit_type, enclosing_method, rp -> expression_opt -> NameCast(), r_table);
  3869. else
  3870. EmitExpressionAssociation(unit_type, enclosing_method, rp -> expression_opt, d_table, w_table);
  3871. }
  3872. }
  3873. break;
  3874. case Ast::SUPER_CALL:
  3875. case Ast::THIS_CALL:
  3876. case Ast::THROW: // JLS 14.16
  3877. break;
  3878. case Ast::SYNCHRONIZED_STATEMENT: // JLS 14.17
  3879. {
  3880. EmitBlockAssociation(unit_type, enclosing_method, statement -> SynchronizedStatementCast() -> block, d_table, w_table, r_table);
  3881. }
  3882. break;
  3883. case Ast::TRY: // JLS 14.18
  3884. {
  3885. EmitBlockAssociation(unit_type, enclosing_method, statement -> TryStatementCast() -> block, d_table, w_table, r_table);
  3886. }
  3887. break;
  3888. case Ast::CATCH: // JLS 14.18
  3889. case Ast::FINALLY: // JLS 14.18
  3890. case Ast::ASSERT: // JDK 1.4 (JSR 41)
  3891. case Ast::LOCAL_CLASS: // Class Declaration
  3892. //
  3893. // This is factored out by the front end; and so must be
  3894. // skipped here (remember, interfaces cannot be declared locally).
  3895. //
  3896. break;
  3897. case Ast::VARIABLE_DECLARATOR:
  3898. {
  3899. AstVariableDeclarator *vd = statement -> VariableDeclaratorCast();
  3900. if (vd -> variable_initializer_opt && vd -> variable_initializer_opt -> ExpressionCast())
  3901. {
  3902. AstExpression *rhs_expression = Utility::RemoveCasting(vd->variable_initializer_opt->ExpressionCast());
  3903. if (rhs_expression->symbol->VariableCast())
  3904. {
  3905. if (!vd->symbol->aliases)
  3906. vd->symbol->aliases = new SymbolSet();
  3907. vd->symbol->aliases->AddElement(rhs_expression->symbol->VariableCast());
  3908. }
  3909. EmitExpressionAssociation(unit_type, enclosing_method, vd -> variable_initializer_opt -> ExpressionCast(), d_table, w_table);
  3910. }
  3911. }
  3912. break;
  3913. default:
  3914. break;
  3915. }
  3916. }
  3917. void ExtractStructure(WriteAccessTable *w_table, ReadAccessTable *r_table, DelegationTable *d_table, ClassSymbolTable *cs_table, MethodBodyTable* mb_table, MethodSymbolTable *ms_table, GenTable* gen_table, AssocTable* assoc_table, TypeSymbol* unit_type, StoragePool* ast_pool)
  3918. {
  3919. //Coutput << unit_type->fully_qualified_name->value << endl;
  3920. if (unit_type->Anonymous() && (unit_type->NumInterfaces() || unit_type->super))
  3921. {
  3922. if (!unit_type->supertypes_closure)
  3923. unit_type->supertypes_closure = new SymbolSet(0);
  3924. if (unit_type->NumInterfaces())
  3925. unit_type->supertypes_closure->AddElement(unit_type->Interface(0));
  3926. if (unit_type->super)
  3927. unit_type->supertypes_closure->AddElement(unit_type->super);
  3928. }
  3929. Semantic& semantic = *unit_type -> semantic_environment -> sem;
  3930. LexStream *lex_stream = semantic.lex_stream;
  3931. wchar_t* package_name = unit_type -> FileLoc();
  3932. AstClassBody* class_body = unit_type -> declaration;
  3933. class_body -> Lexify(*lex_stream);
  3934. wchar_t* class_name = const_cast<wchar_t*>(unit_type -> Name());
  3935. EmitGeneralization(gen_table, unit_type); // to be eliminated.
  3936. cs_table -> AddClassSymbol(unit_type);
  3937. unsigned i;
  3938. if ((class_body -> NumClassVariables() + class_body -> NumInstanceVariables()) > 0)
  3939. {
  3940. unit_type -> instances = new SymbolSet();
  3941. unit_type -> references = new SymbolSet();
  3942. }
  3943. //
  3944. // Process static variables.
  3945. //
  3946. for (i = 0; i < class_body -> NumClassVariables(); i++)
  3947. {
  3948. AstFieldDeclaration* field_decl = class_body -> ClassVariable(i);
  3949. TypeSymbol *type = (field_decl -> type -> symbol -> IsArray())
  3950. ? field_decl -> type -> symbol -> base_type
  3951. : field_decl -> type -> symbol;
  3952. unit_type -> references -> AddElement(type);
  3953. for (unsigned vi = 0;
  3954. vi < field_decl -> NumVariableDeclarators(); vi++)
  3955. {
  3956. AstVariableDeclarator* vd = field_decl -> VariableDeclarator(vi);
  3957. unit_type -> instances -> AddElement(vd -> symbol);
  3958. field_decl -> PrintAssociation(assoc_table, package_name, class_name, *lex_stream);
  3959. //DeclareField(vd -> symbol);
  3960. if (vd->variable_initializer_opt && vd->variable_initializer_opt->ExpressionCast())
  3961. {
  3962. AstExpression *rhs_expression = Utility::RemoveCasting(vd->variable_initializer_opt->ExpressionCast());
  3963. if (rhs_expression->symbol->VariableCast())
  3964. {
  3965. if (!vd->symbol->aliases)
  3966. vd->symbol->aliases = new SymbolSet();
  3967. vd->symbol->aliases->AddElement(rhs_expression->symbol->VariableCast());
  3968. }
  3969. }
  3970. }
  3971. }
  3972. //
  3973. // Process instance variables. We separate constant fields from others,
  3974. // because in 1.4 or later, constant fields are initialized before the
  3975. // call to super() in order to obey semantics of JLS 13.1.
  3976. //
  3977. Tuple<AstVariableDeclarator*> constant_instance_fields
  3978. (unit_type -> NumVariableSymbols());
  3979. for (i = 0; i < class_body -> NumInstanceVariables(); i++)
  3980. {
  3981. AstFieldDeclaration* field_decl = class_body -> InstanceVariable(i);
  3982. TypeSymbol *type = (field_decl -> type -> symbol -> IsArray())
  3983. ? field_decl -> type -> symbol -> base_type
  3984. : field_decl -> type -> symbol;
  3985. unit_type -> references -> AddElement(type);
  3986. for (unsigned vi = 0;
  3987. vi < field_decl -> NumVariableDeclarators(); vi++)
  3988. {
  3989. AstVariableDeclarator* vd = field_decl -> VariableDeclarator(vi);
  3990. field_decl -> PrintAssociation(assoc_table, package_name, class_name, *lex_stream);
  3991. VariableSymbol* vsym = vd -> symbol;
  3992. unit_type -> instances -> AddElement(vsym);
  3993. //DeclareField(vsym);
  3994. if (vd -> variable_initializer_opt && vsym -> initial_value)
  3995. {
  3996. AstExpression* init;
  3997. assert(init = vd -> variable_initializer_opt -> ExpressionCast());
  3998. assert(init -> IsConstant() && vd -> symbol -> ACC_FINAL());
  3999. constant_instance_fields.Next() = vd;
  4000. AstExpression *expr = (init -> kind == Ast::CAST)
  4001. ? init -> CastExpressionCast() -> expression
  4002. : init;
  4003. if (expr -> kind == Ast::CLASS_CREATION)
  4004. {
  4005. if (!vsym -> concrete_types)
  4006. vsym -> concrete_types = new SymbolSet(0);
  4007. vsym -> concrete_types -> AddElement(expr -> ClassCreationExpressionCast() -> class_type -> symbol -> TypeCast());
  4008. }
  4009. }
  4010. if (vd->variable_initializer_opt && vd->variable_initializer_opt->ExpressionCast())
  4011. {
  4012. AstExpression *rhs_expression = Utility::RemoveCasting(vd->variable_initializer_opt->ExpressionCast());
  4013. if (rhs_expression->symbol->VariableCast())
  4014. {
  4015. if (!vd->symbol->aliases)
  4016. vd->symbol->aliases = new SymbolSet();
  4017. vd->symbol->aliases->AddElement(rhs_expression->symbol->VariableCast());
  4018. }
  4019. }
  4020. }
  4021. }
  4022. //
  4023. // Process synthetic fields (this$0, local shadow parameters, $class...,
  4024. // $array..., $noassert).
  4025. //
  4026. /*
  4027. if (unit_type -> EnclosingType())
  4028. DeclareField(unit_type -> EnclosingInstance());
  4029. for (i = 0; i < unit_type -> NumConstructorParameters(); i++)
  4030. DeclareField(unit_type -> ConstructorParameter(i));
  4031. for (i = 0; i < unit_type -> NumClassLiterals(); i++)
  4032. DeclareField(unit_type -> ClassLiteral(i));
  4033. VariableSymbol* assert_variable = unit_type -> AssertVariable();
  4034. if (assert_variable)
  4035. {
  4036. assert(! control.option.noassert);
  4037. DeclareField(assert_variable);
  4038. if (control.option.target < JikesOption::SDK1_4)
  4039. {
  4040. semantic.ReportSemError(SemanticError::ASSERT_UNSUPPORTED_IN_TARGET,
  4041. unit_type -> declaration,
  4042. unit_type -> ContainingPackageName(),
  4043. unit_type -> ExternalName());
  4044. assert_variable = NULL;
  4045. }
  4046. }
  4047. */
  4048. //
  4049. // Process declared methods.
  4050. //
  4051. for (i = 0; i < class_body -> NumMethods(); i++)
  4052. {
  4053. AstMethodDeclaration* method = class_body -> Method(i);
  4054. if (method -> method_symbol)
  4055. {
  4056. counter3++;
  4057. wchar_t* method_name = const_cast<wchar_t*>((*lex_stream).NameString(method -> method_declarator -> identifier_token));
  4058. //int method_index = methods.NextIndex(); // index for method
  4059. //BeginMethod(method_index, method -> method_symbol);
  4060. if (method -> method_body_opt) // not an abstract method ?
  4061. {
  4062. mb_table -> addMethodBodyAddr(package_name, class_name, method_name, method); // to be eliminated.
  4063. method -> PrintAssociation(assoc_table, package_name, class_name, *lex_stream);
  4064. ms_table -> AddMethodSymbol(method -> method_symbol);
  4065. assert(method -> method_body_opt -> NumStatements() > 0);
  4066. EmitBlockAssociation(unit_type, method -> method_symbol, method -> method_body_opt, d_table, w_table, r_table);
  4067. counter2++;
  4068. //EmitBlockStatement(method -> method_body_opt);
  4069. }
  4070. else
  4071. counter1++;
  4072. //EndMethod(method_index, method -> method_symbol);
  4073. }
  4074. }
  4075. //
  4076. // Process synthetic methods (access$..., class$).
  4077. //
  4078. /*
  4079. for (i = 0; i < unit_type -> NumPrivateAccessMethods(); i++)
  4080. {
  4081. int method_index = methods.NextIndex(); // index for method
  4082. MethodSymbol* method_sym = unit_type -> PrivateAccessMethod(i);
  4083. AstMethodDeclaration* method = method_sym -> declaration ->
  4084. MethodDeclarationCast();
  4085. assert(method);
  4086. BeginMethod(method_index, method_sym);
  4087. EmitBlockStatement(method -> method_body_opt);
  4088. EndMethod(method_index, method_sym);
  4089. }
  4090. MethodSymbol* class_literal_sym = unit_type -> ClassLiteralMethod();
  4091. if (class_literal_sym)
  4092. {
  4093. int method_index = methods.NextIndex(); // index for method
  4094. BeginMethod(method_index, class_literal_sym);
  4095. GenerateClassAccessMethod();
  4096. EndMethod(method_index, class_literal_sym);
  4097. }
  4098. */
  4099. //
  4100. // Process the instance initializer.
  4101. //
  4102. /*
  4103. bool has_instance_initializer = false;
  4104. if (unit_type -> instance_initializer_method)
  4105. {
  4106. AstMethodDeclaration* declaration = (AstMethodDeclaration*)
  4107. unit_type -> instance_initializer_method -> declaration;
  4108. AstBlock* init_block = declaration -> method_body_opt;
  4109. if (! IsNop(init_block))
  4110. {
  4111. int method_index = methods.NextIndex(); // index for method
  4112. BeginMethod(method_index,
  4113. unit_type -> instance_initializer_method);
  4114. bool abrupt = EmitBlockStatement(init_block);
  4115. if (! abrupt)
  4116. PutOp(OP_RETURN);
  4117. EndMethod(method_index, unit_type -> instance_initializer_method);
  4118. has_instance_initializer = true;
  4119. }
  4120. }
  4121. */
  4122. //
  4123. // Process all constructors (including synthetic ones).
  4124. //
  4125. if (!class_body -> default_constructor)
  4126. {
  4127. for (i = 0; i < class_body -> NumConstructors(); i++)
  4128. {
  4129. //AstConstructorDeclaration *constructor = dynamic_cast<AstConstructorDeclaration*>(class_body -> Constructor(i) -> Clone(ast_pool, *lex_stream));
  4130. AstConstructorDeclaration *constructor = class_body -> Constructor(i);
  4131. mb_table -> addMethodBodyAddr(package_name, class_name, class_name, constructor); // to be eliminated.
  4132. ms_table -> AddMethodSymbol(constructor -> constructor_symbol);
  4133. EmitBlockAssociation(unit_type, constructor -> constructor_symbol, constructor -> constructor_body, d_table, w_table, r_table);
  4134. // CompileConstructor(class_body -> Constructor(i), constant_instance_fields, has_instance_initializer);
  4135. }
  4136. }
  4137. /*
  4138. for (i = 0; i < unit_type -> NumPrivateAccessConstructors(); i++)
  4139. {
  4140. Coutput << "private access class ctor: " << class_name << endl;
  4141. MethodSymbol* constructor_sym = unit_type -> PrivateAccessConstructor(i);
  4142. AstConstructorDeclaration* constructor = constructor_sym -> declaration -> ConstructorDeclarationCast();
  4143. mb_table -> addMethodBodyAddr(package_name, class_name, class_name, constructor);
  4144. constructor-> PrintAssociation(assoc_table, package_name, class_name, *lex_stream);
  4145. ms_table -> AddMethodSymbol(const_cast<char*>(constructor_sym -> Utf8Name()), constructor_sym);
  4146. // CompileConstructor(constructor, constant_instance_fields, has_instance_initializer);
  4147. }
  4148. */
  4149. //
  4150. // Process the static initializer.
  4151. //
  4152. /*
  4153. if (unit_type -> static_initializer_method)
  4154. {
  4155. AstMethodDeclaration* declaration = (AstMethodDeclaration*)
  4156. unit_type -> static_initializer_method -> declaration;
  4157. AstBlock* init_block = declaration -> method_body_opt;
  4158. if (assert_variable || ! IsNop(init_block))
  4159. {
  4160. int method_index = methods.NextIndex(); // index for method
  4161. BeginMethod(method_index, unit_type -> static_initializer_method);
  4162. if (assert_variable)
  4163. GenerateAssertVariableInitializer(unit_type -> outermost_type,
  4164. assert_variable);
  4165. bool abrupt = EmitBlockStatement(init_block);
  4166. if (! abrupt)
  4167. PutOp(OP_RETURN);
  4168. EndMethod(method_index, unit_type -> static_initializer_method);
  4169. }
  4170. }
  4171. */
  4172. }
  4173. #ifdef DONTDOIT
  4174. void PrintRelation(MethodBodyTable* mb_table, GenTable* gen_table, AssocTable* assoc_table, TypeSymbol* unit_type, StoragePool* ast_pool)
  4175. {
  4176. Semantic& semantic = *unit_type -> semantic_environment -> sem;
  4177. LexStream *lex_stream = semantic.lex_stream;
  4178. AstCompilationUnit* compilation_unit = semantic.compilation_unit;
  4179. unsigned i;
  4180. for (i = 0; i < compilation_unit -> NumTypeDeclarations(); i++)
  4181. {
  4182. wchar_t* package_name = (compilation_unit -> package_declaration_opt)
  4183. ? const_cast<wchar_t*>((*lex_stream).NameString(compilation_unit -> package_declaration_opt -> name -> identifier_token))
  4184. : NULL;
  4185. if (compilation_unit -> TypeDeclaration(i) -> kind == Ast::CLASS)
  4186. {
  4187. AstClassDeclaration* class_declaration = dynamic_cast<AstClassDeclaration*> (compilation_unit -> TypeDeclaration(i));
  4188. class_declaration -> PrintGeneralization(gen_table, package_name, *lex_stream);
  4189. AstClassBody* class_body = class_declaration -> class_body;
  4190. unsigned j;
  4191. for (j = 0; j < class_body -> NumClassBodyDeclarations(); j++)
  4192. {
  4193. switch(class_body -> ClassBodyDeclaration(j) -> kind)
  4194. {
  4195. case Ast::FIELD:
  4196. class_body -> ClassBodyDeclaration(j) -> PrintAssociation(assoc_table,
  4197. package_name,
  4198. const_cast<wchar_t*>((*lex_stream).NameString(class_body -> identifier_token)),
  4199. *lex_stream);
  4200. break;
  4201. case Ast::CONSTRUCTOR:
  4202. {
  4203. wchar_t* class_name = const_cast<wchar_t*>((*lex_stream).NameString(class_body -> identifier_token));
  4204. AstConstructorDeclaration* ctor_declaration = dynamic_cast<AstConstructorDeclaration*> (class_body -> ClassBodyDeclaration(j));
  4205. wchar_t* ctor_name = const_cast<wchar_t*>((*lex_stream).NameString(ctor_declaration -> constructor_declarator -> identifier_token));
  4206. if (!ctor_declaration -> GoFTag)
  4207. {
  4208. AstConstructorDeclaration* cloned_declaration = dynamic_cast<AstConstructorDeclaration*>(ctor_declaration -> Clone(ast_pool, *lex_stream));
  4209. mb_table -> addMethodBodyAddr(package_name, class_name, ctor_name, cloned_declaration);
  4210. ctor_declaration -> GoFTag = true;
  4211. }
  4212. }
  4213. break;
  4214. case Ast::METHOD:
  4215. {
  4216. wchar_t* _className = const_cast<wchar_t*>((*lex_stream).NameString(class_body -> identifier_token));
  4217. AstMethodDeclaration* method_declaration = DYNAMIC_CAST<AstMethodDeclaration*> (class_body -> ClassBodyDeclaration(j));
  4218. wchar_t* _methodName = const_cast<wchar_t*>((*lex_stream).NameString(method_declaration -> method_declarator -> identifier_token));
  4219. /*
  4220. if ((wcscmp(_className, L"MediaTracker") == 0)
  4221. && (wcscmp(_methodName, L"addImage") == 0))
  4222. method_declaration -> method_body_opt -> Statement(0) -> Print(*lex_stream);
  4223. */
  4224. if (!method_declaration -> method_body_opt)
  4225. counter1++;
  4226. else if (method_declaration -> method_body_opt -> NumStatements() > 0)
  4227. counter2++;
  4228. else if ((method_declaration -> method_body_opt)
  4229. && (method_declaration -> method_body_opt -> NumStatements() == 0))
  4230. Coutput << _className << "." << _methodName << endl;
  4231. counter3++;
  4232. AstMethodDeclaration* cloned_declaration = DYNAMIC_CAST<AstMethodDeclaration*>(method_declaration -> Clone(ast_pool, *lex_stream));
  4233. mb_table -> addMethodBodyAddr(package_name, _className, _methodName, cloned_declaration);
  4234. class_body -> ClassBodyDeclaration(j) -> PrintAssociation(assoc_table,
  4235. package_name,
  4236. const_cast<wchar_t*>((*lex_stream).NameString(class_body -> identifier_token)),
  4237. *lex_stream);
  4238. method_declaration -> GoFTag = true;
  4239. }
  4240. break;
  4241. case Ast::CLASS:
  4242. case Ast::INTERFACE:
  4243. {
  4244. class_body -> ClassBodyDeclaration(j) -> PrintGeneralization(gen_table, package_name, *lex_stream);
  4245. }
  4246. break;
  4247. default:
  4248. break;
  4249. } // switch
  4250. } // for
  4251. class_declaration -> GoFTag = true;
  4252. }
  4253. else if (compilation_unit -> TypeDeclaration(i) -> kind == Ast::INTERFACE)
  4254. {
  4255. AstInterfaceDeclaration* interface_declaration = dynamic_cast<AstInterfaceDeclaration*> (compilation_unit -> TypeDeclaration(i));
  4256. interface_declaration -> PrintGeneralization(gen_table, package_name, *lex_stream);
  4257. interface_declaration -> GoFTag = true;
  4258. }
  4259. else
  4260. {
  4261. //Coutput << L"kind = " << compilation_unit -> TypeDeclaration(i) -> kind << endl;
  4262. }
  4263. }
  4264. }
  4265. #endif
  4266. bool WriteAccessTable::IsWrittenBy(VariableSymbol *vsym, MethodSymbol *msym)
  4267. {
  4268. multimap<VariableSymbol*, MethodSymbol*>::iterator p;
  4269. for (p = table -> begin(); p != table -> end(); p++)
  4270. {
  4271. if ((p -> first == vsym) && (p -> second == msym))
  4272. return true;
  4273. }
  4274. return false;
  4275. }
  4276. bool WriteAccessTable::IsWrittenBy(VariableSymbol *vsym, MethodSymbol *msym, DelegationTable *d_table)
  4277. {
  4278. multimap<VariableSymbol*, MethodSymbol*>::iterator p;
  4279. for (p = table -> begin(); p != table -> end(); p++)
  4280. {
  4281. if (p -> first == vsym)
  4282. {
  4283. if ((p -> second == msym) || (d_table -> TraceCall(p -> second, msym)))
  4284. return true;
  4285. }
  4286. }
  4287. return false;
  4288. }
  4289. int DelegationTable::IsBidirectional(TypeSymbol *t1,TypeSymbol *t2)
  4290. {
  4291. //
  4292. // return code:
  4293. //
  4294. // 3: bidirectional
  4295. // 2: -->
  4296. // 1: <--
  4297. // 0: no delegation
  4298. //
  4299. int forward = 0, backward = 0;
  4300. for (unsigned i =0; i < table -> size(); i++)
  4301. {
  4302. DelegationEntry *entry = (*table)[i];
  4303. forward = ((forward == 0) && (entry->from == t1) && (entry -> to == t2)) ? 1 : forward;
  4304. backward = ((backward == 0) && (entry->from == t2) && (entry -> to == t1)) ? 1 : backward;
  4305. }
  4306. return (2*forward + backward);
  4307. }
  4308. bool DelegationTable::TraceCall(MethodSymbol *start, MethodSymbol *target)
  4309. {
  4310. for (unsigned i =0; i < table -> size(); i++)
  4311. {
  4312. DelegationEntry *entry = (*table)[i];
  4313. if (entry -> method == start)
  4314. {
  4315. if ((entry -> enclosing == target)
  4316. ||(entry -> enclosing -> Overrides(target))
  4317. || TraceCall(entry -> enclosing, target))
  4318. return true;
  4319. }
  4320. }
  4321. return false;
  4322. }
  4323. int DelegationTable::UniqueDirectedCalls ()
  4324. {
  4325. multimap<TypeSymbol*, TypeSymbol*> stack;
  4326. for (unsigned i = 0; i < table -> size(); i++)
  4327. {
  4328. DelegationEntry *entry = (*table)[i];
  4329. if (entry -> to -> file_symbol
  4330. && (!entry -> to -> file_symbol -> IsClassOnly())
  4331. && (entry -> from != entry -> to)
  4332. && ((!entry -> from -> IsSubclass(entry -> to)) && (!entry -> to -> IsSubclass(entry -> from))))
  4333. {
  4334. if (stack.size() > 0)
  4335. {
  4336. multimap<TypeSymbol*, TypeSymbol*>::iterator p = stack.begin();
  4337. while (((p->first != entry -> from) || (p->second != entry -> to))
  4338. && (p != stack.end()))
  4339. p++;
  4340. if (p == stack.end())
  4341. stack.insert(p, pair<TypeSymbol*, TypeSymbol*>(entry->from, entry->to));
  4342. }
  4343. else
  4344. stack.insert(pair<TypeSymbol*, TypeSymbol*>(entry->from, entry->to));
  4345. }
  4346. }
  4347. return stack.size();
  4348. }
  4349. bool DelegationTable::DelegatesSuccessors(TypeSymbol *from, TypeSymbol *to)
  4350. {
  4351. assert (!from -> ACC_INTERFACE() && to -> ACC_INTERFACE());
  4352. for (unsigned i = 0; i < table -> size(); i++)
  4353. {
  4354. DelegationEntry *entry = (*table)[i];
  4355. if ((entry -> from == from) && (entry -> to != to) && (entry -> to -> Implements(to)))
  4356. {
  4357. TypeSymbol *resolve = (entry -> base_opt) ? ResolveType(entry -> base_opt) : NULL;
  4358. if (resolve && (to != resolve))
  4359. {
  4360. #ifdef GOF_CONSOLE
  4361. Coutput << "From: " << from -> Utf8Name()
  4362. << " To: " << to -> Utf8Name()
  4363. << " RESOLVE: " << resolve -> Utf8Name()
  4364. << " (" << entry -> method -> Utf8Name() << ")"
  4365. << endl;
  4366. #endif
  4367. return true;
  4368. }
  4369. }
  4370. }
  4371. return false;
  4372. }
  4373. TypeSymbol *DelegationTable::ResolveType(AstExpression *expression)
  4374. {
  4375. assert (expression);
  4376. switch(expression -> kind)
  4377. {
  4378. case Ast::NAME:
  4379. if (expression -> NameCast() -> resolution_opt)
  4380. return ResolveType(expression -> NameCast() -> resolution_opt);
  4381. else if (expression -> symbol -> Kind() == Symbol::TYPE)
  4382. return expression -> symbol -> TypeCast();
  4383. else if (expression -> symbol -> Kind() == Symbol::VARIABLE)
  4384. {
  4385. VariableSymbol *vsym = expression -> symbol -> VariableCast();
  4386. VariableSymbol *svsym = vsym -> ContainingType() -> Shadows(vsym);
  4387. if (svsym)
  4388. return svsym -> Type();
  4389. else
  4390. {
  4391. // Coutput << "\"" << vsym -> FileLoc() << "\"" << endl;
  4392. if (vsym -> IsLocal() && (vsym -> declarator -> variable_initializer_opt))
  4393. return ResolveType(vsym -> declarator -> variable_initializer_opt -> ExpressionCast());
  4394. return vsym -> Type();
  4395. }
  4396. }
  4397. case Ast::CALL:
  4398. {
  4399. AstMethodInvocation* method_call = expression -> MethodInvocationCast();
  4400. if (method_call -> resolution_opt)
  4401. method_call = method_call -> resolution_opt -> MethodInvocationCast();
  4402. return ((MethodSymbol*) method_call -> symbol) -> Type();
  4403. }
  4404. case Ast::CAST:
  4405. return ResolveType(expression -> CastExpressionCast() -> expression);
  4406. case Ast::PARENTHESIZED_EXPRESSION:
  4407. return ResolveType(expression -> ParenthesizedExpressionCast() -> expression);
  4408. default:
  4409. return NULL;
  4410. }
  4411. }
  4412. MethodSymbol *DelegationTable::Delegates(TypeSymbol *from, TypeSymbol *to)
  4413. {
  4414. assert(from -> ACC_INTERFACE() && (! to -> ACC_INTERFACE()));
  4415. unsigned i = 0;
  4416. while (i < table -> size())
  4417. {
  4418. DelegationEntry *entry = (*table)[i];
  4419. if (((entry -> from == from) || entry -> from -> Implements(from))
  4420. && ((entry -> to == to) || entry -> to -> IsSubclass(to)))
  4421. {
  4422. #ifdef GOF_CONSOLE
  4423. Coutput << entry -> from -> Utf8Name()
  4424. << " delegates "
  4425. << entry -> to -> Utf8Name()
  4426. << "::"
  4427. << entry -> method -> Utf8Name()
  4428. << endl;
  4429. #endif
  4430. return entry -> method;
  4431. }
  4432. i++;
  4433. }
  4434. return NULL;
  4435. }
  4436. void DelegationTable::InsertDelegation(TypeSymbol *from, TypeSymbol *to, AstExpression *base_opt, VariableSymbol *vsym, MethodSymbol *method, MethodSymbol *enclosing, AstMethodInvocation *call)
  4437. {
  4438. unsigned i = 0;
  4439. while ((i < table -> size())
  4440. && (((*table)[i] -> from != from)
  4441. ||((*table)[i] -> to != to)
  4442. ||((*table)[i] -> base_opt != base_opt)
  4443. ||((*table)[i] -> vsym != vsym)
  4444. ||((*table)[i] -> method != method)
  4445. ||((*table)[i] -> enclosing != enclosing)
  4446. ||((*table)[i] -> call != call))) i++;
  4447. if (i == table -> size())
  4448. table -> push_back(new DelegationEntry(from, to, base_opt, vsym, method, enclosing, call));
  4449. }
  4450. void DelegationTable::ShowDelegations(TypeSymbol *from, TypeSymbol *to)
  4451. {
  4452. if (from -> ACC_INTERFACE() && to -> ACC_INTERFACE())
  4453. {
  4454. for (unsigned i = 0; i < table -> size(); i++)
  4455. {
  4456. DelegationEntry *entry = (*table)[i];
  4457. bool flag1, flag2;
  4458. flag1 = (entry -> from -> ACC_INTERFACE() && entry -> from -> IsSubinterface(from))
  4459. ? true
  4460. : (!entry -> from -> ACC_INTERFACE() && entry -> from -> Implements(from))
  4461. ? true
  4462. : false;
  4463. flag2 = (entry -> to -> ACC_INTERFACE() && entry -> to -> IsSubinterface(to))
  4464. ? true
  4465. : (!entry -> to -> ACC_INTERFACE() && entry -> to -> Implements(to))
  4466. ? true
  4467. : false;
  4468. if (flag1 && flag2)
  4469. {
  4470. Coutput << entry -> from -> Utf8Name()
  4471. << " --> "
  4472. << entry -> to -> Utf8Name()
  4473. << " (";
  4474. if (entry -> base_opt == NULL)
  4475. Coutput << "";
  4476. else if (entry -> base_opt -> kind == Ast::THIS_CALL)
  4477. Coutput << "this";
  4478. else if ((entry -> base_opt -> kind == Ast::CAST) && (entry -> base_opt -> CastExpressionCast() -> expression -> kind == Ast::NAME))
  4479. Coutput << entry -> base_opt -> CastExpressionCast() -> expression -> symbol -> VariableCast() -> Utf8Name();
  4480. else if ((entry -> base_opt -> kind == Ast::NAME) && (entry -> base_opt -> symbol -> Kind() == Symbol::VARIABLE))
  4481. Coutput << entry -> base_opt -> symbol -> VariableCast() -> Utf8Name();
  4482. else if ((entry -> base_opt -> kind == Ast::NAME) && (entry -> base_opt -> symbol -> Kind() == Symbol::TYPE))
  4483. Coutput << entry -> base_opt -> symbol -> TypeCast() -> Utf8Name();
  4484. else
  4485. Coutput << "unknown";
  4486. Coutput << "."
  4487. << entry -> method -> Utf8Name()
  4488. << ")"
  4489. << endl;
  4490. }
  4491. }
  4492. }
  4493. else if (!from -> ACC_INTERFACE() && to -> ACC_INTERFACE())
  4494. {
  4495. for (unsigned i = 0; i < table -> size(); i++)
  4496. {
  4497. DelegationEntry *entry = (*table)[i];
  4498. bool flag1, flag2;
  4499. flag1 = (!entry -> from -> ACC_INTERFACE() && entry -> from -> IsSubclass(from))
  4500. ? true
  4501. : false;
  4502. flag2 = (entry -> to -> ACC_INTERFACE() && entry -> to -> IsSubinterface(to))
  4503. ? true
  4504. : (!entry -> to -> ACC_INTERFACE() && entry -> to -> Implements(to))
  4505. ? true
  4506. : false;
  4507. if (flag1 && flag2)
  4508. {
  4509. Coutput << entry -> from -> Utf8Name()
  4510. << " --> "
  4511. << entry -> to -> Utf8Name()
  4512. << " (";
  4513. if (entry -> base_opt)
  4514. Coutput << ResolveType(entry -> base_opt) -> Utf8Name();
  4515. /*
  4516. if (entry -> base_opt == NULL)
  4517. Coutput << "";
  4518. else if (entry -> base_opt -> kind == Ast::THIS_CALL)
  4519. Coutput << "this";
  4520. else if (entry -> base_opt -> kind == Ast::PARENTHESIZED_EXPRESSION)
  4521. Coutput << "(...)";
  4522. else if ((entry -> base_opt -> kind == Ast::CAST) && (entry -> base_opt -> CastExpressionCast() -> expression -> kind == Ast::NAME))
  4523. Coutput << entry -> base_opt -> CastExpressionCast() -> expression -> symbol -> VariableCast() -> Utf8Name();
  4524. else if ((entry -> base_opt -> kind == Ast::NAME) && (entry -> base_opt -> symbol -> Kind() == Symbol::VARIABLE))
  4525. Coutput << entry -> base_opt -> symbol -> VariableCast() -> Utf8Name();
  4526. else if ((entry -> base_opt -> kind == Ast::NAME) && (entry -> base_opt -> symbol -> Kind() == Symbol::TYPE))
  4527. Coutput << entry -> base_opt -> symbol -> TypeCast() -> Utf8Name();
  4528. else
  4529. Coutput << "unknown";
  4530. */
  4531. Coutput << "."
  4532. << entry -> method -> Utf8Name()
  4533. << ")"
  4534. << endl;
  4535. }
  4536. }
  4537. }
  4538. }
  4539. void DelegationTable::ConcretizeDelegations()
  4540. {
  4541. unsigned i;
  4542. for (i = 0; i<table->size(); i++)
  4543. {
  4544. DelegationEntry *entry = (*table)[i];
  4545. if (entry-> from && entry->vsym && entry->vsym->concrete_types)
  4546. {
  4547. Symbol *sym = entry -> vsym -> concrete_types -> FirstElement();
  4548. while (sym)
  4549. {
  4550. if (!sym -> TypeCast() -> call_dependents)
  4551. sym -> TypeCast() -> call_dependents = new SymbolSet(0);
  4552. sym -> TypeCast() -> call_dependents -> AddElement(entry -> from);
  4553. sym = entry -> vsym -> concrete_types -> NextElement();
  4554. }
  4555. }
  4556. }
  4557. }
  4558. void DelegationTable::DumpTable()
  4559. {
  4560. Coutput << "delegationTable::DumpTable" << endl;
  4561. unsigned i;
  4562. for (i = 0; i < table -> size(); i++)
  4563. {
  4564. DelegationEntry *entry = (*table)[i];
  4565. Coutput << entry -> from -> Utf8Name()
  4566. << " --> "
  4567. << entry -> to -> Utf8Name()
  4568. << " ("
  4569. << entry -> method -> Utf8Name()
  4570. << ") at "
  4571. << entry -> enclosing -> Utf8Name()
  4572. << endl
  4573. << endl;
  4574. }
  4575. }
  4576. int ClassSymbolTable::ConcreteClasses()
  4577. {
  4578. int ct = 0;
  4579. for (unsigned c = 0; c < table->size(); c++)
  4580. {
  4581. if ((!(*table)[c] -> ACC_INTERFACE())
  4582. && (!(*table)[c] -> ACC_ABSTRACT())
  4583. && (!(*table)[c] -> ACC_SYNTHETIC())
  4584. && (!(*table)[c] ->IsInner()))
  4585. ct++;
  4586. }
  4587. return ct;
  4588. }
  4589. bool ClassSymbolTable::Converge(TypeSymbol* super1, TypeSymbol* super2)
  4590. {
  4591. bool flag1, flag2;
  4592. flag1 = flag2 = false;
  4593. for (unsigned c = 0; (!flag1 ||!flag2) && (c < table->size()); c++)
  4594. {
  4595. TypeSymbol *type = (*table)[c];
  4596. if (type -> ACC_INTERFACE())
  4597. {
  4598. if (super1 -> ACC_INTERFACE())
  4599. flag1 = type -> IsSubinterface(super1);
  4600. else
  4601. flag1 = false;
  4602. if (super2 -> ACC_INTERFACE())
  4603. flag2 = type -> IsSubinterface(super2);
  4604. else
  4605. flag2 = false;
  4606. }
  4607. else
  4608. {
  4609. if (super1 -> ACC_INTERFACE())
  4610. flag1 = type -> Implements(super1);
  4611. else
  4612. flag1 = type -> IsSubclass(super1);
  4613. if (super2 -> ACC_INTERFACE())
  4614. flag2 = type -> Implements(super2);
  4615. else
  4616. flag2 = type -> IsSubclass(super2);
  4617. }
  4618. }
  4619. #ifdef GOF_CONSOLE
  4620. if (flag1 && flag2)
  4621. Coutput << (--p) -> first << " converges " << super1->Utf8Name() << " and " << super2->Utf8Name() << endl;
  4622. #endif
  4623. return (flag1 && flag2);
  4624. }
  4625. void ClassSymbolTable::AddClassSymbol(TypeSymbol *sym)
  4626. {
  4627. table->push_back(sym);
  4628. }
  4629. TypeSymbol *ClassSymbolTable::GetSymbol(wchar_t * cls)
  4630. {
  4631. for (unsigned c = 0; c < table->size(); c++)
  4632. {
  4633. TypeSymbol *sym = (*table)[c];
  4634. if (wcscmp(cls, sym-> Name()) == 0)
  4635. return sym;
  4636. }
  4637. return NULL;
  4638. }
  4639. bool ClassSymbolTable::IsFamily(TypeSymbol* t1, TypeSymbol *t2)
  4640. {
  4641. if ((t1 -> ACC_INTERFACE() ||t1 -> ACC_ABSTRACT() || t1 -> ACC_SYNTHETIC())
  4642. || (t2 -> ACC_INTERFACE() ||t2 -> ACC_ABSTRACT() || t2 -> ACC_SYNTHETIC()))
  4643. return false;
  4644. for (unsigned c = 0; c < table->size(); c++)
  4645. {
  4646. TypeSymbol *type = (*table)[c];
  4647. if (type->ACC_SYNTHETIC())
  4648. {
  4649. if (type -> ACC_INTERFACE())
  4650. return (t1->Implements(type) && t2->Implements(type));
  4651. else
  4652. return (t1->IsSubclass(type) && t2->IsSubclass(type));
  4653. }
  4654. }
  4655. return false;
  4656. }
  4657. bool ClassSymbolTable::HasSubclasses(TypeSymbol *super)
  4658. {
  4659. if (!super -> ACC_INTERFACE())
  4660. {
  4661. for (unsigned c = 0; c < table->size(); c++)
  4662. {
  4663. TypeSymbol *type = (*table)[c];
  4664. if (type -> IsSubclass(super))
  4665. return true;
  4666. }
  4667. return false;
  4668. }
  4669. return false;
  4670. }
  4671. vector<TypeSymbol*> *ClassSymbolTable::GetAncestors(TypeSymbol *type)
  4672. {
  4673. // Error: includes Object, which every class subclasses
  4674. vector<TypeSymbol*> *a = new vector<TypeSymbol*>();
  4675. for (; type; type = type -> super)
  4676. a -> push_back(type);
  4677. return a;
  4678. }
  4679. void ClassSymbolTable::PrintSubclasses(TypeSymbol* super)
  4680. {
  4681. assert (! super -> ACC_INTERFACE());
  4682. for (unsigned c = 0; c < table->size(); c++)
  4683. {
  4684. if ((!(*table)[c]->ACC_INTERFACE())
  4685. && ((*table)[c] -> IsSubclass(super)))
  4686. Coutput << (*table)[c]->Utf8Name() << " ";
  4687. }
  4688. Coutput << endl;
  4689. }
  4690. void ClassSymbolTable::PrintSubinterfaces(TypeSymbol* inter)
  4691. {
  4692. assert (inter -> ACC_INTERFACE());
  4693. for (unsigned c = 0; c < table->size(); c++)
  4694. {
  4695. if (((*table)[c]->ACC_INTERFACE())
  4696. && ((*table)[c]->IsSubinterface(inter)))
  4697. Coutput << (*table)[c]->Utf8Name() << " ";
  4698. }
  4699. Coutput << endl;
  4700. }
  4701. void ClassSymbolTable::PrintSubtypes(TypeSymbol *inter)
  4702. {
  4703. assert (inter -> ACC_INTERFACE());
  4704. for (unsigned c = 0; c < table->size(); c++)
  4705. {
  4706. if ((!(*table)[c]->ACC_INTERFACE()) && ((*table)[c]->Implements(inter)))
  4707. {
  4708. Coutput << (*table)[c]->Utf8Name();
  4709. if ((*table)[c]->IsInner())
  4710. Coutput << "(inner) ";
  4711. else if ((*table)[c]->ACC_PRIVATE())
  4712. Coutput << "(private) ";
  4713. else
  4714. Coutput << " ";
  4715. }
  4716. }
  4717. Coutput << endl;
  4718. }
  4719. void ClassSymbolTable::ExpandSubtypes()
  4720. {
  4721. unsigned p, q;
  4722. for (p = 0; p < table->size(); p++)
  4723. {
  4724. /*
  4725. Coutput << p->second->fully_qualified_name->value << ": " << endl;
  4726. if (p->second->subtypes_closure && p->second->subtypes_closure->Size())
  4727. {
  4728. Coutput << "subtypes_closure: ";
  4729. p->second->subtypes_closure->Print();
  4730. }
  4731. if (p->second->subtypes && p->second->subtypes->Size())
  4732. {
  4733. Coutput << "subtypes: ";
  4734. p->second->subtypes->Print();
  4735. }
  4736. Coutput << endl;
  4737. */
  4738. if ((*table)[p]->subtypes)
  4739. {
  4740. for (q = 0; q < table->size(); q++)
  4741. {
  4742. if ((*table)[p] != (*table)[q]
  4743. && !(*table)[p]->subtypes->IsElement((*table)[q])
  4744. && (*table)[q]->IsSubtype((*table)[p])
  4745. )
  4746. (*table)[p]->subtypes->AddElement((*table)[q]);
  4747. }
  4748. }
  4749. }
  4750. }
  4751. void MethodSymbolTable::AddMethodSymbol(MethodSymbol *sym)
  4752. {
  4753. table -> push_back(sym);
  4754. }
  4755. MethodSymbol *MethodSymbolTable::GetSymbol(char *cls, char *mtd, char *fname)
  4756. {
  4757. for (unsigned i=0; i<table->size(); i++)
  4758. {
  4759. MethodSymbol *method_symbol = (*table)[i];
  4760. TypeSymbol *unit_type = method_symbol -> containing_type;
  4761. if ((strcmp(method_symbol->Utf8Name(), mtd) == 0)
  4762. && (strcmp(unit_type -> Utf8Name(), cls) == 0)
  4763. && (strcmp(unit_type -> file_symbol -> FileName(), fname) == 0))
  4764. return method_symbol;
  4765. }
  4766. return NULL;
  4767. }
  4768. Ast *MethodSymbolTable::GetAstDeclaration(wchar_t *pkg, wchar_t *cls, wchar_t *mtd)
  4769. {
  4770. for (unsigned i=0; i<table->size(); i++)
  4771. {
  4772. MethodSymbol *method_symbol = (*table)[i];
  4773. TypeSymbol *unit_type = method_symbol -> containing_type;
  4774. if ((wcscmp(method_symbol -> Name(), mtd) == 0)
  4775. && (wcscmp(unit_type -> Name(), cls) == 0)
  4776. && (wcscmp(unit_type -> FileLoc(), pkg) == 0))
  4777. return method_symbol -> declaration;
  4778. }
  4779. return NULL;
  4780. }
  4781. void MethodSymbolTable::PrintDeclaration(char *cls, char *mtd, char *fname)
  4782. {
  4783. for (unsigned i=0; i<table->size(); i++)
  4784. {
  4785. TypeSymbol *unit_type = (*table)[i]->containing_type;
  4786. if ((strcmp((*table)[i]->Utf8Name(), mtd) == 0)
  4787. && (strcmp(unit_type -> Utf8Name(), cls) == 0)
  4788. && (strcmp(unit_type -> file_symbol -> FileName(), fname) == 0))
  4789. {
  4790. MethodSymbol *method_symbol = (*table)[i];
  4791. TypeSymbol *type = method_symbol -> containing_type;
  4792. Coutput << "file name: " << type -> file_symbol -> FileName() << endl;
  4793. Coutput << "class name: " << type -> Utf8Name() << endl;
  4794. method_symbol -> declaration -> Print();
  4795. Coutput << mtd << ": " << dynamic_cast<AstMethodDeclaration*>(method_symbol -> declaration) -> method_body_opt -> NumStatements() << endl;
  4796. }
  4797. }
  4798. }
  4799. void MethodSymbolTable::PrintBody(char *cls, char *mtd, char *fname)
  4800. {
  4801. unsigned i=0;
  4802. for (; i<table->size(); i++)
  4803. {
  4804. TypeSymbol *unit_type = (*table)[i]->containing_type;
  4805. if ((strcmp((*table)[i]->Utf8Name(), mtd) == 0)
  4806. && (strcmp(unit_type -> Utf8Name(), cls) == 0)
  4807. && (strcmp(unit_type -> file_symbol -> FileName(), fname) == 0))
  4808. break;
  4809. }
  4810. if (i<table->size())
  4811. {
  4812. MethodSymbol *method_symbol = (*table)[i];
  4813. dynamic_cast<AstMethodDeclaration*>(method_symbol -> declaration) -> method_body_opt -> Print();
  4814. }
  4815. }
  4816. void MethodSymbolTable::ExpandCallDependents()
  4817. {
  4818. // does NOT expand typesymbol->call_dependents
  4819. for (unsigned i=0; i<table->size(); i++)
  4820. {
  4821. MethodSymbol *method = (*table)[i];
  4822. MethodSymbol *overridden = method->GetVirtual(); // TODO: consider mult-inheritance
  4823. if (overridden)
  4824. {
  4825. if (overridden->invokers)
  4826. {
  4827. if (!method->invokers)
  4828. method->invokers = new SymbolSet(0);
  4829. method->invokers->Union(*overridden->invokers);
  4830. Symbol *sym = overridden->invokers->FirstElement();
  4831. while(sym)
  4832. {
  4833. MethodSymbol *msym = sym->MethodCast();
  4834. msym->invokees->AddElement(method);
  4835. sym = overridden->invokers->NextElement();
  4836. }
  4837. }
  4838. if (overridden ->callers)
  4839. {
  4840. if (!method->callers)
  4841. method->callers = new SymbolSet(0);
  4842. method->callers->Union(*overridden->callers);
  4843. }
  4844. }
  4845. }
  4846. }
  4847. void MethodSymbolTable::ClearMarks()
  4848. {
  4849. for (unsigned i=0; i<table->size(); i++)
  4850. {
  4851. if ((*table)[i]->mark != 'W')
  4852. (*table)[i]->mark = 'W';
  4853. }
  4854. }
  4855. Env::State EnvTable::getState(wchar_t* var)
  4856. {
  4857. unsigned i = 0;
  4858. while ((i < table -> size())
  4859. && (wcscmp((*table)[i] -> var, var) != 0))
  4860. i++;
  4861. return (*table)[i] -> state;
  4862. }
  4863. void EnvTable::changeState(wchar_t* var, Env::State state)
  4864. {
  4865. unsigned i = 0;
  4866. while ((i < table -> size())
  4867. && (wcscmp((*table)[i] -> var, var) != 0))
  4868. i++;
  4869. if (i < table -> size())
  4870. (*table)[i] -> state = state;
  4871. }
  4872. AstDeclared* MethodBodyTable::getAstLocation(wchar_t* cls, wchar_t* mtd)
  4873. {
  4874. MethodBodyAddr* entry = NULL;
  4875. bool flag = false;
  4876. unsigned i = 0;
  4877. while (!flag && (i < table -> size()))
  4878. {
  4879. entry = (*table)[i];
  4880. if ((wcscmp(cls, entry -> class_name) == 0)
  4881. && (wcscmp(mtd, entry -> method_name) == 0))
  4882. flag = true;
  4883. else
  4884. i++;
  4885. }
  4886. return (flag) ? entry -> ast_location : NULL;
  4887. }
  4888. vector<wchar_t*>* MethodBodyTable::getModifiersAt(int i)
  4889. {
  4890. AstDeclared *decl = (*table)[i] -> ast_location;
  4891. vector<wchar_t*>* modifiers = NULL;
  4892. if (decl -> modifiers_opt)
  4893. {
  4894. modifiers = new vector<wchar_t*>();
  4895. unsigned i;
  4896. for (i = 0; i < decl -> modifiers_opt -> NumModifiers(); i++)
  4897. {
  4898. if (decl -> modifiers_opt -> Modifier(i) -> kind == Ast::MODIFIER_KEYWORD)
  4899. modifiers -> push_back(dynamic_cast<AstModifierKeyword*>(decl -> modifiers_opt -> Modifier(i)) -> modifier_token_string);
  4900. else
  4901. decl -> Print();
  4902. }
  4903. }
  4904. return modifiers;
  4905. }
  4906. vector<wchar_t*>* GenTable::getAncestors(GenTable::Kind kind, wchar_t* cls, wchar_t* pkg)
  4907. {
  4908. bool flag = false;
  4909. unsigned i = 0;
  4910. while (!flag && (i < table -> size()))
  4911. {
  4912. Gen* entry = (*table)[i];
  4913. if (wcscmp((entry -> class_name), cls) == 0)
  4914. //*&& (wcscmp((entry -> package_name), pkg) == 0))
  4915. flag = true;
  4916. else
  4917. i++;
  4918. }
  4919. Gen* entry = (*table)[i];
  4920. if (flag && (kind == GenTable::SUBC) && (entry -> kind != Gen::INTERFACE))
  4921. {
  4922. wchar_t* spr = entry -> super_name;
  4923. vector<wchar_t*>* ancestors = new vector<wchar_t*>();
  4924. ancestors -> push_back(cls);
  4925. while (spr)
  4926. {
  4927. ancestors -> push_back(spr);
  4928. spr = getSuper(spr, pkg);
  4929. }
  4930. return ancestors;
  4931. }
  4932. else if (flag && (kind == GenTable::IMPL))
  4933. {
  4934. vector<wchar_t*>* ancestors = new vector<wchar_t*>();
  4935. if ((entry -> kind != Gen::INTERFACE) && (entry -> interfaces))
  4936. {
  4937. unsigned j;
  4938. for (j = 0; j < entry -> interfaces -> size(); j++)
  4939. ancestors -> push_back((*entry -> interfaces)[j]);
  4940. }
  4941. if (entry -> kind == Gen::INTERFACE)
  4942. ancestors -> push_back(entry -> class_name);
  4943. return ancestors;
  4944. }
  4945. return NULL;
  4946. }
  4947. wchar_t* GenTable::getSuper(wchar_t* cls, wchar_t* pkg)
  4948. {
  4949. unsigned i = 0;
  4950. Gen*entry = NULL;
  4951. while (!entry && (i < table -> size()))
  4952. {
  4953. if (wcscmp(((*table)[i] -> class_name), cls) == 0)
  4954. {
  4955. if ((((*table)[i] -> package_name == NULL) && (pkg == NULL))
  4956. || (((*table)[i] -> package_name != NULL) && (pkg != NULL) && (wcscmp((*table)[i] -> package_name, pkg) == 0)))
  4957. entry = (*table)[i];
  4958. else
  4959. i++;
  4960. }
  4961. else
  4962. i++;
  4963. }
  4964. return (entry)?entry -> super_name:NULL;
  4965. }
  4966. vector<wchar_t*>* GenTable::getSuccessors(wchar_t* super, GenTable::Kind kind)
  4967. {
  4968. vector<wchar_t*>* list = NULL;
  4969. unsigned i;
  4970. if (kind == GenTable::IMPL)
  4971. {
  4972. for (i = 0; i < table -> size(); i++)
  4973. {
  4974. Gen* entry = (*table)[i];
  4975. unsigned j;
  4976. if (entry -> interfaces)
  4977. {
  4978. for (j = 0; j < entry -> interfaces -> size(); j++)
  4979. {
  4980. if (wcscmp(super, (*entry -> interfaces)[j]) == 0)
  4981. {
  4982. if (list == NULL)
  4983. list = new vector<wchar_t*>();
  4984. list -> push_back(entry -> class_name);
  4985. }
  4986. }
  4987. }
  4988. }
  4989. }
  4990. else
  4991. {
  4992. for (i = 0; i < table -> size(); i++)
  4993. {
  4994. Gen* entry = (*table)[i];
  4995. //unsigned j;
  4996. if (entry -> super_name)
  4997. {
  4998. if (wcscmp(super, entry -> super_name) == 0)
  4999. {
  5000. if (list == NULL)
  5001. list = new vector<wchar_t*>();
  5002. list -> push_back(entry -> class_name);
  5003. }
  5004. }
  5005. }
  5006. }
  5007. return list;
  5008. }
  5009. Gen::Kind GenTable::getKind(wchar_t* cls, wchar_t* pkg)
  5010. {
  5011. Gen* entry = NULL;
  5012. bool flag = false;
  5013. unsigned i = 0;
  5014. while (!flag && (i < table -> size()))
  5015. {
  5016. entry = (*table)[i];
  5017. if (wcscmp(entry -> class_name, cls) == 0)
  5018. {
  5019. if (((entry -> package_name == NULL) && (pkg == NULL))
  5020. || (((entry -> package_name != NULL) && (pkg != NULL)) && (wcscmp(entry -> package_name, pkg) == 0)))
  5021. flag = true;
  5022. else
  5023. i++;
  5024. }
  5025. else
  5026. i++;
  5027. }
  5028. assert(flag);
  5029. return entry ->kind;
  5030. }
  5031. char* GenTable::getFileName(wchar_t* cls, wchar_t* pkg)
  5032. {
  5033. Gen* entry = NULL;
  5034. bool flag = false;
  5035. unsigned i = 0;
  5036. while (!flag && (i < table -> size()))
  5037. {
  5038. entry = (*table)[i];
  5039. if (wcscmp(entry -> class_name, cls) == 0)
  5040. {
  5041. if (((entry -> package_name == NULL) && (pkg == NULL))
  5042. || ((entry -> package_name != NULL && (pkg != NULL)) && (wcscmp(entry -> package_name, pkg) == 0)))
  5043. flag = true;
  5044. else
  5045. i++;
  5046. }
  5047. else
  5048. i++;
  5049. }
  5050. return (flag) ? entry ->file_name : NULL;
  5051. }
  5052. vector<wchar_t*>* GenTable::getInterfaces(wchar_t* pkg, wchar_t* cls)
  5053. {
  5054. Gen* entry = NULL;
  5055. bool flag = false;
  5056. unsigned i = 0;
  5057. while (!flag && (i < table -> size()))
  5058. {
  5059. entry = (*table)[i];
  5060. if ((wcscmp(entry -> package_name, pkg) == 0)
  5061. && (wcscmp(entry -> class_name, cls) == 0))
  5062. {
  5063. flag = true;
  5064. }
  5065. else
  5066. i++;
  5067. }
  5068. return (flag) ? entry -> interfaces : NULL;
  5069. }
  5070. wchar_t* AssocTable::getName(Assoc::Kind kind, Assoc::Mode mode, wchar_t* type, wchar_t* cls)
  5071. {
  5072. Assoc* entry = NULL;
  5073. bool flag = false;
  5074. unsigned i = 0;
  5075. while (!flag && (i < table -> size()))
  5076. {
  5077. entry = (*table)[i];
  5078. if ((entry -> kind == kind)
  5079. && (entry -> mode == mode)
  5080. && (wcscmp(entry -> type, type) == 0)
  5081. && (wcscmp(entry -> class_name, cls) == 0))
  5082. flag = true;
  5083. else
  5084. i++;
  5085. }
  5086. return (flag) ? entry -> name : NULL;
  5087. }
  5088. wchar_t* AssocTable::getType(Assoc::Kind kind, Assoc::Mode mode, wchar_t* name, wchar_t* pkg, wchar_t* cls)
  5089. {
  5090. Assoc* entry = NULL;
  5091. bool flag = false;
  5092. unsigned i = 0;
  5093. while (!flag && (i < table -> size()))
  5094. {
  5095. entry = (*table)[i];
  5096. if ((entry -> kind == kind)
  5097. && (entry -> mode == mode)
  5098. && (wcscmp(entry -> name, name) == 0)
  5099. // && (wcscmp(entry -> package_name, pkg) == 0)
  5100. && (wcscmp(entry -> class_name, cls) == 0))
  5101. flag = true;
  5102. else
  5103. i++;
  5104. }
  5105. return (flag) ? entry -> type : NULL;
  5106. }
  5107. bool AssocTable::isInvoked(wchar_t* name, wchar_t* cls)
  5108. {
  5109. unsigned i = 0;
  5110. while (i < table -> size())
  5111. {
  5112. Assoc* entry = (*table)[i];
  5113. if ((entry -> kind == Assoc::MI)
  5114. && (entry -> type)
  5115. && (wcscmp(entry -> type, name) == 0)
  5116. && (wcscmp(entry -> class_name, cls) == 0))
  5117. return true;
  5118. i++;
  5119. }
  5120. return false;
  5121. }
  5122. void EnvTable::addEnvironment(wchar_t* var, Env::State state)
  5123. {
  5124. Env* entry = new Env(var, state);
  5125. table -> push_back(entry);
  5126. }
  5127. void MethodBodyTable::addMethodBodyAddr(wchar_t* pkg, wchar_t* cls, wchar_t* mtd, AstDeclared* ptr)
  5128. {
  5129. MethodBodyAddr* entry = new MethodBodyAddr(pkg, cls, mtd, ptr);
  5130. table -> push_back(entry);
  5131. }
  5132. void GenTable::addGeneralization(wchar_t* pkg, wchar_t* cls, wchar_t* spr, vector<wchar_t*>* ifcs, Gen::Kind k, char* f)
  5133. {
  5134. Gen* entry = new Gen(pkg, cls, spr, ifcs, k, f);
  5135. table -> push_back(entry);
  5136. }
  5137. void AssocTable::addAssociation(Assoc::Kind kind, Assoc::Mode mode, wchar_t* name, wchar_t* type, wchar_t* pkg, wchar_t* cls, wchar_t* mtd)
  5138. {
  5139. Assoc* entry = new Assoc(kind, mode, name, type, pkg, cls, mtd);
  5140. table -> push_back(entry);
  5141. }
  5142. void MethodBodyTable::dumpTable()
  5143. {
  5144. Coutput << L"Method Body Reference Table" << endl;
  5145. unsigned i;
  5146. for (i = 0; i < table -> size(); i++)
  5147. {
  5148. MethodBodyAddr* entry = (*table)[i];
  5149. Coutput << entry -> class_name
  5150. << "::"
  5151. << entry -> method_name
  5152. << endl;
  5153. if (entry -> ast_location -> kind == Ast::CONSTRUCTOR)
  5154. {
  5155. Coutput << L"***constructor***" << endl;
  5156. dynamic_cast<AstConstructorDeclaration*>(entry -> ast_location) -> Print();
  5157. }
  5158. else
  5159. {
  5160. Coutput << L"***method***" << endl;
  5161. dynamic_cast<AstMethodDeclaration*>(entry -> ast_location) -> Print();
  5162. }
  5163. }
  5164. Coutput << endl;
  5165. }
  5166. void GenTable::dumpTable()
  5167. {
  5168. Coutput << L"Generalization Table" << endl;
  5169. unsigned i;
  5170. for (i = 0; i < table -> size(); i++)
  5171. {
  5172. Gen* entry = (*table)[i];
  5173. if (entry -> kind == Gen::CLASS)
  5174. {
  5175. Coutput << entry -> class_name << " |--> "
  5176. << ((entry -> super_name) ? entry -> super_name : L"java.lang.Object")
  5177. << " ";
  5178. unsigned j;
  5179. Coutput << "{";
  5180. if (entry -> interfaces)
  5181. {
  5182. for (j = 0; j < entry -> interfaces -> size(); j++)
  5183. {
  5184. unsigned end = entry -> interfaces -> size() - 1;
  5185. Coutput << (*(entry -> interfaces))[j];
  5186. if (j < end)
  5187. Coutput << ", ";
  5188. }
  5189. }
  5190. Coutput << "}" << endl;
  5191. }
  5192. else
  5193. {
  5194. Coutput << entry -> class_name << " " ;
  5195. unsigned j;
  5196. Coutput << "{";
  5197. if (entry -> interfaces)
  5198. {
  5199. for (j = 0; j < entry -> interfaces -> size(); j++)
  5200. {
  5201. unsigned end = entry -> interfaces -> size() - 1;
  5202. Coutput << (*(entry -> interfaces))[j];
  5203. if (j < end)
  5204. Coutput << ", ";
  5205. }
  5206. }
  5207. Coutput << "} " << endl;
  5208. }
  5209. Coutput << entry -> package_name << endl << entry -> file_name << endl;
  5210. }
  5211. }
  5212. void AssocTable::dumpTable()
  5213. {
  5214. Coutput << L"Association Table" << endl;
  5215. unsigned i;
  5216. for (i = 0; i < table -> size(); i++)
  5217. {
  5218. Assoc* entry = (*table)[i];
  5219. Coutput << entry -> class_name << " --> "
  5220. << entry -> type;
  5221. Coutput << " (by ";
  5222. switch(entry -> kind)
  5223. {
  5224. case Assoc::CF:
  5225. if (entry -> mode == Assoc::PRIVATE)
  5226. Coutput << L"private class member " << entry -> name << ")";
  5227. else if (entry -> mode == Assoc::PROTECTED)
  5228. Coutput << L"protected class member " << entry -> name << ")";
  5229. else
  5230. Coutput << L"public class member " << entry -> name << ")";
  5231. break;
  5232. case Assoc::IM:
  5233. Coutput << L"instance member " << entry -> name << ")";
  5234. break;
  5235. case Assoc::MP:
  5236. Coutput << L"parameter " << entry -> name << L" in " << entry -> method_name << "(...))";
  5237. break;
  5238. case Assoc::OC:
  5239. break;
  5240. case Assoc::MR:
  5241. if (entry -> mode == Assoc::PRIVATE)
  5242. Coutput << L"return type in private instance method " << entry -> method_name << "(...))";
  5243. else if (entry -> mode == Assoc::PROTECTED)
  5244. Coutput << L"return type in protected instance method " << entry -> method_name << "(...))";
  5245. else
  5246. Coutput << L"return type in public instance method " << entry -> method_name << "(...))";
  5247. break;
  5248. case Assoc::CM:
  5249. if (entry -> mode == Assoc::PRIVATE)
  5250. Coutput << L"return type in private static method " << entry -> method_name << "(...))";
  5251. else if (entry -> mode == Assoc::PROTECTED)
  5252. Coutput << L"return type in protected static method " << entry -> method_name << "(...))";
  5253. else
  5254. Coutput << L"return type in public static method " << entry -> method_name << "(...))";
  5255. break;
  5256. default:
  5257. break;
  5258. }
  5259. Coutput << endl;
  5260. }
  5261. Coutput << endl;
  5262. }
  5263. void Statechart::Print()
  5264. {
  5265. unsigned i;
  5266. for (i = 0; i < statechart -> size(); i++)
  5267. {
  5268. switch((*statechart)[i] -> kind)
  5269. {
  5270. case State::GET:
  5271. Coutput << "GET state.";
  5272. break;
  5273. case State::SET:
  5274. Coutput << "SET state.";
  5275. break;
  5276. case State::CREATE:
  5277. Coutput << "CREATE state.";
  5278. break;
  5279. case State::RETURN:
  5280. Coutput << "RETURN state.";
  5281. break;
  5282. case State::CONDITION:
  5283. Coutput << "CONDITION state.";
  5284. break;
  5285. default:
  5286. break;
  5287. }
  5288. Coutput << endl;
  5289. if ((*statechart)[i] -> kind != State::RETURN)
  5290. {
  5291. unsigned j;
  5292. for (j = 0; j < (*statechart)[i] -> participants -> size(); j++)
  5293. Coutput << " " << (*(*statechart)[i] -> participants)[j];
  5294. Coutput << endl;
  5295. }
  5296. }
  5297. }
  5298. /***
  5299. *
  5300. * Flatten data structure
  5301. *
  5302. */
  5303. void Flatten::BuildSummary()
  5304. {
  5305. visit(method->declaration->MethodDeclarationCast()->method_body_opt);
  5306. for(unsigned i = 0; i < summary.size(); i++)
  5307. {
  5308. set<signed>::iterator p;
  5309. for (p = (summary[i]->next).begin(); p != (summary[i]->next).end(); p++)
  5310. (summary[*p]->previous).insert(i);
  5311. }
  5312. }
  5313. bool Flatten::Compare(AstExpression *b1, AstExpression *b2)
  5314. {
  5315. if (b1->symbol && (b1->symbol == b2->symbol))
  5316. return true;
  5317. else if (b1->kind == b2->kind)
  5318. {
  5319. if (b1->kind == Ast::BINARY)
  5320. {
  5321. return (Compare(b1->BinaryExpressionCast()->left_expression, b2->BinaryExpressionCast()->left_expression)
  5322. && Compare(b1->BinaryExpressionCast()->right_expression, b2->BinaryExpressionCast()->right_expression));
  5323. }
  5324. else if (b1->kind == Ast::PRE_UNARY)
  5325. {
  5326. return Compare(b1->PreUnaryExpressionCast()->expression, b2->PreUnaryExpressionCast()->expression);
  5327. }
  5328. }
  5329. return false;
  5330. }
  5331. void Flatten::FlattenBoolean(vector<AstExpression*>& list, AstExpression *expression)
  5332. {
  5333. if (expression)
  5334. {
  5335. if (!expression->conjoint)
  5336. list.push_back(expression);
  5337. else
  5338. {
  5339. list.push_back(expression->BinaryExpressionCast()->right_expression);
  5340. FlattenBoolean(list, expression->BinaryExpressionCast()->left_expression);
  5341. }
  5342. }
  5343. }
  5344. Flatten::TransitionTag Flatten::TransitionFlow(AstExpression *b1, AstExpression *b2)
  5345. {
  5346. if (!b1 && !b2)
  5347. return UNCONDITIONAL;
  5348. else if (!b1 && b2)
  5349. return UNCONDITIONAL;
  5350. else if (b1 && !b2)
  5351. return CONDITIONAL;
  5352. else if (Compare(b1, b2))
  5353. return UNCONDITIONAL;
  5354. else
  5355. {
  5356. // pre and post are both not null
  5357. vector<AstExpression*> v1, v2;
  5358. FlattenBoolean(v1, b1);
  5359. FlattenBoolean(v2, b2);
  5360. for (unsigned i = 0; i < v1.size(); i++)
  5361. {
  5362. bool neg1 = ((v1[i]->kind == Ast::PRE_UNARY) && (v1[i]->PreUnaryExpressionCast()->Tag() == AstPreUnaryExpression::NOT));
  5363. AstExpression *expr1 = (neg1) ? v1[i]->PreUnaryExpressionCast()->expression : v1[i];
  5364. for (unsigned j = 0; j < v2.size(); j++)
  5365. {
  5366. bool neg2 = ((v2[j]->kind == Ast::PRE_UNARY) && (v2[j]->PreUnaryExpressionCast()->Tag() == AstPreUnaryExpression::NOT));
  5367. AstExpression *expr2 = (neg2) ? v2[j]->PreUnaryExpressionCast()->expression : v2[j];
  5368. if (Compare(expr1, expr2))
  5369. {
  5370. if ((neg1 && !neg2) || (!neg1 && neg2))
  5371. return NOTRANSITION;
  5372. }
  5373. }
  5374. }
  5375. return CONDITIONAL;
  5376. }
  5377. }
  5378. void Flatten::PushCondition(AstExpression *expression)
  5379. {
  5380. if (!condition)
  5381. condition = expression;
  5382. else
  5383. {
  5384. AstExpression *temp = condition;
  5385. condition = ast_pool->NewBinaryExpression(AstBinaryExpression::AND_AND);
  5386. condition->conjoint = true;
  5387. condition->BinaryExpressionCast()->left_expression = temp;
  5388. condition->BinaryExpressionCast()->right_expression = expression;
  5389. }
  5390. }
  5391. void Flatten::PopCondition()
  5392. {
  5393. if (condition)
  5394. {
  5395. if (condition->conjoint)
  5396. {
  5397. if (condition->kind == Ast::BINARY)
  5398. {
  5399. AstExpression *temp = condition->BinaryExpressionCast()->right_expression;
  5400. if (temp->kind == Ast::PRE_UNARY)
  5401. {
  5402. condition->BinaryExpressionCast()->right_expression = temp->PreUnaryExpressionCast()->expression;
  5403. }
  5404. else
  5405. {
  5406. condition->BinaryExpressionCast()->right_expression = ast_pool->NewPreUnaryExpression(AstPreUnaryExpression::NOT);
  5407. condition->BinaryExpressionCast()->right_expression->conjoint = true;
  5408. condition->BinaryExpressionCast()->right_expression->PreUnaryExpressionCast()->expression = temp;
  5409. }
  5410. }
  5411. }
  5412. else
  5413. {
  5414. AstExpression *temp = condition;
  5415. condition = ast_pool->NewPreUnaryExpression(AstPreUnaryExpression::NOT);
  5416. condition->conjoint = true;
  5417. condition->PreUnaryExpressionCast()->expression = temp;
  5418. }
  5419. }
  5420. }
  5421. void Flatten::visit(AstBlock* block)
  5422. {
  5423. if (block->NumStatements())
  5424. {
  5425. unsigned lstmt = (block->NumStatements() == 1) ? 0 : (block->NumStatements() - 1);
  5426. for (unsigned i = 0; i < lstmt; i++)
  5427. visit(block -> Statement(i));
  5428. visit(block->Statement(lstmt));
  5429. UpdateSummary();
  5430. }
  5431. }
  5432. void Flatten::visit(AstWhileStatement* while_statement)
  5433. {
  5434. UpdateSummary();
  5435. if (summary.size())
  5436. {
  5437. pred.clear();
  5438. pred.insert(summary.size()-1);
  5439. }
  5440. PushCondition(while_statement->expression);
  5441. visit(while_statement->statement);
  5442. UpdateSummary();
  5443. pred.insert(summary.size()-1);
  5444. PopCondition();
  5445. }
  5446. void Flatten::visit(AstForStatement* for_statement)
  5447. {
  5448. UpdateSummary();
  5449. PushCondition(for_statement->end_expression_opt);
  5450. visit(for_statement->statement);
  5451. UpdateSummary();
  5452. PopCondition();
  5453. }
  5454. void Flatten::visit(AstTryStatement *try_statement)
  5455. {
  5456. visit(try_statement->block);
  5457. }
  5458. void Flatten::visit(AstSynchronizedStatement* synch_statement)
  5459. {
  5460. visit(synch_statement->block);
  5461. }
  5462. void Flatten::visit(AstStatement *statement)
  5463. {
  5464. switch(statement -> kind)
  5465. {
  5466. case Ast::IF:
  5467. visit(statement -> IfStatementCast());
  5468. break;
  5469. case Ast::WHILE:
  5470. visit(statement -> WhileStatementCast());
  5471. break;
  5472. case Ast::FOR:
  5473. visit(statement -> ForStatementCast());
  5474. break;
  5475. case Ast::TRY:
  5476. visit(statement -> TryStatementCast());
  5477. break;
  5478. case Ast::EXPRESSION_STATEMENT:
  5479. visit(statement -> ExpressionStatementCast() -> expression);
  5480. break;
  5481. case Ast::SYNCHRONIZED_STATEMENT:
  5482. visit(statement -> SynchronizedStatementCast());
  5483. break;
  5484. case Ast::BLOCK:
  5485. visit(statement -> BlockCast());
  5486. break;
  5487. case Ast::RETURN:
  5488. visit(statement -> ReturnStatementCast());
  5489. break;
  5490. case Ast::LOCAL_VARIABLE_DECLARATION:
  5491. visit(statement -> LocalVariableStatementCast());
  5492. break;
  5493. default:
  5494. statements.push_back(statement);
  5495. break;
  5496. }
  5497. }
  5498. void Flatten::visit(AstExpression *expression)
  5499. {
  5500. switch(expression -> kind)
  5501. {
  5502. case Ast::PARENTHESIZED_EXPRESSION:
  5503. visit(expression->ParenthesizedExpressionCast() -> expression);
  5504. break;
  5505. case Ast::CAST:
  5506. visit(expression->CastExpressionCast() -> expression);
  5507. break;
  5508. case Ast::CONDITIONAL:
  5509. statements.push_back(expression);
  5510. //visit(expression->ConditionalExpressionCast());
  5511. break;
  5512. case Ast::ASSIGNMENT:
  5513. visit(expression->AssignmentExpressionCast());
  5514. break;
  5515. case Ast::CALL:
  5516. visit(expression->MethodInvocationCast());
  5517. break;
  5518. default:
  5519. statements.push_back(expression);
  5520. break;
  5521. }
  5522. }
  5523. void visit(AstConditionalExpression *cond_expression)
  5524. {
  5525. // TODO: should add conditional BLOCK statements
  5526. }
  5527. void Flatten::visit(AstMethodInvocation* call)
  5528. {
  5529. // might want to check all participants in this method invocation
  5530. // e.g., base_opt, call->symbol->MethodCast()>Type(), call->arguments->Argument(i), etc
  5531. if ((strcmp(call->symbol->MethodCast()->containing_type->fully_qualified_name->value, "java/security/AccessController") == 0)
  5532. && (strcmp(call->symbol->MethodCast()->SignatureString(), "(Ljava/security/PrivilegedAction;)Ljava/lang/Object;") == 0))
  5533. {
  5534. AstClassCreationExpression *class_creation = Utility::RemoveCasting(call->arguments->Argument(0))->ClassCreationExpressionCast();
  5535. visit(class_creation->symbol->TypeCast()->MethodSym(1)->declaration->MethodDeclarationCast()->method_body_opt);
  5536. }
  5537. else
  5538. statements.push_back(call);
  5539. }
  5540. void Flatten::visit(AstIfStatement* statement)
  5541. {
  5542. UpdateSummary();
  5543. if (summary.size())
  5544. {
  5545. pred.clear();
  5546. pred.insert(summary.size()-1);
  5547. }
  5548. set<signed> pred2(pred);
  5549. AstExpression *top = condition;
  5550. PushCondition(statement->expression);
  5551. //visit(statement->expression);
  5552. visit(statement->true_statement);
  5553. UpdateSummary();
  5554. if (statement->false_statement_opt)
  5555. {
  5556. pred.swap(pred2);
  5557. condition = top;
  5558. AstExpression *else_condition = ast_pool->NewPreUnaryExpression(AstPreUnaryExpression::NOT);
  5559. else_condition->PreUnaryExpressionCast()->expression = statement->expression;
  5560. PushCondition(else_condition);
  5561. visit(statement->false_statement_opt);
  5562. UpdateSummary();
  5563. pred.clear();
  5564. pred.insert(summary.size() - 2); // last block for the true branch
  5565. pred.insert(summary.size() - 1); // last block for the false branch
  5566. condition = top;
  5567. }
  5568. else
  5569. {
  5570. if ((*summary[summary.size() - 1]->statements)[summary[summary.size() - 1]->statements->size() - 1]->kind != Ast::RETURN)
  5571. pred.insert(summary.size() - 1);
  5572. // pred <<Union>> pred2
  5573. set<signed>::iterator p;
  5574. for (p = pred2.begin(); p != pred2.end(); p++)
  5575. pred.insert(*p);
  5576. condition = top;
  5577. AstExpression *else_condition = ast_pool->NewPreUnaryExpression(AstPreUnaryExpression::NOT);
  5578. else_condition->PreUnaryExpressionCast()->expression = statement->expression;
  5579. PushCondition(else_condition);
  5580. }
  5581. }
  5582. void Flatten::visit(AstAssignmentExpression *expression)
  5583. {
  5584. statements.push_back(expression);
  5585. // TODO also check for aliasing
  5586. }
  5587. void Flatten::visit(AstLocalVariableStatement* local_var)
  5588. {
  5589. for (unsigned i=0; i < local_var->NumVariableDeclarators(); i++)
  5590. visit(local_var->VariableDeclarator(i));
  5591. }
  5592. void Flatten::visit(AstVariableDeclarator* var_declarator)
  5593. {
  5594. statements.push_back(var_declarator);
  5595. }
  5596. void Flatten::visit(AstReturnStatement* statement)
  5597. {
  5598. statements.push_back(statement);
  5599. capture_trace = true;
  5600. }
  5601. void Flatten::UpdateSummary()
  5602. {
  5603. if (statements.size())
  5604. {
  5605. Snapshot *snapshot = new Snapshot();
  5606. snapshot->statements = new vector<Ast*>(statements);
  5607. statements.clear();
  5608. if (condition)
  5609. {
  5610. snapshot->condition = condition->Clone(ast_pool)->ExpressionCast();
  5611. }
  5612. snapshot->index = summary.size();
  5613. set<signed>::iterator p;
  5614. for(p = pred.begin(); p != pred.end(); p++)
  5615. {
  5616. if (*p >= 0)
  5617. (summary[*p]->next).insert(snapshot->index);
  5618. else
  5619. (snapshot->previous).insert(-1);
  5620. }
  5621. summary.push_back(snapshot);
  5622. if (capture_trace)
  5623. {
  5624. traces.push_back(snapshot);
  5625. capture_trace = false;
  5626. }
  5627. }
  5628. }
  5629. void Flatten::DumpSummary()
  5630. {
  5631. Coutput << method->Utf8Name() << endl;
  5632. for (unsigned i = 0; i < summary.size(); i++)
  5633. {
  5634. Snapshot *snapshot = summary[i];
  5635. Coutput << "Snapshot[" << snapshot->index << "]" << endl;
  5636. set<signed>::iterator p;
  5637. //incoming edges
  5638. Coutput << "In-coming snapshots: ";
  5639. for (p = (snapshot->previous).begin(); p != (snapshot->previous).end(); p++)
  5640. Coutput << *p << " ";
  5641. Coutput << endl;
  5642. // outgoiong edges
  5643. Coutput << "Out-going snapshots: ";
  5644. for (p = (snapshot->next).begin(); p != (snapshot->next).end(); p++)
  5645. Coutput << *p << " ";
  5646. Coutput << endl;
  5647. Coutput << "STATEMENTS:" << endl;
  5648. unsigned j;
  5649. for (j = 0; j < snapshot->statements->size(); j++)
  5650. {
  5651. Coutput << "---Statement[" << j << "]---" << endl;
  5652. (*snapshot->statements)[j]->Print();
  5653. }
  5654. Coutput << "CONDITIONS:" << endl;
  5655. if (snapshot->condition)
  5656. snapshot->condition->Print();
  5657. Coutput << endl;
  5658. }
  5659. }
  5660. Control::Control(char** arguments, Option& option_)
  5661. : return_code(0)
  5662. , option(option_)
  5663. , dot_classpath_index(0)
  5664. , system_table(NULL)
  5665. , system_semantic(NULL)
  5666. , semantic(1024)
  5667. , needs_body_work(1024)
  5668. , type_trash_bin(1024)
  5669. , input_java_file_set(1021)
  5670. , input_class_file_set(1021)
  5671. , expired_file_set()
  5672. , recompilation_file_set(1021)
  5673. // Type and method cache. These variables are assigned in control.h
  5674. // accessors, but must be NULL at startup.
  5675. , Annotation_type(NULL)
  5676. , AssertionError_type(NULL)
  5677. , AssertionError_Init_method(NULL)
  5678. , AssertionError_InitWithChar_method(NULL)
  5679. , AssertionError_InitWithBoolean_method(NULL)
  5680. , AssertionError_InitWithInt_method(NULL)
  5681. , AssertionError_InitWithLong_method(NULL)
  5682. , AssertionError_InitWithFloat_method(NULL)
  5683. , AssertionError_InitWithDouble_method(NULL)
  5684. , AssertionError_InitWithObject_method(NULL)
  5685. , Boolean_type(NULL)
  5686. , Boolean_TYPE_field(NULL)
  5687. , Byte_type(NULL)
  5688. , Byte_TYPE_field(NULL)
  5689. , Character_type(NULL)
  5690. , Character_TYPE_field(NULL)
  5691. , Class_type(NULL)
  5692. , Class_forName_method(NULL)
  5693. , Class_getComponentType_method(NULL)
  5694. , Class_desiredAssertionStatus_method(NULL)
  5695. , ClassNotFoundException_type(NULL)
  5696. , Cloneable_type(NULL)
  5697. , Comparable_type(NULL)
  5698. , Double_type(NULL)
  5699. , Double_TYPE_field(NULL)
  5700. , ElementType_type(NULL)
  5701. , ElementType_TYPE_field(NULL)
  5702. , ElementType_FIELD_field(NULL)
  5703. , ElementType_METHOD_field(NULL)
  5704. , ElementType_PARAMETER_field(NULL)
  5705. , ElementType_CONSTRUCTOR_field(NULL)
  5706. , ElementType_LOCAL_VARIABLE_field(NULL)
  5707. , ElementType_ANNOTATION_TYPE_field(NULL)
  5708. , ElementType_PACKAGE_field(NULL)
  5709. , Enum_type(NULL)
  5710. , Enum_Init_method(NULL)
  5711. , Enum_ordinal_method(NULL)
  5712. , Enum_valueOf_method(NULL)
  5713. , Error_type(NULL)
  5714. , Exception_type(NULL)
  5715. , Float_type(NULL)
  5716. , Float_TYPE_field(NULL)
  5717. , Integer_type(NULL)
  5718. , Integer_TYPE_field(NULL)
  5719. , Iterable_type(NULL)
  5720. , Iterable_iterator_method(NULL)
  5721. , Iterator_type(NULL)
  5722. , Iterator_hasNext_method(NULL)
  5723. , Iterator_next_method(NULL)
  5724. , Long_type(NULL)
  5725. , Long_TYPE_field(NULL)
  5726. , NoClassDefFoundError_type(NULL)
  5727. , NoClassDefFoundError_Init_method(NULL)
  5728. , NoClassDefFoundError_InitString_method(NULL)
  5729. , Object_type(NULL)
  5730. , Object_getClass_method(NULL)
  5731. , Overrides_type(NULL)
  5732. , Retention_type(NULL)
  5733. , RetentionPolicy_type(NULL)
  5734. , RetentionPolicy_SOURCE_field(NULL)
  5735. , RetentionPolicy_CLASS_field(NULL)
  5736. , RetentionPolicy_RUNTIME_field(NULL)
  5737. , RuntimeException_type(NULL)
  5738. , Serializable_type(NULL)
  5739. , Short_type(NULL)
  5740. , Short_TYPE_field(NULL)
  5741. , String_type(NULL)
  5742. , StringBuffer_type(NULL)
  5743. , StringBuffer_Init_method(NULL)
  5744. , StringBuffer_InitWithString_method(NULL)
  5745. , StringBuffer_toString_method(NULL)
  5746. , StringBuffer_append_char_method(NULL)
  5747. , StringBuffer_append_boolean_method(NULL)
  5748. , StringBuffer_append_int_method(NULL)
  5749. , StringBuffer_append_long_method(NULL)
  5750. , StringBuffer_append_float_method(NULL)
  5751. , StringBuffer_append_double_method(NULL)
  5752. , StringBuffer_append_string_method(NULL)
  5753. , StringBuffer_append_object_method(NULL)
  5754. , StringBuilder_type(NULL)
  5755. , StringBuilder_Init_method(NULL)
  5756. , StringBuilder_InitWithString_method(NULL)
  5757. , StringBuilder_toString_method(NULL)
  5758. , StringBuilder_append_char_method(NULL)
  5759. , StringBuilder_append_boolean_method(NULL)
  5760. , StringBuilder_append_int_method(NULL)
  5761. , StringBuilder_append_long_method(NULL)
  5762. , StringBuilder_append_float_method(NULL)
  5763. , StringBuilder_append_double_method(NULL)
  5764. , StringBuilder_append_string_method(NULL)
  5765. , StringBuilder_append_object_method(NULL)
  5766. , Target_type(NULL)
  5767. , Throwable_type(NULL)
  5768. , Throwable_getMessage_method(NULL)
  5769. , Throwable_initCause_method(NULL)
  5770. , Void_type(NULL)
  5771. , Void_TYPE_field(NULL)
  5772. // storage for all literals seen in source
  5773. , int_pool(&bad_value)
  5774. , long_pool(&bad_value)
  5775. , float_pool(&bad_value)
  5776. , double_pool(&bad_value)
  5777. , Utf8_pool(&bad_value)
  5778. #ifdef JIKES_DEBUG
  5779. , input_files_processed(0)
  5780. , class_files_read(0)
  5781. , class_files_written(0)
  5782. , line_count(0)
  5783. #endif // JIKES_DEBUG
  5784. // Package cache. unnamed and lang are initialized in constructor body.
  5785. , annotation_package(NULL)
  5786. , io_package(NULL)
  5787. , util_package(NULL)
  5788. {
  5789. PINOT_DEBUG = (getenv("PINOT_DEBUG")) ? true : false;
  5790. option.bytecode = false;
  5791. // breakpoint 0.
  5792. // getchar();
  5793. r_table = new ReadAccessTable();
  5794. w_table = new WriteAccessTable();
  5795. d_table = new DelegationTable();
  5796. cs_table = new ClassSymbolTable();
  5797. ms_table = new MethodSymbolTable();
  5798. nSingleton = nCoR = nBridge = nStrategy = nState = nFlyweight = nComposite = nMediator = nTemplate = nFactoryMethod = nAbstractFactory = nVisitor = nDecorator = nObserver = nProxy = nAdapter = nFacade = 0;
  5799. mb_table = new MethodBodyTable();
  5800. gen_table = new GenTable();
  5801. assoc_table = new AssocTable();
  5802. counter1 = 0;
  5803. counter2 = 0;
  5804. counter3 = 0;
  5805. ProcessGlobals();
  5806. ProcessUnnamedPackage();
  5807. ProcessPath();
  5808. ProcessSystemInformation();
  5809. //
  5810. // Instantiate a scanner and a parser and initialize the static members
  5811. // for the semantic processors.
  5812. //
  5813. scanner = new Scanner(*this);
  5814. parser = new Parser();
  5815. SemanticError::StaticInitializer();
  5816. //
  5817. // Process all file names specified in command line
  5818. //
  5819. ProcessNewInputFiles(input_java_file_set, arguments);
  5820. //
  5821. // For each input file, copy it into the input_files array and process
  5822. // its package declaration. Estimate we need 64 tokens.
  5823. //
  5824. StoragePool* ast_pool = new StoragePool(64);
  5825. FileSymbol** input_files = new FileSymbol*[input_java_file_set.Size() + 1];
  5826. int num_files = 0;
  5827. FileSymbol* file_symbol;
  5828. for (file_symbol = (FileSymbol*) input_java_file_set.FirstElement();
  5829. file_symbol;
  5830. file_symbol = (FileSymbol*) input_java_file_set.NextElement())
  5831. {
  5832. input_files[num_files++] = file_symbol;
  5833. //Coutput << file_symbol->FileName() << endl;
  5834. #ifdef JIKES_DEBUG
  5835. input_files_processed++;
  5836. #endif
  5837. errno = 0;
  5838. scanner -> Scan(file_symbol);
  5839. if (file_symbol -> lex_stream) // did we have a successful scan!
  5840. {
  5841. AstPackageDeclaration* package_declaration =
  5842. parser -> PackageHeaderParse(file_symbol -> lex_stream,
  5843. ast_pool);
  5844. ProcessPackageDeclaration(file_symbol, package_declaration);
  5845. ast_pool -> Reset();
  5846. }
  5847. else
  5848. {
  5849. const char* std_err = strerror(errno);
  5850. ErrorString err_str;
  5851. err_str << '"' << std_err << '"' << " while trying to open "
  5852. << file_symbol -> FileName();
  5853. general_io_errors.Next() = err_str.SafeArray();
  5854. }
  5855. }
  5856. //
  5857. //
  5858. //
  5859. FileSymbol* main_file_clone;
  5860. if (num_files > 0)
  5861. main_file_clone = input_files[0] -> Clone();
  5862. else
  5863. {
  5864. //
  5865. // Some name, any name !!! We use dot_name_symbol as a bad file name
  5866. // because no file can be named ".".
  5867. //
  5868. FileSymbol* file_symbol = classpath[dot_classpath_index] ->
  5869. RootDirectory() -> InsertFileSymbol(dot_name_symbol);
  5870. file_symbol -> directory_symbol = classpath[dot_classpath_index] ->
  5871. RootDirectory();
  5872. file_symbol -> SetJava();
  5873. main_file_clone = file_symbol -> Clone();
  5874. }
  5875. main_file_clone -> semantic = new Semantic(*this, main_file_clone);
  5876. system_semantic = main_file_clone -> semantic;
  5877. scanner -> SetUp(main_file_clone);
  5878. #ifdef WIN32_FILE_SYSTEM
  5879. //
  5880. //
  5881. //
  5882. if (option.BadMainDisk())
  5883. {
  5884. system_semantic -> ReportSemError(SemanticError::NO_CURRENT_DIRECTORY,
  5885. BAD_TOKEN);
  5886. }
  5887. #endif // WIN32_FILE_SYSTEM
  5888. unsigned i;
  5889. for (i = 0; i < bad_dirnames.Length(); i++)
  5890. {
  5891. system_semantic ->
  5892. ReportSemError(SemanticError::CANNOT_OPEN_PATH_DIRECTORY,
  5893. BAD_TOKEN, bad_dirnames[i]);
  5894. }
  5895. for (i = 0; i < bad_zip_filenames.Length(); i++)
  5896. {
  5897. system_semantic -> ReportSemError(SemanticError::CANNOT_OPEN_ZIP_FILE,
  5898. BAD_TOKEN, bad_zip_filenames[i]);
  5899. }
  5900. for (i = 0; i < general_io_warnings.Length(); i++)
  5901. {
  5902. system_semantic -> ReportSemError(SemanticError::IO_WARNING, BAD_TOKEN,
  5903. general_io_warnings[i]);
  5904. delete [] general_io_warnings[i];
  5905. }
  5906. for (i = 0; i < general_io_errors.Length(); i++)
  5907. {
  5908. system_semantic -> ReportSemError(SemanticError::IO_ERROR, BAD_TOKEN,
  5909. general_io_errors[i]);
  5910. delete [] general_io_errors[i];
  5911. }
  5912. //
  5913. // Require the existence of java.lang.
  5914. //
  5915. if (lang_package -> directory.Length() == 0)
  5916. {
  5917. system_semantic -> ReportSemError(SemanticError::PACKAGE_NOT_FOUND,
  5918. BAD_TOKEN,
  5919. StringConstant::US_java_SL_lang);
  5920. }
  5921. //
  5922. // When the -d option is specified, create the relevant
  5923. // directories if they don't already exist.
  5924. //
  5925. if (option.directory)
  5926. {
  5927. if (! SystemIsDirectory(option.directory))
  5928. {
  5929. for (char* ptr = option.directory; *ptr; ptr++)
  5930. {
  5931. char delimiter = *ptr;
  5932. if (delimiter == U_SLASH)
  5933. {
  5934. *ptr = U_NULL;
  5935. if (! SystemIsDirectory(option.directory))
  5936. SystemMkdir(option.directory);
  5937. *ptr = delimiter;
  5938. }
  5939. }
  5940. SystemMkdir(option.directory);
  5941. if (! SystemIsDirectory(option.directory))
  5942. {
  5943. int length = strlen(option.directory);
  5944. wchar_t* name = new wchar_t[length + 1];
  5945. for (int j = 0; j < length; j++)
  5946. name[j] = option.directory[j];
  5947. name[length] = U_NULL;
  5948. system_semantic -> ReportSemError(SemanticError::CANNOT_OPEN_DIRECTORY,
  5949. BAD_TOKEN, name);
  5950. delete [] name;
  5951. }
  5952. }
  5953. }
  5954. //
  5955. //
  5956. //
  5957. for (i = 0; i < bad_input_filenames.Length(); i++)
  5958. {
  5959. system_semantic -> ReportSemError(SemanticError::BAD_INPUT_FILE,
  5960. BAD_TOKEN, bad_input_filenames[i]);
  5961. }
  5962. //
  5963. //
  5964. //
  5965. for (i = 0; i < unreadable_input_filenames.Length(); i++)
  5966. {
  5967. system_semantic -> ReportSemError(SemanticError::UNREADABLE_INPUT_FILE,
  5968. BAD_TOKEN,
  5969. unreadable_input_filenames[i]);
  5970. }
  5971. //
  5972. //
  5973. //
  5974. if (system_semantic -> NumErrors() > 0)
  5975. {
  5976. system_semantic -> PrintMessages();
  5977. return_code = system_semantic -> return_code;
  5978. }
  5979. else
  5980. {
  5981. //
  5982. // There might be some warnings we want to print.
  5983. //
  5984. system_semantic -> PrintMessages();
  5985. input_java_file_set.SetEmpty();
  5986. for (int j = 0; j < num_files; j++)
  5987. {
  5988. FileSymbol* file_symbol = input_files[j];
  5989. if (! input_java_file_set.IsElement(file_symbol))
  5990. ProcessFile(file_symbol, ast_pool);
  5991. }
  5992. // mb_table -> dumpTable();
  5993. // gen_table -> dumpTable();
  5994. // assoc_table -> dumpTable();
  5995. // d_table -> DumpTable();
  5996. //FindPrototype(mb_table, gen_table, assoc_table);
  5997. // breakpoint 1.
  5998. // getchar();
  5999. // Coutput << "breakpoint 1." << endl;
  6000. d_table->ConcretizeDelegations();
  6001. ms_table->ExpandCallDependents();
  6002. cs_table->ExpandSubtypes();
  6003. // breakpoint 2.
  6004. // getchar();
  6005. Coutput << endl;
  6006. Coutput << "--------- Original GoF Patterns ----------" << endl << endl;
  6007. //FindSingleton(cs_table, ms_table);
  6008. FindSingleton1(cs_table, ast_pool);
  6009. FindChainOfResponsibility(cs_table, ms_table, d_table, ast_pool);
  6010. FindBridge(cs_table, d_table);
  6011. FindStrategy1(cs_table, d_table, w_table, r_table, ms_table);
  6012. //FindFlyweight(mb_table, gen_table, assoc_table);
  6013. FindFlyweight1(ms_table);
  6014. FindFlyweight2(cs_table, w_table, r_table);
  6015. FindComposite(cs_table, d_table);
  6016. //FindMediator(cs_table, d_table);
  6017. FindTemplateMethod(d_table);
  6018. FindFactory(cs_table, ms_table, ast_pool);
  6019. FindVisitor(cs_table, ms_table);
  6020. FindObserver(cs_table, d_table);
  6021. FindMediator2(cs_table);
  6022. FindProxy(cs_table, d_table);
  6023. FindAdapter(cs_table);
  6024. FindFacade(cs_table);
  6025. // FindThreadSafeInterface(d_table);
  6026. #ifdef PLUGIN_ENABLED
  6027. Coutput << endl;
  6028. Coutput << "--------- User-defined Patterns ----------" << endl<< endl;
  6029. void *handle = dlopen("/home/madonna/sandbox/pinot/src/plugins.dll", RTLD_LAZY);
  6030. if (!handle)
  6031. {
  6032. printf("Error during dlopen(): %s\n", dlerror());
  6033. exit(1);
  6034. }
  6035. void (*pattern)(DelegationTable*);
  6036. pattern = (void (*)(DelegationTable*))dlsym(handle, "FindTemplateMethod");
  6037. if (!pattern)
  6038. {
  6039. printf("Error locating 'FindTemplateMethod' - %s\n", dlerror());
  6040. exit(1);
  6041. }
  6042. (*pattern)(d_table);
  6043. #endif
  6044. // Print Statics
  6045. Coutput << endl << "------------------------------------------" << endl << endl;
  6046. Coutput << "Pattern Instance Statistics:" << endl << endl;
  6047. Coutput << "Creational Patterns" << endl;
  6048. Coutput << "==============================" << endl;
  6049. Coutput << "Abstract Factory";
  6050. Coutput.width(30 - sizeof("Abstract Factory"));
  6051. Coutput << nAbstractFactory << endl;
  6052. Coutput << "Factory Method";
  6053. Coutput.width(30 - sizeof("Factory Method"));
  6054. Coutput << nFactoryMethod<< endl;
  6055. Coutput << "Singleton";
  6056. Coutput.width(30 - sizeof("Singleton"));
  6057. Coutput << nSingleton << endl;
  6058. Coutput << "------------------------------" << endl;
  6059. Coutput << "Structural Patterns" << endl;
  6060. Coutput << "==============================" << endl;
  6061. Coutput << "Adapter";
  6062. Coutput.width(30 - sizeof("Adapter"));
  6063. Coutput << nAdapter << endl;
  6064. Coutput << "Bridge";
  6065. Coutput.width(30 - sizeof("Bridge"));
  6066. Coutput << nBridge<< endl;
  6067. Coutput << "Composite";
  6068. Coutput.width(30 - sizeof("Composite"));
  6069. Coutput << nComposite << endl;
  6070. Coutput << "Decorator";
  6071. Coutput.width(30 - sizeof("Decorator"));
  6072. Coutput << nDecorator << endl;
  6073. Coutput << "Facade";
  6074. Coutput.width(30 - sizeof("Facade"));
  6075. Coutput << nFacade << endl;
  6076. Coutput << "Flyweight";
  6077. Coutput.width(30 - sizeof("Flyweight"));
  6078. Coutput << nFlyweight << endl;
  6079. Coutput << "Proxy";
  6080. Coutput.width(30 - sizeof("Proxy"));
  6081. Coutput << nProxy << endl;
  6082. Coutput << "------------------------------" << endl;
  6083. Coutput << "Behavioral Patterns" << endl;
  6084. Coutput << "==============================" << endl;
  6085. Coutput << "Chain of Responsibility";
  6086. Coutput.width(30 - sizeof("Chain of Responsibility"));
  6087. Coutput << nCoR<< endl;
  6088. Coutput << "Mediator";
  6089. Coutput.width(30 - sizeof("Mediator"));
  6090. Coutput << nMediator << endl;
  6091. Coutput << "Observer";
  6092. Coutput.width(30 - sizeof("Observer"));
  6093. Coutput << nObserver << endl;
  6094. Coutput << "State";
  6095. Coutput.width(30 - sizeof("State"));
  6096. Coutput << nState << endl;
  6097. Coutput << "Strategy";
  6098. Coutput.width(30 - sizeof("Strategy"));
  6099. Coutput << nStrategy<< endl;
  6100. Coutput << "Template Method";
  6101. Coutput.width(30 - sizeof("Template Method"));
  6102. Coutput << nTemplate << endl;
  6103. Coutput << "Visitor";
  6104. Coutput.width(30 - sizeof("Visitor"));
  6105. Coutput << nVisitor << endl;
  6106. Coutput << "------------------------------" << endl;
  6107. Coutput << endl;
  6108. Coutput << "Number of classes processed: " << gen_table -> getSize() << endl;
  6109. Coutput << "Number of files processed: " << num_files << endl;
  6110. Coutput << "Size of DelegationTable: " << d_table -> size() << endl;
  6111. Coutput << "Size of concrete class nodes: " << cs_table -> ConcreteClasses() << endl;
  6112. Coutput << "Size of undirected invocation edges: " << d_table -> UniqueDirectedCalls () << endl;
  6113. Coutput << endl << endl;
  6114. Coutput << "nMediatorFacadeDual/nMediator = " << nMediatorFacadeDual << "/" << nMediator << endl;
  6115. Coutput << "nImmutable/nFlyweight = " << nImmutable << "/" << nFlyweight << endl;
  6116. Coutput << "nFlyweightGoFVersion = " << nFlyweightGoFVersion << endl;
  6117. //
  6118. // Clean up all the files that have just been compiled in this new
  6119. // batch.
  6120. //
  6121. FileSymbol* file_symbol;
  6122. for (file_symbol = (FileSymbol*) input_java_file_set.FirstElement();
  6123. file_symbol;
  6124. file_symbol = (FileSymbol*) input_java_file_set.NextElement())
  6125. {
  6126. CleanUp(file_symbol);
  6127. }
  6128. //
  6129. // If more messages were added to system_semantic, print them...
  6130. //
  6131. system_semantic -> PrintMessages();
  6132. if (system_semantic -> return_code > 0 ||
  6133. bad_input_filenames.Length() > 0 ||
  6134. unreadable_input_filenames.Length() > 0)
  6135. {
  6136. return_code = 1;
  6137. }
  6138. //
  6139. // If the incremental flag is on, check to see if the user wants us
  6140. // to recompile.
  6141. //
  6142. if (option.incremental)
  6143. {
  6144. // The depend flag should only be in effect in the first pass
  6145. option.depend = false;
  6146. for (bool recompile = IncrementalRecompilation();
  6147. recompile; recompile = IncrementalRecompilation())
  6148. {
  6149. // Reset the return code as we may compile clean in this pass.
  6150. return_code = 0;
  6151. system_semantic -> return_code = 0;
  6152. //
  6153. //
  6154. //
  6155. for (i = 0; i < bad_input_filenames.Length(); i++)
  6156. {
  6157. system_semantic ->
  6158. ReportSemError(SemanticError::BAD_INPUT_FILE,
  6159. BAD_TOKEN, bad_input_filenames[i]);
  6160. }
  6161. //
  6162. //
  6163. //
  6164. for (i = 0; i < unreadable_input_filenames.Length(); i++)
  6165. {
  6166. system_semantic ->
  6167. ReportSemError(SemanticError::UNREADABLE_INPUT_FILE,
  6168. BAD_TOKEN,
  6169. unreadable_input_filenames[i]);
  6170. }
  6171. FileSymbol* file_symbol;
  6172. num_files = 0;
  6173. delete [] input_files; // delete previous copy
  6174. input_files = new FileSymbol*[recompilation_file_set.Size()];
  6175. for (file_symbol = (FileSymbol*) recompilation_file_set.FirstElement();
  6176. file_symbol;
  6177. file_symbol = (FileSymbol*) recompilation_file_set.NextElement())
  6178. {
  6179. input_java_file_set.RemoveElement(file_symbol);
  6180. input_files[num_files++] = file_symbol;
  6181. LexStream* lex_stream = file_symbol -> lex_stream;
  6182. if (lex_stream)
  6183. {
  6184. AstPackageDeclaration* package_declaration = parser ->
  6185. PackageHeaderParse(lex_stream, ast_pool);
  6186. ProcessPackageDeclaration(file_symbol,
  6187. package_declaration);
  6188. ast_pool -> Reset();
  6189. }
  6190. }
  6191. //
  6192. // If a file was erased, remove it from the input file set.
  6193. //
  6194. for (file_symbol = (FileSymbol*) expired_file_set.FirstElement();
  6195. file_symbol;
  6196. file_symbol = (FileSymbol*) expired_file_set.NextElement())
  6197. {
  6198. input_java_file_set.RemoveElement(file_symbol);
  6199. }
  6200. //
  6201. // Reset the global objects before recompiling this new batch.
  6202. //
  6203. expired_file_set.SetEmpty();
  6204. recompilation_file_set.SetEmpty();
  6205. type_trash_bin.Reset();
  6206. //
  6207. // For each file that should be recompiled, process it if it
  6208. // has not already been dragged in by dependence.
  6209. //
  6210. for (int j = 0; j < num_files; j++)
  6211. {
  6212. FileSymbol* file_symbol = input_files[j];
  6213. if (! input_java_file_set.IsElement(file_symbol))
  6214. ProcessFile(file_symbol, ast_pool);
  6215. }
  6216. //
  6217. // Clean up all the files that have just been compiled in
  6218. // this new batch.
  6219. //
  6220. for (file_symbol = (FileSymbol*) input_java_file_set.FirstElement();
  6221. // delete file_symbol
  6222. file_symbol;
  6223. file_symbol = (FileSymbol*) input_java_file_set.NextElement())
  6224. {
  6225. // delete file_symbol
  6226. CleanUp(file_symbol);
  6227. }
  6228. //
  6229. // If any system error or warning was detected, print it...
  6230. //
  6231. system_semantic -> PrintMessages();
  6232. if (system_semantic -> return_code > 0 ||
  6233. bad_input_filenames.Length() > 0 ||
  6234. unreadable_input_filenames.Length() > 0)
  6235. {
  6236. return_code = 1;
  6237. }
  6238. }
  6239. }
  6240. //
  6241. // Are we supposed to generate Makefiles?
  6242. //
  6243. if (option.makefile)
  6244. {
  6245. if (option.dependence_report)
  6246. {
  6247. FILE* outfile = SystemFopen(option.dependence_report_name,
  6248. "w");
  6249. if (outfile == NULL)
  6250. Coutput << "*** Cannot open dependence output file "
  6251. << option.dependence_report_name << endl;
  6252. else
  6253. {
  6254. SymbolSet types_in_new_files;
  6255. FileSymbol* file_symbol;
  6256. for (file_symbol = (FileSymbol*) input_java_file_set.FirstElement();
  6257. file_symbol;
  6258. file_symbol = (FileSymbol*) input_java_file_set.NextElement())
  6259. {
  6260. char* java_name = file_symbol -> FileName();
  6261. for (i = 0; i < file_symbol -> types.Length(); i++)
  6262. {
  6263. TypeSymbol* type = file_symbol -> types[i];
  6264. fprintf(outfile, "%s : %s\n", java_name,
  6265. type -> SignatureString());
  6266. TypeSymbol* static_parent;
  6267. for (static_parent = (TypeSymbol*) type -> static_parents -> FirstElement();
  6268. static_parent;
  6269. static_parent = (TypeSymbol*) type -> static_parents -> NextElement())
  6270. {
  6271. if (! type -> parents ->
  6272. IsElement(static_parent))
  6273. {
  6274. // Only a static ref to static_parent?
  6275. fprintf(outfile, " !%s\n",
  6276. static_parent -> SignatureString());
  6277. //
  6278. // If the type is contained in a type that
  6279. // is not one of the input files, save it
  6280. //
  6281. if (static_parent -> file_symbol &&
  6282. static_parent -> file_symbol -> IsClass())
  6283. {
  6284. types_in_new_files.AddElement(static_parent);
  6285. }
  6286. }
  6287. }
  6288. TypeSymbol* parent;
  6289. for (parent = (TypeSymbol*) type -> parents -> FirstElement();
  6290. parent;
  6291. parent = (TypeSymbol*) type -> parents -> NextElement())
  6292. {
  6293. fprintf(outfile, " %s\n",
  6294. parent -> SignatureString());
  6295. //
  6296. // If the type is contained in a type that is
  6297. // not one of the input files, save it
  6298. //
  6299. if (parent -> file_symbol &&
  6300. parent -> file_symbol -> IsClass())
  6301. {
  6302. types_in_new_files.AddElement(parent);
  6303. }
  6304. }
  6305. }
  6306. }
  6307. //
  6308. // Print the list of class files that are referenced.
  6309. //
  6310. TypeSymbol* type;
  6311. for (type = (TypeSymbol*) types_in_new_files.FirstElement();
  6312. type;
  6313. type = (TypeSymbol*) types_in_new_files.NextElement())
  6314. {
  6315. char* class_name = type -> file_symbol -> FileName();
  6316. fprintf(outfile, "%s : %s\n", class_name,
  6317. type -> SignatureString());
  6318. }
  6319. fclose(outfile);
  6320. }
  6321. }
  6322. else
  6323. {
  6324. SymbolSet* candidates =
  6325. new SymbolSet(input_java_file_set.Size() +
  6326. input_class_file_set.Size());
  6327. *candidates = input_java_file_set;
  6328. candidates -> Union(input_class_file_set);
  6329. TypeDependenceChecker* dependence_checker =
  6330. new TypeDependenceChecker(this, *candidates,
  6331. type_trash_bin);
  6332. dependence_checker -> PartialOrder();
  6333. dependence_checker -> OutputDependences();
  6334. delete dependence_checker;
  6335. delete candidates;
  6336. }
  6337. }
  6338. }
  6339. delete ast_pool;
  6340. delete main_file_clone; // delete the clone of the main source file...
  6341. delete [] input_files;
  6342. delete cs_table;
  6343. delete ms_table;
  6344. delete mb_table;
  6345. delete gen_table;
  6346. delete assoc_table;
  6347. }
  6348. Control::~Control()
  6349. {
  6350. unsigned i;
  6351. for (i = 0; i < bad_zip_filenames.Length(); i++)
  6352. delete [] bad_zip_filenames[i];
  6353. for (i = 0; i < bad_input_filenames.Length(); i++)
  6354. delete [] bad_input_filenames[i];
  6355. for (i = 0; i < unreadable_input_filenames.Length(); i++)
  6356. delete [] unreadable_input_filenames[i];
  6357. for (i = 0; i < system_directories.Length(); i++)
  6358. delete system_directories[i];
  6359. delete scanner;
  6360. delete parser;
  6361. delete system_semantic;
  6362. delete system_table;
  6363. #ifdef JIKES_DEBUG
  6364. if (option.debug_dump_lex || option.debug_dump_ast ||
  6365. option.debug_unparse_ast)
  6366. {
  6367. Coutput << line_count << " source lines read" << endl
  6368. << class_files_read << " \".class\" files read" << endl
  6369. << class_files_written << " \".class\" files written" << endl
  6370. << input_files_processed << " \".java\" files processed"
  6371. << endl;
  6372. }
  6373. #endif // JIKES_DEBUG
  6374. }
  6375. PackageSymbol* Control::ProcessPackage(const wchar_t* name)
  6376. {
  6377. int name_length = wcslen(name);
  6378. wchar_t* package_name = new wchar_t[name_length];
  6379. int length;
  6380. for (length = 0;
  6381. length < name_length && name[length] != U_SLASH; length++)
  6382. {
  6383. package_name[length] = name[length];
  6384. }
  6385. NameSymbol* name_symbol = FindOrInsertName(package_name, length);
  6386. PackageSymbol* package_symbol =
  6387. external_table.FindPackageSymbol(name_symbol);
  6388. if (! package_symbol)
  6389. {
  6390. package_symbol = external_table.InsertPackageSymbol(name_symbol, NULL);
  6391. FindPathsToDirectory(package_symbol);
  6392. }
  6393. while (length < name_length)
  6394. {
  6395. int start = ++length;
  6396. for (int i = 0;
  6397. length < name_length && name[length] != U_SLASH;
  6398. i++, length++)
  6399. {
  6400. package_name[i] = name[length];
  6401. }
  6402. name_symbol = FindOrInsertName(package_name, length - start);
  6403. PackageSymbol* subpackage_symbol =
  6404. package_symbol -> FindPackageSymbol(name_symbol);
  6405. if (! subpackage_symbol)
  6406. {
  6407. subpackage_symbol =
  6408. package_symbol -> InsertPackageSymbol(name_symbol);
  6409. FindPathsToDirectory(subpackage_symbol);
  6410. }
  6411. package_symbol = subpackage_symbol;
  6412. }
  6413. delete [] package_name;
  6414. return package_symbol;
  6415. }
  6416. //
  6417. // When searching for a subdirectory in a zipped file, it must already be
  6418. // present in the hierarchy.
  6419. //
  6420. DirectorySymbol* Control::FindSubdirectory(PathSymbol* path_symbol,
  6421. wchar_t* name, int name_length)
  6422. {
  6423. wchar_t* directory_name = new wchar_t[name_length + 1];
  6424. DirectorySymbol* directory_symbol = path_symbol -> RootDirectory();
  6425. for (int start = 0, end;
  6426. directory_symbol && start < name_length;
  6427. start = end + 1)
  6428. {
  6429. end = start;
  6430. for (int i = 0; end < name_length && name[end] != U_SLASH; i++, end++)
  6431. directory_name[i] = name[end];
  6432. NameSymbol* name_symbol = FindOrInsertName(directory_name,
  6433. end - start);
  6434. directory_symbol =
  6435. directory_symbol -> FindDirectorySymbol(name_symbol);
  6436. }
  6437. delete [] directory_name;
  6438. return directory_symbol;
  6439. }
  6440. //
  6441. // When searching for a directory in the system, if it is not already present
  6442. // in the hierarchy insert it and attempt to read it from the system...
  6443. //
  6444. #ifdef UNIX_FILE_SYSTEM
  6445. DirectorySymbol* Control::ProcessSubdirectories(wchar_t* source_name,
  6446. int source_name_length,
  6447. bool source_dir)
  6448. {
  6449. int name_length = (source_name_length < 0 ? 0 : source_name_length);
  6450. char* input_name = new char[name_length + 1];
  6451. for (int i = 0; i < name_length; i++)
  6452. input_name[i] = source_name[i];
  6453. input_name[name_length] = U_NULL;
  6454. DirectorySymbol* directory_symbol = NULL;
  6455. struct stat status;
  6456. if (SystemStat(input_name, &status) == 0 &&
  6457. (status.st_mode & JIKES_STAT_S_IFDIR))
  6458. {
  6459. directory_symbol = system_table ->
  6460. FindDirectorySymbol(status.st_dev, status.st_ino);
  6461. }
  6462. if (! directory_symbol)
  6463. {
  6464. if (input_name[0] == U_SLASH) // file name starts with '/'
  6465. {
  6466. directory_symbol =
  6467. new DirectorySymbol(FindOrInsertName(source_name, name_length),
  6468. classpath[dot_classpath_index],
  6469. source_dir);
  6470. directory_symbol -> ReadDirectory();
  6471. system_directories.Next() = directory_symbol;
  6472. system_table -> InsertDirectorySymbol(status.st_dev,
  6473. status.st_ino,
  6474. directory_symbol);
  6475. }
  6476. else
  6477. {
  6478. wchar_t* name = new wchar_t[name_length + 1];
  6479. for (int i = 0; i < name_length; i++)
  6480. name[i] = source_name[i];
  6481. name[name_length] = U_NULL;
  6482. // Start at the dot directory.
  6483. directory_symbol =
  6484. classpath[dot_classpath_index] -> RootDirectory();
  6485. wchar_t* directory_name = new wchar_t[name_length];
  6486. int end = 0;
  6487. for (int start = end; start < name_length; start = end)
  6488. {
  6489. int length;
  6490. for (length = 0;
  6491. end < name_length && name[end] != U_SLASH;
  6492. length++, end++)
  6493. {
  6494. directory_name[length] = name[end];
  6495. }
  6496. if (length != 1 || directory_name[0] != U_DOT)
  6497. {
  6498. // Not the current directory.
  6499. if (length == 2 && directory_name[0] == U_DOT &&
  6500. directory_name[1] == U_DOT)
  6501. {
  6502. // keep the current directory
  6503. if (directory_symbol -> Identity() == dot_name_symbol ||
  6504. directory_symbol -> Identity() == dot_dot_name_symbol)
  6505. {
  6506. DirectorySymbol* subdirectory_symbol =
  6507. directory_symbol -> FindDirectorySymbol(dot_dot_name_symbol);
  6508. if (! subdirectory_symbol)
  6509. subdirectory_symbol =
  6510. directory_symbol -> InsertDirectorySymbol(dot_dot_name_symbol,
  6511. source_dir);
  6512. directory_symbol = subdirectory_symbol;
  6513. }
  6514. else directory_symbol = directory_symbol -> owner -> DirectoryCast();
  6515. }
  6516. else
  6517. {
  6518. NameSymbol* name_symbol =
  6519. FindOrInsertName(directory_name, length);
  6520. DirectorySymbol* subdirectory_symbol =
  6521. directory_symbol -> FindDirectorySymbol(name_symbol);
  6522. if (! subdirectory_symbol)
  6523. subdirectory_symbol =
  6524. directory_symbol -> InsertDirectorySymbol(name_symbol,
  6525. source_dir);
  6526. directory_symbol = subdirectory_symbol;
  6527. }
  6528. }
  6529. for (end++;
  6530. end < name_length && name[end] == U_SLASH;
  6531. end++); // skip all extra '/'
  6532. }
  6533. //
  6534. // Insert the new directory into the system table to avoid
  6535. // duplicates, in case the same directory is specified with
  6536. // a different name.
  6537. //
  6538. if (directory_symbol !=
  6539. classpath[dot_classpath_index] -> RootDirectory())
  6540. {
  6541. // Not the dot directory.
  6542. system_table -> InsertDirectorySymbol(status.st_dev,
  6543. status.st_ino,
  6544. directory_symbol);
  6545. directory_symbol -> ReadDirectory();
  6546. }
  6547. delete [] directory_name;
  6548. delete [] name;
  6549. }
  6550. }
  6551. delete [] input_name;
  6552. return directory_symbol;
  6553. }
  6554. #elif defined(WIN32_FILE_SYSTEM)
  6555. DirectorySymbol* Control::ProcessSubdirectories(wchar_t* source_name,
  6556. int source_name_length,
  6557. bool source_dir)
  6558. {
  6559. DirectorySymbol* directory_symbol =
  6560. classpath[dot_classpath_index] -> RootDirectory();
  6561. int name_length = (source_name_length < 0 ? 0 : source_name_length);
  6562. wchar_t* name = new wchar_t[name_length + 1];
  6563. char* input_name = new char[name_length + 1];
  6564. for (int i = 0; i < name_length; i++)
  6565. input_name[i] = name[i] = source_name[i];
  6566. input_name[name_length] = name[name_length] = U_NULL;
  6567. if (name_length >= 2 && Case::IsAsciiAlpha(input_name[0]) &&
  6568. input_name[1] == U_COLON) // a disk was specified
  6569. {
  6570. char disk = input_name[0];
  6571. option.SaveCurrentDirectoryOnDisk(disk);
  6572. if (SetCurrentDirectory(input_name))
  6573. {
  6574. // First, get the right size.
  6575. DWORD directory_length = GetCurrentDirectory(0, input_name);
  6576. char* full_directory_name = new char[directory_length + 1];
  6577. DWORD length = GetCurrentDirectory(directory_length, full_directory_name);
  6578. if (length <= directory_length)
  6579. {
  6580. // Turn '\' to '/'.
  6581. for (char* ptr = full_directory_name; *ptr; ptr++)
  6582. *ptr = (*ptr != U_BACKSLASH ? *ptr : (char) U_SLASH);
  6583. char* current_directory = option.GetMainCurrentDirectory();
  6584. int prefix_length = strlen(current_directory);
  6585. int start = (prefix_length <= (int) length &&
  6586. Case::StringSegmentEqual(current_directory,
  6587. full_directory_name,
  6588. prefix_length) &&
  6589. (full_directory_name[prefix_length] == U_SLASH ||
  6590. full_directory_name[prefix_length] == U_NULL)
  6591. ? prefix_length + 1
  6592. : 0);
  6593. if (start > (int) length)
  6594. name_length = 0;
  6595. else if (start <= (int) length) // note that we can assert that (start != length)
  6596. {
  6597. delete [] name;
  6598. name_length = length - start;
  6599. name = new wchar_t[name_length + 1];
  6600. for (int k = 0, i = start; i < (int) length; i++, k++)
  6601. name[k] = full_directory_name[i];
  6602. name[name_length] = U_NULL;
  6603. }
  6604. }
  6605. delete [] full_directory_name;
  6606. }
  6607. // Reset the current directory on this disk.
  6608. option.ResetCurrentDirectoryOnDisk(disk);
  6609. option.SetMainCurrentDirectory(); // Reset the real current directory.
  6610. }
  6611. int end;
  6612. if (name_length > 2 && Case::IsAsciiAlpha(name[0]) &&
  6613. name[1] == U_COLON && name[2] == U_SLASH)
  6614. {
  6615. end = 3;
  6616. }
  6617. else
  6618. {
  6619. for (end = 0;
  6620. end < name_length && name[end] == U_SLASH;
  6621. end++); // keep all extra leading '/'
  6622. }
  6623. wchar_t* directory_name = new wchar_t[name_length];
  6624. int length;
  6625. if (end > 0)
  6626. {
  6627. for (length = 0; length < end; length++)
  6628. directory_name[length] = name[length];
  6629. NameSymbol* name_symbol = FindOrInsertName(directory_name, length);
  6630. DirectorySymbol* subdirectory_symbol =
  6631. directory_symbol -> FindDirectorySymbol(name_symbol);
  6632. if (! subdirectory_symbol)
  6633. subdirectory_symbol =
  6634. directory_symbol -> InsertDirectorySymbol(name_symbol,
  6635. source_dir);
  6636. directory_symbol = subdirectory_symbol;
  6637. }
  6638. for (int start = end; start < name_length; start = end)
  6639. {
  6640. for (length = 0;
  6641. end < name_length && name[end] != U_SLASH;
  6642. length++, end++)
  6643. {
  6644. directory_name[length] = name[end];
  6645. }
  6646. if (length != 1 || directory_name[0] != U_DOT)
  6647. {
  6648. // Not the current directory.
  6649. if (length == 2 && directory_name[0] == U_DOT &&
  6650. directory_name[1] == U_DOT)
  6651. {
  6652. // Keep the current directory.
  6653. if (directory_symbol -> Identity() == dot_name_symbol ||
  6654. directory_symbol -> Identity() == dot_dot_name_symbol)
  6655. {
  6656. DirectorySymbol* subdirectory_symbol =
  6657. directory_symbol -> FindDirectorySymbol(dot_dot_name_symbol);
  6658. if (! subdirectory_symbol)
  6659. subdirectory_symbol =
  6660. directory_symbol -> InsertDirectorySymbol(dot_dot_name_symbol,
  6661. source_dir);
  6662. directory_symbol = subdirectory_symbol;
  6663. }
  6664. else directory_symbol = directory_symbol -> owner -> DirectoryCast();
  6665. }
  6666. else
  6667. {
  6668. NameSymbol* name_symbol = FindOrInsertName(directory_name,
  6669. length);
  6670. DirectorySymbol* subdirectory_symbol =
  6671. directory_symbol -> FindDirectorySymbol(name_symbol);
  6672. if (! subdirectory_symbol)
  6673. subdirectory_symbol =
  6674. directory_symbol -> InsertDirectorySymbol(name_symbol,
  6675. source_dir);
  6676. directory_symbol = subdirectory_symbol;
  6677. }
  6678. }
  6679. for (end++;
  6680. end < name_length && name[end] == U_SLASH;
  6681. end++); // skip all extra '/'
  6682. }
  6683. directory_symbol -> ReadDirectory();
  6684. delete [] directory_name;
  6685. delete [] name;
  6686. delete [] input_name;
  6687. return directory_symbol;
  6688. }
  6689. #endif // WIN32_FILE_SYSTEM
  6690. void Control::ProcessNewInputFiles(SymbolSet& file_set, char** arguments)
  6691. {
  6692. unsigned i;
  6693. for (i = 0; i < bad_input_filenames.Length(); i++)
  6694. delete [] bad_input_filenames[i];
  6695. bad_input_filenames.Reset();
  6696. for (i = 0; i < unreadable_input_filenames.Length(); i++)
  6697. delete [] unreadable_input_filenames[i];
  6698. unreadable_input_filenames.Reset();
  6699. //
  6700. // Process all file names specified in command line. By this point, only
  6701. // filenames should remain in arguments - constructing the Option should
  6702. // have filtered out all options and expanded @files.
  6703. //
  6704. if (arguments)
  6705. {
  6706. int j = 0;
  6707. while (arguments[j])
  6708. {
  6709. char* file_name = arguments[j++];
  6710. unsigned file_name_length = strlen(file_name);
  6711. wchar_t* name = new wchar_t[file_name_length + 1];
  6712. for (unsigned i = 0; i < file_name_length; i++)
  6713. name[i] = (file_name[i] != U_BACKSLASH ? file_name[i]
  6714. : (wchar_t) U_SLASH); // Change '\' to '/'.
  6715. name[file_name_length] = U_NULL;
  6716. //
  6717. // File must be of the form xxx.java where xxx is a
  6718. // character string consisting of at least one character.
  6719. //
  6720. if (file_name_length < FileSymbol::java_suffix_length ||
  6721. (! FileSymbol::IsJavaSuffix(&file_name[file_name_length - FileSymbol::java_suffix_length])))
  6722. {
  6723. bad_input_filenames.Next() = name;
  6724. }
  6725. else
  6726. {
  6727. FileSymbol* file_symbol =
  6728. FindOrInsertJavaInputFile(name,
  6729. file_name_length - FileSymbol::java_suffix_length);
  6730. if (! file_symbol)
  6731. unreadable_input_filenames.Next() = name;
  6732. else
  6733. {
  6734. delete [] name;
  6735. file_set.AddElement(file_symbol);
  6736. }
  6737. }
  6738. }
  6739. }
  6740. }
  6741. FileSymbol* Control::FindOrInsertJavaInputFile(DirectorySymbol* directory_symbol,
  6742. NameSymbol* file_name_symbol)
  6743. {
  6744. FileSymbol* file_symbol = NULL;
  6745. int length = file_name_symbol -> Utf8NameLength() +
  6746. FileSymbol::java_suffix_length;
  6747. char* java_name = new char[length + 1]; // +1 for \0
  6748. strcpy(java_name, file_name_symbol -> Utf8Name());
  6749. strcat(java_name, FileSymbol::java_suffix);
  6750. DirectoryEntry* entry = directory_symbol -> FindEntry(java_name, length);
  6751. if (entry)
  6752. {
  6753. file_symbol = directory_symbol -> FindFileSymbol(file_name_symbol);
  6754. if (! file_symbol)
  6755. {
  6756. file_symbol =
  6757. directory_symbol -> InsertFileSymbol(file_name_symbol);
  6758. file_symbol -> directory_symbol = directory_symbol;
  6759. file_symbol -> SetJava();
  6760. }
  6761. file_symbol -> mtime = entry -> Mtime();
  6762. }
  6763. delete [] java_name;
  6764. return file_symbol;
  6765. }
  6766. FileSymbol* Control::FindOrInsertJavaInputFile(wchar_t* name, int name_length)
  6767. {
  6768. FileSymbol* file_symbol = NULL;
  6769. //
  6770. // The name has been preprocessed so that if it contains any
  6771. // slashes it is a forward slash. In the loop below we look
  6772. // for the occurrence of the first slash (if any) that separates
  6773. // the file name from its directory name.
  6774. //
  6775. DirectorySymbol* directory_symbol;
  6776. NameSymbol* file_name_symbol;
  6777. #ifdef UNIX_FILE_SYSTEM
  6778. int len;
  6779. for (len = name_length - 1; len >= 0 && name[len] != U_SLASH; len--)
  6780. ;
  6781. directory_symbol = ProcessSubdirectories(name, len, true);
  6782. file_name_symbol = FindOrInsertName(&name[len + 1],
  6783. name_length - (len + 1));
  6784. #elif defined(WIN32_FILE_SYSTEM)
  6785. int len;
  6786. for (len = name_length - 1;
  6787. len >= 0 && name[len] != U_SLASH && name[len] != U_COLON;
  6788. len--);
  6789. directory_symbol = ProcessSubdirectories(name,
  6790. (name[len] == U_COLON ? len + 1
  6791. : len),
  6792. true);
  6793. file_name_symbol = FindOrInsertName(&name[len + 1],
  6794. name_length - (len + 1));
  6795. #endif // WIN32_FILE_SYSTEM
  6796. for (unsigned i = 1; i < classpath.Length(); i++)
  6797. {
  6798. if (i == dot_classpath_index) // the current directory (.).
  6799. {
  6800. file_symbol = FindOrInsertJavaInputFile(directory_symbol,
  6801. file_name_symbol);
  6802. if (file_symbol)
  6803. break;
  6804. }
  6805. else if (classpath[i] -> IsZip())
  6806. {
  6807. DirectorySymbol* directory_symbol = FindSubdirectory(classpath[i],
  6808. name, len);
  6809. if (directory_symbol)
  6810. {
  6811. file_symbol =
  6812. directory_symbol -> FindFileSymbol(file_name_symbol);
  6813. if (file_symbol && file_symbol -> IsJava())
  6814. break;
  6815. else file_symbol = NULL;
  6816. }
  6817. }
  6818. }
  6819. //
  6820. // If the file was found, return it; otherwise, in case the (.) directory
  6821. // was not specified in the classpath, search for the file in it...
  6822. //
  6823. return file_symbol ? file_symbol
  6824. : FindOrInsertJavaInputFile(directory_symbol, file_name_symbol);
  6825. }
  6826. PackageSymbol* Control::FindOrInsertPackage(LexStream* lex_stream,
  6827. AstName* name)
  6828. {
  6829. PackageSymbol* package;
  6830. if (name -> base_opt)
  6831. {
  6832. package = FindOrInsertPackage(lex_stream, name -> base_opt);
  6833. NameSymbol* name_symbol =
  6834. lex_stream -> NameSymbol(name -> identifier_token);
  6835. PackageSymbol* subpackage = package -> FindPackageSymbol(name_symbol);
  6836. if (! subpackage)
  6837. subpackage = package -> InsertPackageSymbol(name_symbol);
  6838. package = subpackage;
  6839. }
  6840. else
  6841. {
  6842. NameSymbol* name_symbol =
  6843. lex_stream -> NameSymbol(name -> identifier_token);
  6844. package = external_table.FindPackageSymbol(name_symbol);
  6845. if (! package)
  6846. package = external_table.InsertPackageSymbol(name_symbol, NULL);
  6847. }
  6848. FindPathsToDirectory(package);
  6849. return package;
  6850. }
  6851. void Control::ProcessFile(FileSymbol* file_symbol, StoragePool* ast_pool)
  6852. {
  6853. ProcessHeaders(file_symbol);
  6854. //
  6855. // As long as there are new bodies, ...
  6856. //
  6857. for (unsigned i = 0; i < needs_body_work.Length(); i++)
  6858. {
  6859. assert(semantic.Length() == 0);
  6860. //
  6861. // These bodies are not necessarily in file_symbol; they
  6862. // might be in another FileSymbol used by file_symbol.
  6863. //
  6864. ProcessBodies(needs_body_work[i], ast_pool);
  6865. }
  6866. needs_body_work.Reset();
  6867. }
  6868. void Control::ProcessHeaders(FileSymbol* file_symbol)
  6869. {
  6870. if (file_symbol -> semantic)
  6871. return;
  6872. input_java_file_set.AddElement(file_symbol);
  6873. bool initial_invocation = (semantic.Length() == 0);
  6874. if (option.verbose)
  6875. {
  6876. Coutput << "[read "
  6877. << file_symbol -> FileName()
  6878. << "]" << endl;
  6879. }
  6880. if (! file_symbol -> lex_stream)
  6881. scanner -> Scan(file_symbol);
  6882. else file_symbol -> lex_stream -> Reset();
  6883. if (file_symbol -> lex_stream) // do we have a successful scan!
  6884. {
  6885. if (! file_symbol -> compilation_unit)
  6886. file_symbol -> compilation_unit =
  6887. parser -> HeaderParse(file_symbol -> lex_stream);
  6888. //
  6889. // If we have a compilation unit, analyze it, process its types.
  6890. //
  6891. if (file_symbol -> compilation_unit)
  6892. {
  6893. assert(! file_symbol -> semantic);
  6894. if (! file_symbol -> package)
  6895. ProcessPackageDeclaration(file_symbol,
  6896. file_symbol -> compilation_unit -> package_declaration_opt);
  6897. file_symbol -> semantic = new Semantic(*this, file_symbol);
  6898. semantic.Next() = file_symbol -> semantic;
  6899. file_symbol -> semantic -> ProcessTypeNames();
  6900. }
  6901. }
  6902. if (initial_invocation)
  6903. ProcessMembers();
  6904. }
  6905. void Control::ProcessMembers()
  6906. {
  6907. Tuple<TypeSymbol*> partially_ordered_types(1024);
  6908. SymbolSet needs_member_work(101);
  6909. TypeCycleChecker cycle_checker(partially_ordered_types);
  6910. TopologicalSort topological_sorter(needs_member_work,
  6911. partially_ordered_types);
  6912. unsigned start = 0;
  6913. while (start < semantic.Length())
  6914. {
  6915. needs_member_work.SetEmpty();
  6916. do
  6917. {
  6918. //
  6919. // Check whether or not there are cycles in this new batch of
  6920. // types. Create a partial order of the types (cycles are ordered
  6921. // arbitrarily) and place the result in partially_ordered_types.
  6922. //
  6923. cycle_checker.PartialOrder(semantic, start);
  6924. start = semantic.Length(); // next starting point
  6925. //
  6926. // Process the extends and implements clauses.
  6927. //
  6928. for (unsigned j = 0; j < partially_ordered_types.Length(); j++)
  6929. {
  6930. TypeSymbol* type = partially_ordered_types[j];
  6931. needs_member_work.AddElement(type);
  6932. type -> ProcessTypeHeaders();
  6933. type -> semantic_environment -> sem ->
  6934. types_to_be_processed.AddElement(type);
  6935. }
  6936. } while (start < semantic.Length());
  6937. //
  6938. // Partially order the collection of types in needs_member_work and
  6939. // place the result in partially_ordered_types. This reordering is
  6940. // based on the complete "supertype" information computed in
  6941. // ProcessTypeHeaders.
  6942. //
  6943. topological_sorter.Sort();
  6944. for (unsigned i = 0; i < partially_ordered_types.Length(); i++)
  6945. {
  6946. TypeSymbol* type = partially_ordered_types[i];
  6947. needs_body_work.Next() = type;
  6948. type -> ProcessMembers();
  6949. }
  6950. }
  6951. semantic.Reset();
  6952. }
  6953. void Control::CollectTypes(TypeSymbol* type, Tuple<TypeSymbol*>& types)
  6954. {
  6955. types.Next() = type;
  6956. for (unsigned j = 0; j < type -> NumAnonymousTypes(); j++)
  6957. CollectTypes(type -> AnonymousType(j), types);
  6958. if (type -> local)
  6959. {
  6960. for (TypeSymbol* local_type = (TypeSymbol*) type -> local -> FirstElement();
  6961. local_type;
  6962. local_type = (TypeSymbol*) type -> local -> NextElement())
  6963. {
  6964. CollectTypes(local_type, types);
  6965. }
  6966. }
  6967. if (type -> non_local)
  6968. {
  6969. for (TypeSymbol* non_local_type = (TypeSymbol*) type -> non_local -> FirstElement();
  6970. non_local_type;
  6971. non_local_type = (TypeSymbol*) type -> non_local -> NextElement())
  6972. {
  6973. CollectTypes(non_local_type, types);
  6974. }
  6975. }
  6976. }
  6977. void Control::ProcessBodies(TypeSymbol* type, StoragePool* ast_pool)
  6978. {
  6979. Semantic* sem = type -> semantic_environment -> sem;
  6980. if (type -> declaration &&
  6981. ! sem -> compilation_unit -> BadCompilationUnitCast())
  6982. {
  6983. #ifdef WIN32_FILE_SYSTEM
  6984. if (! type -> file_symbol -> IsZip())
  6985. {
  6986. int length = type -> Utf8NameLength() +
  6987. FileSymbol::class_suffix_length;
  6988. char* classfile_name = new char[length + 1]; // +1 for "\0"
  6989. strcpy(classfile_name, type -> Utf8Name());
  6990. strcat(classfile_name, FileSymbol::class_suffix);
  6991. DirectorySymbol* directory =
  6992. type -> file_symbol -> OutputDirectory();
  6993. DirectoryEntry* entry =
  6994. directory -> FindCaseInsensitiveEntry(classfile_name, length);
  6995. //
  6996. // If an entry is found and it is not identical (in a
  6997. // case-sensitive test) to the name of the type, issue an
  6998. // appropriate message.
  6999. //
  7000. if (entry && strcmp(classfile_name, entry -> name) != 0)
  7001. {
  7002. wchar_t* entry_name = new wchar_t[entry -> length + 1];
  7003. for (int i = 0; i < length; i++)
  7004. entry_name[i] = entry -> name[i];
  7005. entry_name[entry -> length] = U_NULL;
  7006. sem -> ReportSemError(SemanticError::FILE_FILE_CONFLICT,
  7007. type -> declaration -> identifier_token,
  7008. type -> Name(), entry_name,
  7009. directory -> Name());
  7010. delete [] entry_name;
  7011. }
  7012. delete [] classfile_name;
  7013. }
  7014. #endif // WIN32_FILE_SYSTEM
  7015. if (! parser -> InitializerParse(sem -> lex_stream,
  7016. type -> declaration))
  7017. {
  7018. // Mark that syntax errors were detected.
  7019. sem -> compilation_unit -> MarkBad();
  7020. }
  7021. else
  7022. {
  7023. type -> CompleteSymbolTable();
  7024. if (! parser -> BodyParse(sem -> lex_stream, type -> declaration))
  7025. {
  7026. // Mark that syntax errors were detected.
  7027. sem -> compilation_unit -> MarkBad();
  7028. }
  7029. else type -> ProcessExecutableBodies();
  7030. }
  7031. if (sem -> NumErrors() == 0 &&
  7032. sem -> lex_stream -> NumBadTokens() == 0 &&
  7033. ! sem -> compilation_unit -> BadCompilationUnitCast())
  7034. {
  7035. Tuple<TypeSymbol*>* types = new Tuple<TypeSymbol*>(1024);
  7036. CollectTypes(type, *types);
  7037. //
  7038. // Get Structural info for pattern detection.
  7039. //
  7040. for (unsigned k = 0; k < types -> Length(); k++)
  7041. {
  7042. TypeSymbol *type = (*types)[k];
  7043. ExtractStructure(w_table, r_table, d_table, cs_table, mb_table, ms_table, gen_table, assoc_table, type, ast_pool);
  7044. }
  7045. //
  7046. // If we are supposed to generate code, do so now !!!
  7047. //
  7048. if (option.bytecode)
  7049. {
  7050. for (unsigned k = 0; k < types -> Length(); k++)
  7051. {
  7052. TypeSymbol* type = (*types)[k];
  7053. // Make sure the literal is available for bytecode.
  7054. type -> file_symbol -> SetFileNameLiteral(this);
  7055. ByteCode* code = new ByteCode(type);
  7056. code -> GenerateCode();
  7057. delete code;
  7058. }
  7059. }
  7060. //
  7061. // If no error was detected while generating code, then
  7062. // start cleaning up.
  7063. //
  7064. if (! option.nocleanup)
  7065. {
  7066. if (sem -> NumErrors() == 0)
  7067. {
  7068. for (unsigned k = 0; k < types -> Length(); k++)
  7069. {
  7070. TypeSymbol* type = (*types)[k];
  7071. delete type -> semantic_environment;
  7072. type -> semantic_environment = NULL;
  7073. type -> declaration -> semantic_environment = NULL;
  7074. }
  7075. }
  7076. delete types;
  7077. }
  7078. }
  7079. }
  7080. sem -> types_to_be_processed.RemoveElement(type);
  7081. if (sem -> types_to_be_processed.Size() == 0)
  7082. {
  7083. // All types belonging to this compilation unit have been processed.
  7084. CheckForUnusedImports(sem);
  7085. if (! option.nocleanup)
  7086. {
  7087. CleanUp(sem -> source_file_symbol);
  7088. }
  7089. }
  7090. }
  7091. void Control::CheckForUnusedImports(Semantic* sem)
  7092. {
  7093. if (sem -> NumErrors() != 0 ||
  7094. sem -> lex_stream -> NumBadTokens() != 0 ||
  7095. sem -> compilation_unit -> BadCompilationUnitCast())
  7096. {
  7097. //
  7098. // It's not worth checking for unused imports if compilation
  7099. // wasn't successful; we may well have just not got round to
  7100. // compiling the relevant code, and if there were errors, the
  7101. // user has more important things to worry about than unused
  7102. // imports!
  7103. //
  7104. return;
  7105. }
  7106. for (unsigned i = 0;
  7107. i < sem -> compilation_unit -> NumImportDeclarations(); ++i)
  7108. {
  7109. AstImportDeclaration* import_declaration =
  7110. sem -> compilation_unit -> ImportDeclaration(i);
  7111. Symbol* symbol = import_declaration -> name -> symbol;
  7112. if (import_declaration -> star_token_opt)
  7113. {
  7114. PackageSymbol* package = symbol -> PackageCast();
  7115. if (package &&
  7116. ! sem -> referenced_package_imports.IsElement(package))
  7117. {
  7118. sem -> ReportSemError(SemanticError::UNUSED_PACKAGE_IMPORT,
  7119. import_declaration,
  7120. package -> PackageName());
  7121. }
  7122. }
  7123. else
  7124. {
  7125. TypeSymbol* import_type = symbol -> TypeCast();
  7126. if (import_type &&
  7127. ! sem -> referenced_type_imports.IsElement(import_type))
  7128. {
  7129. sem -> ReportSemError(SemanticError::UNUSED_TYPE_IMPORT,
  7130. import_declaration,
  7131. import_type -> ContainingPackage() -> PackageName(),
  7132. import_type -> ExternalName());
  7133. }
  7134. }
  7135. }
  7136. }
  7137. //
  7138. // Introduce the main package and the current package.
  7139. // This procedure is invoked directly only while doing
  7140. // an incremental compilation.
  7141. //
  7142. void Control::ProcessPackageDeclaration(FileSymbol* file_symbol,
  7143. AstPackageDeclaration* package_declaration)
  7144. {
  7145. file_symbol -> package = (package_declaration
  7146. ? FindOrInsertPackage(file_symbol -> lex_stream,
  7147. package_declaration -> name)
  7148. : unnamed_package);
  7149. for (unsigned i = 0; i < file_symbol -> lex_stream -> NumTypes(); i++)
  7150. {
  7151. TokenIndex identifier_token = file_symbol -> lex_stream ->
  7152. Next(file_symbol -> lex_stream -> Type(i));
  7153. if (file_symbol -> lex_stream -> Kind(identifier_token) ==
  7154. TK_Identifier)
  7155. {
  7156. NameSymbol* name_symbol =
  7157. file_symbol -> lex_stream -> NameSymbol(identifier_token);
  7158. if (! file_symbol -> package -> FindTypeSymbol(name_symbol))
  7159. {
  7160. TypeSymbol* type = file_symbol -> package ->
  7161. InsertOuterTypeSymbol(name_symbol);
  7162. type -> file_symbol = file_symbol;
  7163. type -> outermost_type = type;
  7164. type -> supertypes_closure = new SymbolSet;
  7165. type -> subtypes = new SymbolSet;
  7166. type -> SetOwner(file_symbol -> package);
  7167. type -> SetSignature(*this);
  7168. type -> MarkSourcePending();
  7169. //
  7170. // If this type is contained in the unnamed package add it to
  7171. // the set unnamed_package_types if a type of similar name was
  7172. // not already there.
  7173. //
  7174. if (! package_declaration &&
  7175. unnamed_package_types.Image(type -> Identity()) == NULL)
  7176. {
  7177. unnamed_package_types.AddElement(type);
  7178. }
  7179. }
  7180. }
  7181. }
  7182. }
  7183. void Control::CleanUp(FileSymbol* file_symbol)
  7184. {
  7185. Semantic* sem = file_symbol -> semantic;
  7186. if (sem)
  7187. {
  7188. #ifdef JIKES_DEBUG
  7189. if (option.debug_dump_lex)
  7190. {
  7191. sem -> lex_stream -> Reset(); // rewind input and ...
  7192. sem -> lex_stream -> Dump(); // dump it!
  7193. }
  7194. if (option.debug_dump_ast)
  7195. sem -> compilation_unit -> Print(*sem -> lex_stream);
  7196. if (option.debug_unparse_ast)
  7197. {
  7198. if (option.debug_unparse_ast_debug)
  7199. {
  7200. // which of these is correct?
  7201. sem -> compilation_unit -> debug_unparse = true;
  7202. Ast::debug_unparse = true;
  7203. }
  7204. sem -> compilation_unit -> Unparse(sem -> lex_stream,
  7205. "unparsed/");
  7206. }
  7207. #endif // JIKES_DEBUG
  7208. //sem -> PrintMessages();
  7209. if (sem -> return_code > 0)
  7210. return_code = 1;
  7211. file_symbol -> CleanUp();
  7212. }
  7213. }
  7214. #ifdef HAVE_JIKES_NAMESPACE
  7215. } // Close namespace Jikes block
  7216. #endif