1 // $Id: symbol.cpp,v 1.109 2004/04/14 02:49:54 cabbey Exp $
2 //
3 // This software is subject to the terms of the IBM Jikes Compiler Open
4 // Source 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
10 #include "symbol.h"
11 #include "stream.h"
12 #include "control.h"
13 #include "ast.h"
14 #include "semantic.h"
15 #include "table.h"
16 #include "zip.h"
17 #include "set.h"
18 #include "case.h"
19 #include "option.h"
20
21 #ifdef HAVE_JIKES_NAMESPACE
22 namespace Jikes { // Open namespace Jikes block
23 #endif
24
25 const char* FileSymbol::java_suffix = StringConstant::U8S_DO_java;
26 unsigned FileSymbol::java_suffix_length = strlen(java_suffix);
27 const char* FileSymbol::class_suffix = StringConstant::U8S_DO_class;
28 unsigned FileSymbol::class_suffix_length = strlen(class_suffix);
29
Header()30 wchar_t* MethodSymbol::Header()
31 {
32 assert(type_);
33
34 if (! header)
35 {
36 bool is_constructor = Name()[0] == U_LESS && Name()[1] == U_i;
37 unsigned num_parameters = NumFormalParameters();
38 int length = (Type() -> ContainingPackage() -> PackageNameLength() +
39 Type() -> ExternalNameLength() +
40 (is_constructor ? containing_type -> NameLength()
41 : NameLength())
42 + 5); // +5 for '.' after package_name, ' ' after type,
43 // '(' after name, ')' after all parameters,
44 // ';' to terminate
45 for (unsigned i = 0; i < num_parameters; i++)
46 {
47 VariableSymbol* formal = FormalParameter(i);
48 length += (formal -> Type() -> ContainingPackage() -> PackageNameLength() +
49 formal -> Type() -> ExternalNameLength() +
50 formal -> NameLength() + 4);
51 // +4 for '.' after package_name, ' ' after type; ',' and ' ' to
52 // separate this formal parameter from the next one. Last
53 // parameter may need '...' instead of '[]', but doesn't need ', '.
54 }
55
56 if (throws_signatures && NumThrowsSignatures())
57 {
58 length += 7; // for " throws"
59 for (unsigned j = 0; j < NumThrowsSignatures(); j++)
60 length += strlen(ThrowsSignature(j)) + 2; // +2 for ", "
61 }
62 else if (NumThrows())
63 {
64 length += 7; // for " throws"
65 for (unsigned j = 0; j < NumThrows(); j++)
66 {
67 TypeSymbol* exception = Throws(j);
68 length += (exception -> ContainingPackage() ->
69 PackageNameLength() +
70 exception -> ExternalNameLength() + 3);
71 // +3 for " throws", '.' after package_name, and ',' and
72 // ' ' to separate this throws clause from the next one
73 }
74 }
75
76 header = new wchar_t[length + 1]; // +1 for '\0'
77 wchar_t* s = header;
78 const wchar_t* s2;
79
80 if (is_constructor)
81 {
82 for (s2 = containing_type -> Name(); *s2; s2++)
83 *s++ = *s2;
84 }
85 else
86 {
87 PackageSymbol* package = Type() -> ContainingPackage();
88 wchar_t* package_name = package -> PackageName();
89 if (package -> PackageNameLength() > 0 &&
90 wcscmp(package_name, StringConstant::US_DOT) != 0)
91 {
92 while (*package_name)
93 {
94 *s++ = (*package_name == U_SLASH ? (wchar_t) U_DOT
95 : *package_name);
96 package_name++;
97 }
98 *s++ = U_DOT;
99 }
100
101 for (s2 = Type() -> ExternalName(); *s2; s2++)
102 *s++ = *s2;
103 *s++ = U_SPACE;
104 for (s2 = Name(); *s2; s2++)
105 *s++ = *s2;
106 }
107 *s++ = U_LEFT_PARENTHESIS;
108 if (num_parameters > 0)
109 {
110 for (unsigned k = 0; k < num_parameters; k++)
111 {
112 VariableSymbol* formal = FormalParameter(k);
113
114 PackageSymbol* package =
115 formal -> Type() -> ContainingPackage();
116 wchar_t* package_name = package -> PackageName();
117 if (package -> PackageNameLength() > 0 &&
118 wcscmp(package_name, StringConstant::US_DOT) != 0)
119 {
120 while (*package_name)
121 {
122 *s++ = (*package_name == U_SLASH ? (wchar_t) U_DOT
123 : *package_name);
124 package_name++;
125 }
126 *s++ = U_DOT;
127 }
128
129 for (s2 = formal -> Type() -> ExternalName(); *s2; s2++)
130 {
131 *s++ = *s2;
132 }
133 if (k == num_parameters - 1 && ACC_VARARGS())
134 {
135 assert(s[-2] == U_LB && s[-1] == U_RB);
136 s[-2] = U_DOT;
137 s[-1] = U_DOT;
138 *s++ = U_DOT;
139 }
140 *s++ = U_SPACE;
141 for (s2 = formal -> Name(); *s2; s2++)
142 *s++ = *s2;
143 *s++ = U_COMMA;
144 *s++ = U_SPACE;
145 }
146
147 s -= 2; // remove the last ',' and ' '
148 }
149 *s++ = U_RIGHT_PARENTHESIS;
150
151 if (throws_signatures && NumThrowsSignatures())
152 {
153 *s++ = U_SPACE;
154 *s++ = U_t;
155 *s++ = U_h;
156 *s++ = U_r;
157 *s++ = U_o;
158 *s++ = U_w;
159 *s++ = U_s;
160 for (unsigned k = 0; k < NumThrowsSignatures(); k++)
161 {
162 *s++ = U_SPACE;
163 for (char* signature = ThrowsSignature(k);
164 *signature; signature++)
165 {
166 *s++ = (*signature == U_SLASH ? (wchar_t) U_DOT
167 : *signature);
168 }
169 *s++ = U_COMMA;
170 }
171 s--; // remove the last ','
172 }
173 else if (NumThrows() > 0)
174 {
175 *s++ = U_SPACE;
176 *s++ = U_t;
177 *s++ = U_h;
178 *s++ = U_r;
179 *s++ = U_o;
180 *s++ = U_w;
181 *s++ = U_s;
182 for (unsigned k = 0; k < NumThrows(); k++)
183 {
184 TypeSymbol* exception = Throws(k);
185
186 PackageSymbol* package = exception -> ContainingPackage();
187 wchar_t* package_name = package -> PackageName();
188 *s++ = U_SPACE;
189 if (package -> PackageNameLength() > 0 &&
190 wcscmp(package_name, StringConstant::US_DOT) != 0)
191 {
192 while (*package_name)
193 {
194 *s++ = (*package_name == U_SLASH ? (wchar_t) U_DOT
195 : *package_name);
196 package_name++;
197 }
198 *s++ = U_DOT;
199 }
200
201 for (s2 = exception -> ExternalName(); *s2; s2++)
202 *s++ = *s2;
203 *s++ = U_COMMA;
204 }
205
206 s--; // remove the last ','
207 }
208
209 *s++ = U_SEMICOLON;
210 *s = U_NULL;
211
212 assert((s - header) <= length);
213 }
214 return header;
215 }
216
SetLocation()217 void MethodSymbol::SetLocation()
218 {
219 //AstMethodDeclaration or AstConstructorDeclaration
220 if (! declaration)
221 file_location = new FileLocation(containing_type -> file_symbol);
222 else
223 {
224 AstMethodDeclaration* method_declaration =
225 declaration -> MethodDeclarationCast();
226 AstConstructorDeclaration* constructor_declaration =
227 declaration -> ConstructorDeclarationCast();
228
229 file_location =
230 new FileLocation((containing_type -> semantic_environment ->
231 sem -> lex_stream),
232 (method_declaration
233 ? method_declaration -> LeftToken()
234 : constructor_declaration -> LeftToken()));
235 }
236 }
237
FindOverloadMethod(MethodSymbol * base_method,AstMethodDeclarator * method_declarator)238 MethodSymbol* SymbolTable::FindOverloadMethod(MethodSymbol* base_method,
239 AstMethodDeclarator* method_declarator)
240 {
241 for (MethodSymbol* method = base_method; method;
242 method = method -> next_method)
243 {
244 assert(method -> IsTyped());
245
246 if (method -> NumFormalParameters() ==
247 method_declarator -> NumFormalParameters())
248 {
249 int i;
250 for (i = method -> NumFormalParameters() - 1; i >= 0; i--)
251 {
252 AstFormalParameter* parameter =
253 method_declarator -> FormalParameter(i);
254 if (method -> FormalParameter(i) -> Type() !=
255 parameter -> formal_declarator -> symbol -> Type())
256 {
257 break;
258 }
259 }
260 if (i < 0)
261 return method;
262 }
263 }
264 return NULL;
265 }
266
267
ProcessTypeHeaders()268 void TypeSymbol::ProcessTypeHeaders()
269 {
270 semantic_environment -> sem -> ProcessTypeHeaders(declaration);
271 }
272
ProcessMembers()273 void TypeSymbol::ProcessMembers()
274 {
275 semantic_environment -> sem -> ProcessMembers(declaration);
276 }
277
CompleteSymbolTable()278 void TypeSymbol::CompleteSymbolTable()
279 {
280 semantic_environment -> sem -> CompleteSymbolTable(declaration);
281 }
282
283
ProcessExecutableBodies()284 void TypeSymbol::ProcessExecutableBodies()
285 {
286 semantic_environment -> sem -> ProcessExecutableBodies(declaration);
287 }
288
289
RemoveCompilationReferences()290 void TypeSymbol::RemoveCompilationReferences()
291 {
292 if (semantic_environment)
293 {
294 semantic_environment = NULL;
295 declaration = NULL;
296
297 //
298 // TODO: What else needs to be reset?
299 //
300 if (table)
301 {
302 unsigned i;
303 for (i = 0; i < table -> NumVariableSymbols(); i++)
304 table -> VariableSym(i) -> declarator = NULL;
305 for (i = 0; i < table -> NumMethodSymbols(); i++)
306 table -> MethodSym(i) -> declaration = NULL;
307 for (i = 0; i < table -> NumTypeSymbols(); i++)
308 table -> TypeSym(i) -> declaration = NULL;
309 for (i = 0; i < table -> NumAnonymousSymbols(); i++)
310 table -> AnonymousSym(i) -> declaration = NULL;
311 }
312 }
313 }
314
315
GetArrayType(Semantic * sem,unsigned dims)316 TypeSymbol* TypeSymbol::GetArrayType(Semantic* sem, unsigned dims)
317 {
318 if (dims == num_dimensions)
319 return this;
320 if (num_dimensions)
321 return base_type -> GetArrayType(sem, dims);
322 if (! dims || Bad())
323 return this;
324 if (dims < NumArrays())
325 return Array(dims);
326
327 if (NumArrays() == 0)
328 AddArrayType(this);
329 TypeSymbol* previous_array_type = Array(array -> Length() - 1);
330 wchar_t* name = new wchar_t[ExternalNameLength() + (dims * 2) + 1];
331 wcscpy(name, previous_array_type -> ExternalName());
332
333 for (unsigned num = array -> Length(),
334 len = previous_array_type -> ExternalNameLength() + 2;
335 num <= dims;
336 num++, len = len + 2)
337 {
338 wcscat(name, StringConstant::US_LB_RB);
339 NameSymbol* name_sym = sem -> control.FindOrInsertName(name, len);
340 TypeSymbol* type = new TypeSymbol(name_sym);
341
342 type -> MarkHeaderProcessed();
343 type -> MarkConstructorMembersProcessed();
344 type -> MarkMethodMembersProcessed();
345 type -> MarkFieldMembersProcessed();
346 type -> MarkLocalClassProcessingCompleted();
347 type -> MarkSourceNoLongerPending();
348 type -> outermost_type = type;
349
350 //
351 // An array type has the same accessibility as its component.
352 //
353 if (ACC_PUBLIC())
354 type -> SetACC_PUBLIC();
355 else if (ACC_PROTECTED())
356 type -> SetACC_PROTECTED();
357 else if (ACC_PRIVATE())
358 type -> SetACC_PRIVATE();
359 type -> SetACC_FINAL();
360
361 type -> super = sem -> control.Object();
362 //
363 // All arrays implement the interfaces java.io.Serializable and
364 // java.io.Cloneable
365 //
366 type -> AddInterface(sem -> control.Serializable());
367 type -> AddInterface(sem -> control.Cloneable());
368 type -> base_type = this;
369 type -> num_dimensions = num;
370 type -> SetOwner(ContainingPackage());
371 // only 2 elements will be added to this table
372 type -> table = new SymbolTable(2);
373 type -> SetSignature(sem -> control);
374
375 MethodSymbol* method =
376 type -> InsertMethodSymbol(sem -> control.clone_name_symbol);
377 method -> SetType(sem -> control.Object());
378 method -> SetContainingType(type);
379 method -> SetFlags(ACCESS_PUBLIC | ACCESS_FINAL);
380 // the associated symbol table will remain empty
381 method -> SetBlockSymbol(new BlockSymbol(1));
382 method -> SetSignature(sem -> control);
383
384 VariableSymbol* symbol =
385 type -> InsertVariableSymbol(sem -> control.length_name_symbol);
386 symbol -> SetFlags(ACCESS_PUBLIC | ACCESS_FINAL);
387 symbol -> SetOwner(type);
388 symbol -> SetType(sem -> control.int_type);
389 symbol -> MarkComplete();
390 symbol -> MarkInitialized();
391
392 type -> CompressSpace(); // space optimization
393 AddArrayType(type);
394 }
395
396 delete [] name;
397 return Array(dims);
398 }
399
SetLocation()400 void TypeSymbol::SetLocation()
401 {
402 if (! declaration)
403 file_location = new FileLocation(file_symbol);
404 else
405 {
406 file_location =
407 new FileLocation(semantic_environment -> sem -> lex_stream,
408 declaration -> identifier_token);
409 }
410 }
411
SetSignature(Control & control)412 void TypeSymbol::SetSignature(Control& control)
413 {
414 if (num_dimensions > 0)
415 {
416 char* type_signature;
417 TypeSymbol* subtype = ArraySubtype();
418 // +1 for '['
419 int signature_len = strlen(subtype -> SignatureString()) + 1;
420 type_signature = new char[signature_len + 1];
421 type_signature[0] = U_LEFT_BRACKET;
422 strcpy(type_signature + 1, subtype -> SignatureString());
423 signature = control.Utf8_pool.FindOrInsert(type_signature,
424 signature_len);
425 fully_qualified_name = signature;
426 delete [] type_signature;
427 }
428 else
429 {
430 const wchar_t* package_name = ContainingPackageName();
431 const wchar_t* type_name = ExternalName();
432
433 // +1 for 'L' +1 for '/' +1 for ';' +1 for '\0'
434 int len = ContainingPackage() -> PackageNameLength() +
435 ExternalNameLength() + 4;
436 wchar_t* type_signature = new wchar_t[len];
437 type_signature[0] = U_L;
438 type_signature[1] = U_NU;
439 if (ContainingPackage() -> PackageNameLength() > 0 &&
440 wcscmp(package_name, StringConstant::US_DOT) != 0)
441 {
442 wcscat(type_signature, package_name);
443 wcscat(type_signature, StringConstant::US_SL);
444 }
445 wcscat(type_signature, type_name);
446 // +1 to skip the initial L'L'
447 fully_qualified_name =
448 control.ConvertUnicodeToUtf8(type_signature + 1);
449
450 wcscat(type_signature, StringConstant::US_SC);
451 signature = control.ConvertUnicodeToUtf8(type_signature);
452
453 delete [] type_signature;
454
455 if (! (Anonymous() || IsLocal()))
456 control.type_table.InsertType(this);
457 }
458 }
459
460
461 unsigned SymbolTable::primes[] = {DEFAULT_HASH_SIZE, 101, 401, MAX_HASH_SIZE};
462
Rehash()463 void SymbolTable::Rehash()
464 {
465 hash_size = primes[++prime_index];
466
467 delete [] base;
468 base = (Symbol**) memset(new Symbol*[hash_size], 0,
469 hash_size * sizeof(Symbol*));
470
471 unsigned k;
472 for (k = 0; k < NumTypeSymbols(); k++)
473 {
474 TypeSymbol* symbol = TypeSym(k);
475 int i = symbol -> name_symbol -> index % hash_size;
476 symbol -> next = base[i];
477 base[i] = symbol;
478 }
479
480 for (k = 0; k < NumMethodSymbols(); k++)
481 {
482 MethodSymbol* symbol = MethodSym(k);
483 if (symbol -> next != symbol) // not an overload
484 {
485 int i = symbol -> name_symbol -> index % hash_size;
486 symbol -> next = base[i];
487 base[i] = symbol;
488 }
489 }
490
491 for (k = 0; k < NumVariableSymbols(); k++)
492 {
493 VariableSymbol* symbol = VariableSym(k);
494 int i = symbol -> name_symbol -> index % hash_size;
495 symbol -> next = base[i];
496 base[i] = symbol;
497 }
498
499 for (k = 0; k < NumOtherSymbols(); k++)
500 {
501 Symbol* symbol = OtherSym(k);
502
503 if (! symbol -> BlockCast())
504 {
505 int i = symbol -> Identity() -> index % hash_size;
506 symbol -> next = base[i];
507 base[i] = symbol;
508 }
509 }
510 }
511
512
SymbolTable(unsigned hash_size_)513 SymbolTable::SymbolTable(unsigned hash_size_)
514 : type_symbol_pool(NULL)
515 , anonymous_symbol_pool(NULL)
516 , method_symbol_pool(NULL)
517 , variable_symbol_pool(NULL)
518 , other_symbol_pool(NULL)
519 {
520 hash_size = (hash_size_ <= 0 ? 1 : hash_size_);
521
522 prime_index = -1;
523 do
524 {
525 if (hash_size < primes[prime_index + 1])
526 break;
527 prime_index++;
528 } while (primes[prime_index] < MAX_HASH_SIZE);
529
530 base = (Symbol**) memset(new Symbol*[hash_size], 0,
531 hash_size * sizeof(Symbol*));
532 }
533
~SymbolTable()534 SymbolTable::~SymbolTable()
535 {
536 unsigned i;
537 for (i = 0; i < NumAnonymousSymbols(); i++)
538 delete AnonymousSym(i);
539 delete anonymous_symbol_pool;
540 for (i = 0; i < NumTypeSymbols(); i++)
541 delete TypeSym(i);
542 delete type_symbol_pool;
543 for (i = 0; i < NumMethodSymbols(); i++)
544 delete MethodSym(i);
545 delete method_symbol_pool;
546 for (i = 0; i < NumVariableSymbols(); i++)
547 delete VariableSym(i);
548 delete variable_symbol_pool;
549 for (i = 0; i < NumOtherSymbols(); i++)
550 delete OtherSym(i);
551 delete other_symbol_pool;
552 delete [] base;
553 }
554
555
~PackageSymbol()556 PackageSymbol::~PackageSymbol()
557 {
558 delete [] package_name;
559 delete table;
560 }
561
562
SetPackageName()563 void PackageSymbol::SetPackageName()
564 {
565 package_name_length = (owner ? owner -> PackageNameLength() + 1 : 0) +
566 NameLength(); // +1 for '/'
567 package_name = new wchar_t[package_name_length + 1]; // +1 for '\0'
568
569 if (owner)
570 {
571 wcscpy(package_name, owner -> PackageName());
572 wcscat(package_name, StringConstant::US_SL);
573 }
574 else package_name[0] = U_NULL;
575 wcscat(package_name, Name());
576
577 assert(wcslen(package_name) == package_name_length);
578 }
579
580
TypeSymbol(const NameSymbol * name_symbol_)581 TypeSymbol::TypeSymbol(const NameSymbol* name_symbol_)
582 : semantic_environment(NULL),
583 declaration(NULL),
584 file_symbol(NULL),
585 file_location(NULL),
586 name_symbol(name_symbol_),
587 owner(NULL),
588 outermost_type(NULL),
589 super(NULL),
590 base_type(NULL),
591 index(TypeCycleChecker::OMEGA),
592 unit_index(TypeCycleChecker::OMEGA),
593 incremental_index(TypeCycleChecker::OMEGA),
594 local(NULL),
595 non_local(NULL),
596 supertypes_closure(NULL),
597 subtypes(NULL),
598 subtypes_closure(NULL),
599 innertypes_closure(NULL),
600 dependents(new SymbolSet()),
601 parents(new SymbolSet()),
602 static_parents(new SymbolSet()),
603 dependents_closure(NULL),
604 parents_closure(NULL),
605 signature(NULL),
606 fully_qualified_name(NULL),
607 expanded_type_table(NULL),
608 expanded_field_table(NULL),
609 expanded_method_table(NULL),
610 num_dimensions(0),
611 instance_initializer_method(NULL),
612 static_initializer_method(NULL),
613 external_name_symbol(NULL),
614 table(NULL),
615 local_shadow_map(NULL),
616 status(0),
617 package(NULL),
618 class_name(NULL),
619 class_literal_method(NULL),
620 class_literal_name(NULL),
621 assert_variable(NULL),
622 local_constructor_call_environments(NULL),
623 private_access_methods(NULL),
624 private_access_constructors(NULL),
625 read_methods(NULL),
626 write_methods(NULL),
627 placeholder_type(NULL),
628 constructor_parameters(NULL),
629 enclosing_instance(NULL),
630 class_literals(NULL),
631 nested_type_signatures(NULL),
632 nested_types(NULL),
633 interfaces(NULL),
634 anonymous_types(NULL),
635 array(NULL)
636 {
637 Symbol::_kind = TYPE;
638 }
639
NumLocalTypes()640 unsigned TypeSymbol::NumLocalTypes()
641 {
642 return local ? local -> Size() : 0;
643 }
644
645
~TypeSymbol()646 TypeSymbol::~TypeSymbol()
647 {
648 unsigned i;
649 delete read_methods;
650 delete write_methods;
651 delete semantic_environment;
652 delete local;
653 delete non_local;
654 delete supertypes_closure;
655 delete subtypes;
656 delete subtypes_closure;
657 delete innertypes_closure;
658 delete dependents;
659 delete parents;
660 delete static_parents;
661 delete table;
662 delete local_shadow_map;
663 delete expanded_type_table;
664 delete expanded_field_table;
665 delete expanded_method_table;
666 delete file_location;
667 delete [] class_name;
668 for (i = 1; i < NumArrays(); i++)
669 delete Array(i);
670 for (i = 0; i < NumNestedTypeSignatures(); i++)
671 delete [] NestedTypeSignature(i);
672 delete nested_type_signatures;
673
674 delete local_constructor_call_environments;
675 delete private_access_methods;
676 delete private_access_constructors;
677 delete constructor_parameters;
678 delete class_literals;
679 delete nested_types;
680 delete interfaces;
681 delete anonymous_types;
682 delete array;
683 }
684
685
UnlinkFromParents()686 void TypeSymbol::UnlinkFromParents()
687 {
688 if (super)
689 {
690 super -> subtypes -> RemoveElement(this);
691 super -> dependents -> RemoveElement(this);
692 }
693 if (interfaces)
694 {
695 for (unsigned i = 0; i < NumInterfaces(); ++i)
696 {
697 TypeSymbol* interf = Interface(i);
698 interf -> subtypes -> RemoveElement(this);
699 interf -> dependents -> RemoveElement(this);
700 }
701 }
702 }
703
704
~MethodSymbol()705 MethodSymbol::~MethodSymbol()
706 {
707 for (unsigned i = 0; i < NumThrowsSignatures(); i++)
708 delete [] ThrowsSignature(i);
709 delete throws_signatures;
710 delete formal_parameters;
711 delete throws;
712
713 delete block_symbol; // overload(s)
714 delete [] header;
715 }
716
717
BlockSymbol(unsigned hash_size)718 BlockSymbol::BlockSymbol(unsigned hash_size)
719 : max_variable_index(-1)
720 , helper_variable_index(-1)
721 , table(hash_size > 0 ? new SymbolTable(hash_size) : (SymbolTable*) NULL)
722 {
723 Symbol::_kind = BLOCK;
724 }
725
~BlockSymbol()726 BlockSymbol::~BlockSymbol()
727 {
728 delete table;
729 }
730
PathSymbol(const NameSymbol * name_symbol_)731 PathSymbol::PathSymbol(const NameSymbol* name_symbol_)
732 : name_symbol(name_symbol_)
733 , zipfile(NULL)
734 {
735 Symbol::_kind = PATH;
736 }
737
~PathSymbol()738 PathSymbol::~PathSymbol()
739 {
740 if (zipfile)
741 delete zipfile;
742 }
743
DirectorySymbol(const NameSymbol * name_symbol_,Symbol * owner_,bool source_dir_only_)744 DirectorySymbol::DirectorySymbol(const NameSymbol* name_symbol_,
745 Symbol* owner_, bool source_dir_only_)
746 : owner(owner_)
747 , name_symbol(name_symbol_)
748 , mtime(0)
749 , table(NULL)
750 , entries(NULL)
751 , directory_name(NULL)
752 , source_dir_only(source_dir_only_)
753 {
754 Symbol::_kind = _DIRECTORY;
755 }
756
757
758
759
~DirectorySymbol()760 DirectorySymbol::~DirectorySymbol()
761 {
762 delete [] directory_name;
763 delete entries;
764 delete table;
765 }
766
SetDirectoryName()767 void DirectorySymbol::SetDirectoryName()
768 {
769 PathSymbol* path_symbol = owner -> PathCast();
770 if (path_symbol)
771 {
772 if (strcmp(path_symbol -> Utf8Name(), ".") == 0)
773 {
774 directory_name_length = Utf8NameLength();
775 directory_name = new char[directory_name_length + 1]; // +1: '\0'
776
777 strcpy(directory_name, Utf8Name());
778 }
779 else
780 {
781 directory_name_length = path_symbol -> Utf8NameLength();
782 directory_name = new char[directory_name_length + 1]; // +1: '\0'
783
784 strcpy(directory_name, path_symbol -> Utf8Name());
785 }
786 }
787 else
788 {
789 DirectorySymbol* owner_directory = owner -> DirectoryCast();
790 if (Name()[NameLength() - 1] == U_SLASH ||
791 strcmp(owner_directory -> DirectoryName(), ".") == 0)
792 {
793 // An absolute file name, or is the owner "." ?
794 directory_name_length = Utf8NameLength();
795 directory_name = new char[directory_name_length + 1]; // +1: '\0'
796 strcpy(directory_name, Utf8Name());
797 }
798 else
799 {
800 int owner_length = owner_directory -> DirectoryNameLength();
801 char* owner_name = owner_directory -> DirectoryName();
802 directory_name_length = owner_length + Utf8NameLength() +
803 (owner_name[owner_length - 1] != U_SLASH ? 1 : 0); // +1: '/'
804
805 directory_name = new char[directory_name_length + 1]; // +1: '\0'
806
807 strcpy(directory_name, owner_directory -> DirectoryName());
808 if (owner_name[owner_length - 1] != U_SLASH)
809 strcat(directory_name, StringConstant::U8S_SL);
810 strcat(directory_name, Utf8Name());
811 }
812 }
813
814 assert(strlen(directory_name) == directory_name_length);
815 }
816
817
ResetDirectory()818 void DirectorySymbol::ResetDirectory()
819 {
820 //
821 // TODO: the stat function does not work for directories in that the
822 // "modified" time stamp associated with a directory is not updated when
823 // a file contained in the directory is changed.
824 // For now, we always reread the directory.
825 //
826 // struct stat status;
827 // if ((SystemStat(DirectoryName(), &status) == 0) &&
828 // status.st_mtime > mtime)
829 // {
830 // mtime = status.st_mtime;
831 //
832 // delete entries;
833 // entries = NULL;
834 // }
835 //
836 // ReadDirectory();
837 //
838
839 delete entries;
840 entries = NULL;
841 ReadDirectory();
842 }
843
844
ReadDirectory()845 void DirectorySymbol::ReadDirectory()
846 {
847 assert(! IsZip());
848
849 if (! entries)
850 {
851 entries = new DirectoryTable();
852
853 //FIXME: these need to go into platform.cpp
854 #ifdef UNIX_FILE_SYSTEM
855 DIR* directory = opendir(DirectoryName());
856 if (directory)
857 {
858 for (dirent* entry = readdir(directory); entry;
859 entry = readdir(directory))
860 {
861 unsigned length = strlen(entry -> d_name);
862
863 //
864 // Check if the file is a java source, a java class file or a
865 // subdirectory. Since packages cannot start with '.', we skip
866 // all files that start with a dot. That includes this
867 // directory "." and its parent ".."
868 //
869 // Don't add the class file if the source_dir_only flag is set.
870 if ((length > FileSymbol::java_suffix_length &&
871 FileSymbol::IsJavaSuffix(&entry -> d_name[length - FileSymbol::java_suffix_length])) ||
872 (! source_dir_only && length > FileSymbol::class_suffix_length &&
873 FileSymbol::IsClassSuffix(&entry -> d_name[length - FileSymbol::class_suffix_length])) ||
874 (Case::Index(entry -> d_name, U_DOT) < 0 &&
875 SystemIsDirectory(entry -> d_name)))
876 {
877 int len = DirectoryNameLength() + strlen(entry -> d_name);
878 char* filename = new char[len + 2]; // +2 for '/', NUL
879 sprintf(filename, "%s/%s", DirectoryName(),
880 entry -> d_name);
881 struct stat status;
882 if(JikesAPI::getInstance() -> stat(filename, &status) == 0)
883 entries -> InsertEntry(this, entry -> d_name, length);
884 delete [] filename;
885 }
886 }
887 closedir(directory);
888 }
889
890 #elif defined(WIN32_FILE_SYSTEM)
891
892 // +2 for "/*" +1 for '\0'
893 int dir_name_len = DirectoryNameLength();
894 char* directory_name = new char[dir_name_len + 3];
895 strcpy(directory_name, DirectoryName());
896 if (directory_name[dir_name_len - 1] != U_SLASH)
897 directory_name[dir_name_len++] = U_SLASH;
898 directory_name[dir_name_len++] = U_STAR;
899 directory_name[dir_name_len] = U_NULL;
900
901 WIN32_FIND_DATA entry;
902 HANDLE file_handle = FindFirstFile(directory_name, &entry);
903 if (file_handle != INVALID_HANDLE_VALUE)
904 {
905 do
906 {
907 unsigned length = strlen(entry.cFileName);
908
909 //
910 // Check if the file is a java source, a java class file or a
911 // subdirectory. Since packages cannot start with '.', we skip
912 // all files that start with a dot. That includes this
913 // directory "." and its parent ".."
914 //
915 bool is_java = (length > FileSymbol::java_suffix_length &&
916 FileSymbol::IsJavaSuffix(&entry.cFileName[length - FileSymbol::java_suffix_length])),
917 is_class = (! source_dir_only &&
918 length > FileSymbol::class_suffix_length &&
919 FileSymbol::IsClassSuffix(&entry.cFileName[length - FileSymbol::class_suffix_length]));
920
921 if (is_java ||
922 is_class ||
923 (entry.dwFileAttributes == FILE_ATTRIBUTE_DIRECTORY &&
924 Case::Index(entry.cFileName, U_DOT) < 0))
925 {
926 char* clean_name = new char[length + 1];
927 for (unsigned i = 0; i < length; i++)
928 {
929 clean_name[i] = entry.cFileName[i] == U_BACKSLASH
930 ? (char) U_SLASH : entry.cFileName[i];
931 }
932 if (is_java)
933 strcpy(&clean_name[length - FileSymbol::java_suffix_length],
934 FileSymbol::java_suffix);
935 else if (is_class)
936 strcpy(&clean_name[length - FileSymbol::class_suffix_length],
937 FileSymbol::class_suffix);
938 DirectoryEntry* entry =
939 entries -> InsertEntry(this, clean_name, length);
940 if (! is_java)
941 entries -> InsertCaseInsensitiveEntry(entry);
942 delete [] clean_name;
943 }
944 } while (FindNextFile(file_handle, &entry));
945 FindClose(file_handle);
946 }
947
948 delete [] directory_name;
949 #endif
950 }
951 }
952
953
OutputDirectory()954 DirectorySymbol* FileSymbol::OutputDirectory()
955 {
956 return output_directory ? output_directory
957 : output_directory = Control::GetOutputDirectory(this);
958 }
959
960
~FileSymbol()961 FileSymbol::~FileSymbol()
962 {
963 delete [] file_name;
964 delete lex_stream;
965 }
966
967
SetFileName()968 void FileSymbol::SetFileName()
969 {
970 PathSymbol* path_symbol = PathSym();
971 char* directory_name = directory_symbol -> DirectoryName();
972 size_t directory_name_length = directory_symbol -> DirectoryNameLength();
973 bool dot_directory = (strcmp(directory_name, ".") == 0);
974 file_name_length = (dot_directory ? 0 : directory_name_length) +
975 Utf8NameLength() +
976 (path_symbol -> IsZip() ? 2 // For zip files, we need "()";
977 : (dot_directory || // for regular directory, we need 1 '/'
978 directory_name[directory_name_length - 1] == U_SLASH ? 0 : 1)) +
979 (kind == JAVA ? java_suffix_length : class_suffix_length);
980
981 file_name = new char[file_name_length + 1]; // +1 for '\0'
982 if (dot_directory)
983 file_name[0] = U_NULL;
984 else
985 {
986 strcpy(file_name, directory_symbol -> DirectoryName());
987 if (path_symbol -> IsZip())
988 strcat(file_name, StringConstant::U8S_LP);
989 else if (directory_name[directory_name_length - 1] != U_SLASH)
990 strcat(file_name, StringConstant::U8S_SL);
991 }
992 strcat(file_name, Utf8Name());
993 strcat(file_name, kind == JAVA ? FileSymbol::java_suffix
994 : FileSymbol::class_suffix);
995 if (path_symbol -> IsZip())
996 strcat(file_name, StringConstant::U8S_RP);
997
998 assert(strlen(file_name) == file_name_length);
999 }
1000
1001 #ifdef UNIX_FILE_SYSTEM
IsClassSuffix(char * suffix)1002 bool FileSymbol::IsClassSuffix(char* suffix)
1003 {
1004 return strncmp(suffix, class_suffix, class_suffix_length) == 0;
1005 }
1006
IsJavaSuffix(char * suffix)1007 bool FileSymbol::IsJavaSuffix(char* suffix)
1008 {
1009 return strncmp(suffix, java_suffix, java_suffix_length) == 0;
1010 }
1011 #elif defined(WIN32_FILE_SYSTEM)
IsClassSuffix(char * suffix)1012 bool FileSymbol::IsClassSuffix(char* suffix)
1013 {
1014 return Case::StringSegmentEqual(suffix, class_suffix, class_suffix_length);
1015 }
1016
IsJavaSuffix(char * suffix)1017 bool FileSymbol::IsJavaSuffix(char* suffix)
1018 {
1019 return Case::StringSegmentEqual(suffix, java_suffix, java_suffix_length);
1020 }
1021 #endif // WIN32_FILE_SYSTEM
1022
SetFileNameLiteral(Control * control)1023 void FileSymbol::SetFileNameLiteral(Control* control)
1024 {
1025 if (! file_name_literal)
1026 {
1027 char* file_name = FileName();
1028
1029 int i;
1030 for (i = FileNameLength() - 1; i >= 0; i--)
1031 {
1032 if (file_name[i] == U_SLASH)
1033 break;
1034 }
1035
1036 int file_name_start = i + 1;
1037 int file_name_length = FileNameLength() - file_name_start;
1038 file_name_literal =
1039 control -> Utf8_pool.FindOrInsert(file_name + file_name_start,
1040 file_name_length);
1041 }
1042 }
1043
1044
CleanUp()1045 void FileSymbol::CleanUp()
1046 {
1047 delete lex_stream;
1048 lex_stream = NULL;
1049
1050 if (compilation_unit)
1051 {
1052 delete compilation_unit -> ast_pool;
1053 compilation_unit = NULL;
1054 }
1055
1056 delete semantic;
1057 semantic = NULL;
1058 }
1059
1060
FileLocation(LexStream * lex_stream,TokenIndex token_index)1061 FileLocation::FileLocation(LexStream* lex_stream, TokenIndex token_index)
1062 {
1063 char* file_name = lex_stream -> FileName();
1064 unsigned length = lex_stream -> FileNameLength();
1065 location = new wchar_t[length + 13];
1066 for (unsigned i = 0; i < length; i++)
1067 location[i] = (wchar_t) file_name[i];
1068 location[length++] = U_COLON;
1069
1070 IntToWstring line_no(lex_stream -> Line(token_index));
1071
1072 for (int j = 0; j < line_no.Length(); j++)
1073 location[length++] = line_no.String()[j];
1074 location[length] = U_NULL;
1075 }
1076
1077
SetClassName()1078 void TypeSymbol::SetClassName()
1079 {
1080 size_t length;
1081
1082 if (semantic_environment -> sem -> control.option.directory)
1083 {
1084 DirectorySymbol* output_directory = file_symbol -> OutputDirectory();
1085 int directory_length = output_directory -> DirectoryNameLength();
1086 char* directory_name = output_directory -> DirectoryName();
1087 length = directory_length + ExternalUtf8NameLength() +
1088 FileSymbol::class_suffix_length + 1; // +1 for /
1089 class_name = new char[length + 1]; // +1 for '\0'
1090
1091 strcpy(class_name, directory_name);
1092
1093 if (directory_name[directory_length - 1] != U_SLASH)
1094 strcat(class_name, StringConstant::U8S_SL);
1095 }
1096 else
1097 {
1098 char* file_name =
1099 semantic_environment -> sem -> lex_stream -> FileName();
1100 int n;
1101 for (n = semantic_environment -> sem -> lex_stream ->
1102 FileNameLength() - 1;
1103 n >= 0; n--)
1104 {
1105 if (file_name[n] == U_SLASH)
1106 break;
1107 }
1108 n++;
1109
1110 length =
1111 n + ExternalUtf8NameLength() + FileSymbol::class_suffix_length;
1112 class_name = new char[length + 1]; // +1 for '\0'
1113 strncpy(class_name, file_name, n);
1114 class_name[n] = U_NULL;
1115 }
1116
1117 strcat(class_name, ExternalUtf8Name());
1118 strcat(class_name, FileSymbol::class_suffix);
1119
1120 assert(strlen(class_name) <= length);
1121 }
1122
1123
ProcessNestedTypeSignatures(Semantic * sem,TokenIndex tok)1124 void TypeSymbol::ProcessNestedTypeSignatures(Semantic* sem, TokenIndex tok)
1125 {
1126 for (unsigned i = 0; i < NumNestedTypeSignatures(); i++)
1127 {
1128 NameSymbol* name_symbol = sem ->
1129 control.ConvertUtf8ToUnicode(NestedTypeSignature(i),
1130 strlen(NestedTypeSignature(i)));
1131 delete [] NestedTypeSignature(i);
1132 sem -> ProcessNestedType(this, name_symbol, tok);
1133 }
1134
1135 delete nested_type_signatures;
1136 nested_type_signatures = NULL;
1137 }
1138
1139
ProcessMethodThrows(Semantic * sem,TokenIndex tok)1140 void MethodSymbol::ProcessMethodThrows(Semantic* sem, TokenIndex tok)
1141 {
1142 if (throws_signatures)
1143 {
1144 assert(sem);
1145
1146 //
1147 // Process throws clause
1148 //
1149 for (unsigned i = 0; i < NumThrowsSignatures(); i++)
1150 {
1151 TypeSymbol* type =
1152 sem -> ReadTypeFromSignature(containing_type,
1153 ThrowsSignature(i),
1154 strlen(ThrowsSignature(i)),
1155 tok);
1156 AddThrows(type);
1157 delete [] ThrowsSignature(i);
1158 }
1159
1160 delete throws_signatures;
1161 throws_signatures = NULL;
1162 }
1163 }
1164
1165
1166 //
1167 // In addition to (re)setting the signature, this updates the
1168 // max_variable_index if needed.
1169 //
SetSignature(Control & control,TypeSymbol * placeholder)1170 void MethodSymbol::SetSignature(Control& control, TypeSymbol* placeholder)
1171 {
1172 unsigned i;
1173 bool is_constructor = Identity() == control.init_name_symbol;
1174 int len = is_constructor ? 3 : 2 + strlen(Type() -> SignatureString());
1175 // +1 for '(' +1 for ')'; constructors have type 'V'
1176
1177 TypeSymbol* this0_type = containing_type -> EnclosingType();
1178 int variable_index = ACC_STATIC() ? 0 : 1;
1179
1180 if (is_constructor && this0_type)
1181 {
1182 len += strlen(this0_type -> SignatureString());
1183 variable_index++;
1184 }
1185 for (i = 0; i < NumFormalParameters(); i++)
1186 {
1187 TypeSymbol* formal_type = FormalParameter(i) -> Type();
1188 len += strlen(formal_type -> SignatureString());
1189 variable_index += (control.IsDoubleWordType(formal_type) ? 2 : 1);
1190 }
1191 if (is_constructor)
1192 {
1193 for (i = 0; i < containing_type -> NumConstructorParameters(); i++)
1194 {
1195 TypeSymbol* shadow_type =
1196 containing_type -> ConstructorParameter(i) -> Type();
1197 len += strlen(shadow_type -> SignatureString());
1198 variable_index += (control.IsDoubleWordType(shadow_type) ? 2 : 1);
1199 }
1200 if (placeholder)
1201 {
1202 len += strlen(placeholder -> SignatureString());
1203 variable_index++;
1204 }
1205 }
1206 if (block_symbol && variable_index > block_symbol -> max_variable_index)
1207 block_symbol -> max_variable_index = variable_index;
1208
1209 char* method_signature = new char[len + 1]; // +1 for '\0'
1210 method_signature[0] = U_LEFT_PARENTHESIS;
1211 int s = 1;
1212 if (is_constructor && this0_type)
1213 {
1214 for (const char* str = this0_type -> SignatureString();
1215 *str; str++, s++)
1216 {
1217 method_signature[s] = *str;
1218 }
1219 }
1220 for (i = 0; i < NumFormalParameters(); i++)
1221 {
1222 TypeSymbol* formal_type = FormalParameter(i) -> Type();
1223 for (const char* str = formal_type -> SignatureString();
1224 *str; str++, s++)
1225 {
1226 method_signature[s] = *str;
1227 }
1228 }
1229 if (is_constructor)
1230 {
1231 for (i = 0; i < containing_type -> NumConstructorParameters(); i++)
1232 {
1233 TypeSymbol* shadow_type =
1234 containing_type -> ConstructorParameter(i) -> Type();
1235 for (const char* str = shadow_type -> SignatureString();
1236 *str; str++, s++)
1237 {
1238 method_signature[s] = *str;
1239 }
1240 }
1241 if (placeholder)
1242 for (const char* str = placeholder -> SignatureString();
1243 *str; str++, s++)
1244 {
1245 method_signature[s] = *str;
1246 }
1247 }
1248 method_signature[s++] = U_RIGHT_PARENTHESIS;
1249 if (is_constructor)
1250 {
1251 assert(Type() == containing_type);
1252 method_signature[s++] = U_V;
1253 }
1254 else
1255 {
1256 for (const char* str = Type() -> SignatureString(); *str; str++, s++)
1257 method_signature[s] = *str;
1258 }
1259 method_signature[s] = U_NULL;
1260
1261 signature = control.Utf8_pool.FindOrInsert(method_signature, len);
1262
1263 delete [] method_signature;
1264 }
1265
1266
ProcessMethodSignature(Semantic * sem,TokenIndex token_location)1267 void MethodSymbol::ProcessMethodSignature(Semantic* sem,
1268 TokenIndex token_location)
1269 {
1270 if (! type_)
1271 {
1272 assert(sem);
1273
1274 int num_parameters = 0;
1275 const char* signature = SignatureString();
1276 assert(*signature == U_LEFT_PARENTHESIS);
1277 signature++; // +1 to skip initial '('
1278
1279 //
1280 // For the constructor of an inner type, skip the "this$0" argument.
1281 //
1282 if (containing_type -> EnclosingType() &&
1283 ! containing_type -> EnclosingType() -> ACC_PRIVATE() &&
1284 Identity() == sem -> control.init_name_symbol)
1285 {
1286 TypeSymbol* enclosing = sem -> ProcessSignature(containing_type,
1287 signature,
1288 token_location);
1289 assert(enclosing == containing_type -> EnclosingType());
1290 }
1291
1292 while (*signature && *signature != U_RIGHT_PARENTHESIS)
1293 {
1294 //
1295 // Make up a name for each parameter.
1296 //
1297 NameSymbol* name_symbol =
1298 sem -> control.MakeParameter(++num_parameters);
1299 VariableSymbol* symbol = new VariableSymbol(name_symbol);
1300 symbol -> SetType(sem -> ProcessSignature(containing_type,
1301 signature,
1302 token_location));
1303 symbol -> MarkComplete();
1304 AddFormalParameter(symbol);
1305 }
1306 assert(*signature == U_RIGHT_PARENTHESIS);
1307 signature++; // skip ')'
1308
1309 //
1310 // Now set the type of the method.
1311 //
1312 if (Identity() == sem -> control.init_name_symbol)
1313 {
1314 assert(*signature++ == U_V);
1315 SetType(containing_type);
1316 }
1317 else
1318 {
1319 SetType(sem -> ProcessSignature(containing_type, signature,
1320 token_location));
1321 }
1322 assert(! *signature);
1323
1324 //
1325 // Create a symbol table for this method for consistency, and in
1326 // order to release the space used by the variable paramaters later.
1327 //
1328 BlockSymbol* block_symbol = new BlockSymbol(num_parameters);
1329 for (int k = 0; k < num_parameters; k++)
1330 block_symbol -> InsertVariableSymbol((*formal_parameters)[k]);
1331 block_symbol -> CompressSpace(); // space optimization
1332 SetBlockSymbol(block_symbol);
1333 }
1334 }
1335
1336
CleanUp()1337 void MethodSymbol::CleanUp()
1338 {
1339 BlockSymbol* block = new BlockSymbol(NumFormalParameters());
1340
1341 //
1342 // Make a copy of each parameter into the new pared-down symbol table and
1343 // fix the FormalParameter information to identify the new symbol.
1344 //
1345 for (unsigned k = 0; k < NumFormalParameters(); k++)
1346 {
1347 VariableSymbol* formal_parameter = (*formal_parameters)[k];
1348 VariableSymbol* symbol =
1349 block -> InsertVariableSymbol(formal_parameter -> Identity());
1350 symbol -> SetType(formal_parameter -> Type());
1351 symbol -> MarkComplete();
1352 (*formal_parameters)[k] = symbol;
1353 }
1354
1355 //
1356 // Destroy the old symbol and replace it by the new one.
1357 //
1358 delete block_symbol;
1359 block -> CompressSpace(); // space optimization
1360 SetBlockSymbol(block);
1361
1362 declaration = NULL; // remove reference to Ast structure
1363 }
1364
1365
LocalVariableIndex(Semantic * sem)1366 int VariableSymbol::LocalVariableIndex(Semantic* sem)
1367 {
1368 if (IsLocal(sem -> ThisMethod()))
1369 {
1370 assert(sem -> FinalFields());
1371 return local_variable_index + sem -> FinalFields() -> Length();
1372 }
1373 return local_variable_index;
1374 }
1375
SetLocation()1376 void VariableSymbol::SetLocation()
1377 {
1378 if (! declarator)
1379 {
1380 file_location = new FileLocation(ContainingType() -> file_symbol);
1381 }
1382 else
1383 {
1384 file_location =
1385 new FileLocation((ContainingType() -> semantic_environment ->
1386 sem -> lex_stream),
1387 declarator -> LeftToken());
1388 }
1389 }
1390
ProcessVariableSignature(Semantic * sem,TokenIndex token_location)1391 void VariableSymbol::ProcessVariableSignature(Semantic* sem,
1392 TokenIndex token_location)
1393 {
1394 if (! type_)
1395 {
1396 assert(sem);
1397 const char* signature = signature_string;
1398
1399 SetType(sem -> ProcessSignature((TypeSymbol*) owner, signature,
1400 token_location));
1401 assert(! *signature);
1402 }
1403 }
1404
1405
IsNestedIn(TypeSymbol * type)1406 bool TypeSymbol::IsNestedIn(TypeSymbol* type)
1407 {
1408 for (SemanticEnvironment* env = semantic_environment;
1409 env; env = env -> previous)
1410 {
1411 if (env -> Type() == type)
1412 return true;
1413 }
1414 return false;
1415 }
1416
1417
1418 //
1419 // Return the type of an enclosing instance, if this is an inner class
1420 // which is not in a static context. For anonymous and local classes, the
1421 // compiler necessarily built them from source, so enclosing_instance will
1422 // be properly set. Non-static nested classes, however, could have been
1423 // read from a .class file, hence the need for the second half of the ||.
1424 //
EnclosingType()1425 TypeSymbol* TypeSymbol::EnclosingType()
1426 {
1427 if (enclosing_instance || (IsInner() && ! Anonymous() && ! IsLocal()))
1428 {
1429 assert(ContainingType());
1430 return ContainingType();
1431 }
1432 return NULL;
1433 }
1434
1435
1436 //
1437 // Check if this type has access to an enclosing instance of the named type.
1438 // If exact is true, the enclosing instance must be the specified type,
1439 // otherwise it is the innermost instance which is a subclass of type.
1440 //
HasEnclosingInstance(TypeSymbol * type,bool exact)1441 bool TypeSymbol::HasEnclosingInstance(TypeSymbol* type, bool exact)
1442 {
1443 assert(semantic_environment);
1444 for (SemanticEnvironment* env = semantic_environment;
1445 env; env = env -> previous)
1446 {
1447 if (exact ? (env -> Type() == type)
1448 : (env -> Type() -> IsSubclass(type)))
1449 {
1450 //
1451 // We found the innermost candidate type, now see if it is an
1452 // enclosing type that is fully initialized.
1453 //
1454 return ! env -> StaticRegion();
1455 }
1456 if (env -> Type() -> ACC_STATIC()) // No more enclosing levels exist.
1457 return false;
1458 }
1459 return false; // The requested type does not enclose this type.
1460 }
1461
1462
1463 //
1464 // Given two types T and T2 in different packages, the type T can access
1465 // protected members of T2 iff T or any class in which T is lexically enclosed
1466 // is a subclass of T2 or of some other type T3 that lexically encloses T2.
1467 //
1468 // Of course, T2 and all its enclosing classes, if any, must have been declared
1469 // either public or protected, otherwise they could not be eligible as a
1470 // superclass candidate. We do not need to check for that condition here.
1471 //
HasProtectedAccessTo(TypeSymbol * target_type)1472 bool TypeSymbol::HasProtectedAccessTo(TypeSymbol* target_type)
1473 {
1474 assert(semantic_environment && ! target_type -> IsArray());
1475
1476 // Loop through T and enclosing classes.
1477 for (SemanticEnvironment* env = semantic_environment;
1478 env; env = env -> previous)
1479 {
1480 TypeSymbol* main_type = env -> Type();
1481 // Loop through T2 and enclosing classes.
1482 for (TypeSymbol* type = target_type;
1483 type; type = type -> owner -> TypeCast())
1484 {
1485 if (main_type -> IsSubclass(type))
1486 return true;
1487 }
1488 }
1489 return false;
1490 }
1491
1492
BoxedType(Control & control)1493 TypeSymbol* TypeSymbol::BoxedType(Control& control)
1494 {
1495 if (! Primitive())
1496 return this;
1497 if (this == control.int_type)
1498 return control.Integer();
1499 if (this == control.boolean_type)
1500 return control.Boolean();
1501 if (this == control.byte_type)
1502 return control.Byte();
1503 if (this == control.short_type)
1504 return control.Short();
1505 if (this == control.char_type)
1506 return control.Character();
1507 if (this == control.long_type)
1508 return control.Long();
1509 if (this == control.float_type)
1510 return control.Float();
1511 if (this == control.double_type)
1512 return control.Double();
1513 assert(this == control.void_type);
1514 return control.Void();
1515 }
1516
1517
UnboxedType(Control & control)1518 TypeSymbol* TypeSymbol::UnboxedType(Control& control)
1519 {
1520 if (ContainingPackage() != control.LangPackage())
1521 return this;
1522 if (this == control.Integer())
1523 return control.int_type;
1524 if (this == control.Boolean())
1525 return control.boolean_type;
1526 if (this == control.Byte())
1527 return control.byte_type;
1528 if (this == control.Short())
1529 return control.short_type;
1530 if (this == control.Character())
1531 return control.char_type;
1532 if (this == control.Long())
1533 return control.long_type;
1534 if (this == control.Float())
1535 return control.float_type;
1536 if (this == control.Double())
1537 return control.double_type;
1538 if (this == control.Void())
1539 return control.void_type;
1540 return this;
1541 }
1542
1543
InsertThis0()1544 VariableSymbol* TypeSymbol::InsertThis0()
1545 {
1546 assert(IsInner() && ContainingType() &&
1547 ! semantic_environment -> previous -> StaticRegion());
1548
1549 Control& control = semantic_environment -> sem -> control;
1550
1551 // No local shadows and no this$0 yet.
1552 assert(NumConstructorParameters() == 0 && ! enclosing_instance);
1553
1554 //
1555 // Create a this0 pointer for an inner class.
1556 //
1557 VariableSymbol* variable_symbol =
1558 InsertVariableSymbol(control.this_name_symbol);
1559 variable_symbol -> SetType(ContainingType());
1560 variable_symbol -> SetFlags(ACCESS_FINAL | ACCESS_SYNTHETIC);
1561 variable_symbol -> SetOwner(this);
1562 variable_symbol -> MarkComplete();
1563 variable_symbol -> MarkInitialized();
1564
1565 enclosing_instance = variable_symbol;
1566 return variable_symbol;
1567 }
1568
1569
FindOrInsertClassLiteralClass()1570 TypeSymbol* TypeSymbol::FindOrInsertClassLiteralClass()
1571 {
1572 //
1573 // Normally, the place-holder type for invoking private constructors can
1574 // be any type, because we just pass null along, avoiding static
1575 // initialization. But if we use the place-holder type to store the
1576 // class$() method, we must ensure it is a subclass of Object.
1577 //
1578 if (placeholder_type && (placeholder_type -> super !=
1579 semantic_environment -> sem -> control.Object()))
1580 placeholder_type = NULL;
1581 return GetPlaceholderType();
1582 }
1583
1584
FindOrInsertClassLiteralMethod(Control & control)1585 MethodSymbol* TypeSymbol::FindOrInsertClassLiteralMethod(Control& control)
1586 {
1587 assert(! ACC_INTERFACE());
1588 if (! class_literal_method)
1589 {
1590 //
1591 // Note that max_variable_index is initialized to 2 (instead of 1),
1592 // even though the class literal method is static. The reason is that
1593 // in generating code for this method, a try statement with a catch
1594 // will be used. Therefore, an extra "local" slot is required for the
1595 // local Exception parameter of the catch clause. We do not fill in
1596 // the body of this method here, because bytecode.cpp can do a much
1597 // more optimal job later. The method has the signature:
1598 //
1599 // /*synthetic*/ static Class class$(String name, boolean array);
1600 //
1601 BlockSymbol* block_symbol = new BlockSymbol(2);
1602 block_symbol -> max_variable_index = 2;
1603
1604 class_literal_method = InsertMethodSymbol(control.class_name_symbol);
1605 class_literal_method -> SetType(control.Class());
1606 class_literal_method -> SetFlags(ACCESS_STATIC | ACCESS_SYNTHETIC);
1607 // No need to worry about strictfp, since this method avoids fp math
1608 class_literal_method -> SetContainingType(this);
1609 class_literal_method -> SetBlockSymbol(block_symbol);
1610
1611 VariableSymbol* variable_symbol =
1612 block_symbol -> InsertVariableSymbol(control.MakeParameter(1));
1613 variable_symbol -> SetACC_SYNTHETIC();
1614 variable_symbol -> SetType(control.String());
1615 variable_symbol -> SetOwner(class_literal_method);
1616 variable_symbol -> SetLocalVariableIndex(block_symbol ->
1617 max_variable_index++);
1618 variable_symbol -> MarkComplete();
1619 class_literal_method -> AddFormalParameter(variable_symbol);
1620
1621 variable_symbol =
1622 block_symbol -> InsertVariableSymbol(control.MakeParameter(2));
1623 variable_symbol -> SetACC_SYNTHETIC();
1624 variable_symbol -> SetType(control.boolean_type);
1625 variable_symbol -> SetOwner(class_literal_method);
1626 variable_symbol -> SetLocalVariableIndex(block_symbol ->
1627 max_variable_index++);
1628 variable_symbol -> MarkComplete();
1629 class_literal_method -> AddFormalParameter(variable_symbol);
1630
1631 class_literal_method -> SetSignature(control);
1632 semantic_environment -> sem -> AddDependence(this, control.Class());
1633 }
1634 return class_literal_method;
1635 }
1636
1637
FindOrInsertClassLiteralName(Control & control)1638 Utf8LiteralValue* TypeSymbol::FindOrInsertClassLiteralName(Control& control)
1639 {
1640 if (! class_literal_name)
1641 {
1642 int length = fully_qualified_name -> length;
1643 char* slashed_name = fully_qualified_name -> value;
1644 char* name = new char[length + 1];
1645 for (int i = 0; i < length; i++)
1646 name[i] = (slashed_name[i] == U_SLASH ? (wchar_t) U_DOT
1647 : slashed_name[i]);
1648 name[length] = U_NULL;
1649 class_literal_name = control.Utf8_pool.FindOrInsert(name, length);
1650 delete [] name;
1651 }
1652 return class_literal_name;
1653 }
1654
1655
FindOrInsertClassLiteral(TypeSymbol * type)1656 VariableSymbol* TypeSymbol::FindOrInsertClassLiteral(TypeSymbol* type)
1657 {
1658 assert(! type -> Primitive() && ! type -> Anonymous());
1659 assert(! Primitive() && ! IsArray());
1660
1661 Semantic* sem = semantic_environment -> sem;
1662 Control& control = sem -> control;
1663
1664 //
1665 // We must be careful that we do not initialize the class literal in
1666 // question, or any enclosing types. True inner classes can defer to their
1667 // enclosing class (since code in the inner class cannot be run without
1668 // the enclosing class being initialized), but static nested types get
1669 // their own class$ method and cache variables. Interfaces cannot have
1670 // non-public members, so if the innermost non-local type is an interface,
1671 // we use the placeholder class to hold the class$ magic.
1672 //
1673 TypeSymbol* owner = this;
1674 while (owner -> IsInner())
1675 owner = owner -> ContainingType();
1676 if (owner -> ACC_INTERFACE())
1677 owner = outermost_type -> FindOrInsertClassLiteralClass();
1678 owner -> FindOrInsertClassLiteralMethod(control);
1679
1680 NameSymbol* name_symbol = NULL;
1681 const char* signature = type -> SignatureString();
1682 if (signature[0] == U_LEFT_BRACKET) // an array?
1683 {
1684 int array_length = control.array_name_symbol -> NameLength();
1685 int length = strlen(signature) + array_length;
1686 wchar_t* name = new wchar_t[length + 1]; // +1 for '\0';
1687 wcscpy(name, control.array_name_symbol -> Name());
1688 int i;
1689 int k;
1690 for (i = 0, k = array_length; signature[i] == U_LEFT_BRACKET; i++, k++)
1691 name[k] = U_DOLLAR;
1692 // Leave leading 'L', since there can be conflicts with primitive
1693 // array types otherwise
1694 for (wchar_t ch = signature[i++]; ch && ch != U_SEMICOLON;
1695 ch = signature[i++])
1696 {
1697 name[k++] = (ch == U_SLASH ? (wchar_t) U_DOLLAR : ch);
1698 }
1699 name[k] = U_NULL;
1700 name_symbol = control.FindOrInsertName(name, k);
1701 delete [] name;
1702 }
1703 else
1704 {
1705 assert(signature[0] == U_L); // a reference type
1706 int class_length = control.class_name_symbol -> NameLength();
1707 int length = strlen(signature) + class_length;
1708
1709 wchar_t* name = new wchar_t[length + 1]; // +1 for '\0';
1710 wcscpy(name, control.class_name_symbol -> Name());
1711 int i = 1; // skip leading 'L'
1712 int k = class_length;
1713 name[k++] = U_DOLLAR;
1714 for (wchar_t ch = signature[i++]; ch && ch != U_SEMICOLON;
1715 ch = signature[i++])
1716 {
1717 name[k++] = (ch == U_SLASH ? (wchar_t) U_DOLLAR : ch);
1718 }
1719 name[k] = U_NULL;
1720 name_symbol = control.FindOrInsertName(name, k);
1721 delete [] name;
1722 }
1723
1724 VariableSymbol* variable_symbol = owner -> FindVariableSymbol(name_symbol);
1725 if (! variable_symbol)
1726 {
1727 //
1728 // Generate a caching variable (no need to make it private, so that
1729 // nested classes of interfaces can share it easily).
1730 //
1731 // Foo.Bar.class is cached in:
1732 // /*synthetic*/ static Class class$Foo$Bar;
1733 // int[][].class is cached in:
1734 // /*synthetic*/ static Class array$$I;
1735 // Blah[].class is cached in:
1736 // /*synthetic*/ static Class array$LBlah;
1737 //
1738 variable_symbol = owner -> InsertVariableSymbol(name_symbol);
1739 variable_symbol -> SetType(control.Class());
1740 variable_symbol -> SetFlags(ACCESS_STATIC | ACCESS_SYNTHETIC);
1741 variable_symbol -> SetOwner(owner);
1742 variable_symbol -> MarkComplete();
1743
1744 owner -> AddClassLiteral(variable_symbol);
1745 }
1746 return variable_symbol;
1747 }
1748
1749
FindOrInsertAssertVariable()1750 VariableSymbol* TypeSymbol::FindOrInsertAssertVariable()
1751 {
1752 if (! assert_variable)
1753 {
1754 assert(! (Primitive() || ACC_INTERFACE() || IsArray()));
1755
1756 Semantic* sem = semantic_environment -> sem;
1757 Control& control = sem -> control;
1758
1759 assert_variable = InsertVariableSymbol(control.assert_name_symbol);
1760 assert_variable -> SetType(control.boolean_type);
1761 assert_variable -> SetFlags(ACCESS_PRIVATE | ACCESS_STATIC |
1762 ACCESS_FINAL | ACCESS_SYNTHETIC);
1763 assert_variable -> SetOwner(this);
1764 assert_variable -> MarkComplete();
1765 assert_variable -> MarkInitialized();
1766
1767 //
1768 // We'll create the field initializer later in bytecode.cpp, but we
1769 // create the static initializer that will contain the field
1770 // initializer now, if it was not already created.
1771 //
1772 sem -> GetStaticInitializerMethod();
1773 }
1774 return assert_variable;
1775 }
1776
1777
FindOrInsertLocalShadow(VariableSymbol * local)1778 VariableSymbol* TypeSymbol::FindOrInsertLocalShadow(VariableSymbol* local)
1779 {
1780 assert(IsLocal() && local -> IsLocal());
1781
1782 Control& control = semantic_environment -> sem -> control;
1783 VariableSymbol* variable = NULL;
1784 if (local_shadow_map)
1785 variable = (VariableSymbol*) local_shadow_map -> Image(local);
1786
1787 //
1788 // For a local/anonymous class, if it does not yet have a shadow for a
1789 // local variable that it needs access to, create one.
1790 //
1791 // For example:
1792 // class Outer {
1793 // static void foo(final int i) {
1794 // class Local {
1795 // Local(int k) { k = i; }
1796 // }
1797 // new Local(1);
1798 // }
1799 // }
1800 //
1801 // expands to:
1802 // class Outer {
1803 // static void foo(final int i) {
1804 // new Outer$1Local(1, i);
1805 // }
1806 // }
1807 // class Outer$1Local {
1808 // /*synthetic*/ final int val$i;
1809 // Outer$1Local(int k, int i) {
1810 // val$i = i;
1811 // super();
1812 // k = val$i;
1813 // }
1814 // }
1815 //
1816 // This method creates Outer$1Local.val$i in the above example. Notice
1817 // that JVMS 4.9.4 permits initialization of synthetic fields BEFORE the
1818 // explicit constructor invocation, even though it would not normally be
1819 // valid Java; this is necessary for the case when the superconstructor
1820 // calls a polymorphic method which references i.
1821 //
1822 // Note that we must mangle the shadow with val$, because of this case:
1823 // void foo(final int i) {
1824 // class Local { int j = i; }
1825 // new Local() { int i; };
1826 // }
1827 //
1828 // In 1.5 and later, we use the prefix "-" instead of "val$".
1829 //
1830 if (! variable)
1831 {
1832 int length = control.val_name_symbol -> NameLength() +
1833 local -> NameLength();
1834 wchar_t* name = new wchar_t[length + 1]; // +1 for '\0';
1835 wcscpy(name, control.val_name_symbol -> Name());
1836 wcscat(name, local -> Name());
1837 NameSymbol* name_symbol = control.FindOrInsertName(name, length);
1838
1839 variable = InsertVariableSymbol(name_symbol);
1840 variable -> SetType(local -> Type());
1841 variable -> SetFlags(ACCESS_FINAL | ACCESS_SYNTHETIC);
1842 variable -> SetOwner(this);
1843 variable -> MarkComplete();
1844 variable -> MarkInitialized();
1845
1846 if (ContainingType() == local -> ContainingType())
1847 variable -> accessed_local = local;
1848 else
1849 {
1850 assert(Anonymous() && ! EnclosingType());
1851 variable -> accessed_local = semantic_environment -> sem ->
1852 FindLocalVariable(local, ContainingType());
1853 }
1854 AddConstructorParameter(variable);
1855
1856 delete [] name;
1857
1858 if (! local_shadow_map)
1859 local_shadow_map = new SymbolMap();
1860 local_shadow_map -> Map(local, variable);
1861 }
1862
1863 #ifdef JIKES_DEBUG
1864 VariableSymbol* accessed;
1865 for (accessed = variable -> accessed_local;
1866 accessed && accessed != local;
1867 accessed = accessed -> accessed_local);
1868 assert(accessed);
1869 #endif // JIKES_DEBUG
1870 return variable;
1871 }
1872
1873
MapSymbolToReadMethod(Symbol * symbol,TypeSymbol * base_type,MethodSymbol * method)1874 inline void TypeSymbol::MapSymbolToReadMethod(Symbol* symbol,
1875 TypeSymbol* base_type,
1876 MethodSymbol* method)
1877 {
1878 if (! read_methods)
1879 // default size
1880 read_methods = new Map<Symbol, Map<TypeSymbol, MethodSymbol> >();
1881
1882 Map<TypeSymbol, MethodSymbol>* map = read_methods -> Image(symbol);
1883 if (! map)
1884 {
1885 map = new Map<TypeSymbol, MethodSymbol>(1); // small size
1886 read_methods -> Add(symbol, map);
1887 }
1888
1889 map -> Add(base_type, method);
1890 }
1891
ReadMethod(Symbol * symbol,TypeSymbol * base_type)1892 inline MethodSymbol* TypeSymbol::ReadMethod(Symbol* symbol,
1893 TypeSymbol* base_type)
1894 {
1895 if (read_methods)
1896 {
1897 Map<TypeSymbol, MethodSymbol>* map = read_methods -> Image(symbol);
1898 if (map)
1899 return map -> Image(base_type);
1900 }
1901 return NULL;
1902 }
1903
MapSymbolToWriteMethod(VariableSymbol * symbol,TypeSymbol * base_type,MethodSymbol * method)1904 inline void TypeSymbol::MapSymbolToWriteMethod(VariableSymbol* symbol,
1905 TypeSymbol* base_type,
1906 MethodSymbol* method)
1907 {
1908 if (! write_methods)
1909 write_methods = new Map<VariableSymbol,
1910 Map<TypeSymbol, MethodSymbol> >(); // default size
1911
1912 Map<TypeSymbol, MethodSymbol>* map = write_methods -> Image(symbol);
1913 if (! map)
1914 {
1915 map = new Map<TypeSymbol, MethodSymbol>(1); // small size
1916 write_methods -> Add(symbol, map);
1917 }
1918
1919 map -> Add(base_type, method);
1920 }
1921
WriteMethod(VariableSymbol * symbol,TypeSymbol * base_type)1922 inline MethodSymbol* TypeSymbol::WriteMethod(VariableSymbol* symbol,
1923 TypeSymbol* base_type)
1924 {
1925 if (write_methods)
1926 {
1927 Map<TypeSymbol, MethodSymbol>* map = write_methods -> Image(symbol);
1928 if (map)
1929 return map -> Image(base_type);
1930 }
1931 return NULL;
1932 }
1933
GetReadAccessMethod(MethodSymbol * member,TypeSymbol * base_type)1934 MethodSymbol* TypeSymbol::GetReadAccessMethod(MethodSymbol* member,
1935 TypeSymbol* base_type)
1936 {
1937 // accessing a method
1938 assert(member -> Identity() !=
1939 semantic_environment -> sem -> control.init_name_symbol);
1940
1941 TypeSymbol* containing_type = member -> containing_type;
1942 if (! base_type)
1943 base_type = this;
1944
1945 assert((member -> ACC_PRIVATE() && this == containing_type) ||
1946 (member -> ACC_PROTECTED() &&
1947 ! semantic_environment -> sem -> ProtectedAccessCheck(containing_type)) ||
1948 (base_type == super && ! member -> ACC_STATIC()));
1949
1950 MethodSymbol* read_method = ReadMethod(member, base_type);
1951
1952 if (! read_method)
1953 {
1954 //
1955 // BaseType is the qualifying type of we are accessing. If the method
1956 // is private, BaseType should be this type, but for protected
1957 // variables, BaseType should be a superclass or subclass of this type
1958 // that is not in this package.
1959 //
1960 // To access
1961 // "static Type name(Type1 p1, Type2 p2, ...) throws Exception;",
1962 // expand to:
1963 //
1964 // /*synthetic*/ static Type access$<num>(Type1 p1, Type2 p2, ...)
1965 // throws Exception
1966 // {
1967 // return BaseType.name(p1, p2, ...);
1968 // }
1969 //
1970 // If we are accessing
1971 // "void name(Type1 p1, Type2 p2, ...) throws Throwable;",
1972 // expand to:
1973 //
1974 // /*synthetic*/ static void access$<num>(BaseType $0, Type1 p1,
1975 // Type2 p2, ...)
1976 // throws Throwable
1977 // {
1978 // $0.name(p1, p2, ...);
1979 // return;
1980 // }
1981 //
1982 // In 1.5 and later, we use the prefix "-" instead of "access$".
1983 //
1984 Semantic* sem = semantic_environment -> sem;
1985 assert(sem);
1986
1987 Control& control = sem -> control;
1988 StoragePool* ast_pool = sem -> compilation_unit -> ast_pool;
1989
1990 IntToWstring value(NumPrivateAccessMethods());
1991
1992 int length = control.access_name_symbol -> NameLength() +
1993 value.Length();
1994 wchar_t* name = new wchar_t[length + 1]; // +1 for '\0';
1995 wcscpy(name, control.access_name_symbol -> Name());
1996 wcscat(name, value.String());
1997
1998 //
1999 // Use the location of the class name for all elements of this method.
2000 //
2001 TokenIndex loc = declaration -> identifier_token;
2002
2003 unsigned parameter_count = member -> NumFormalParameters();
2004
2005 //
2006 // Add the method instead of inserting it, so it is not an overload
2007 // candidate.
2008 //
2009 read_method = new MethodSymbol(control.FindOrInsertName(name, length));
2010 Table() -> AddMethodSymbol(read_method);
2011 read_method -> SetType(member -> Type());
2012 read_method -> SetFlags(ACCESS_STATIC | ACCESS_SYNTHETIC);
2013 if (member -> ACC_STRICTFP())
2014 read_method -> SetACC_STRICTFP();
2015 if (member -> ACC_FINAL() || ACC_FINAL())
2016 read_method -> SetACC_FINAL();
2017 read_method -> SetContainingType(this);
2018
2019 //
2020 // A read access method for a method has a formal parameter per
2021 // parameter of the member in question, plus one more if it is not
2022 // static.
2023 //
2024 BlockSymbol* block_symbol =
2025 new BlockSymbol(parameter_count +
2026 (member -> ACC_STATIC() ? 0 : 1));
2027 block_symbol -> max_variable_index = 0;
2028 read_method -> SetBlockSymbol(block_symbol);
2029 for (unsigned j = 0; j < member -> NumThrows(); j++)
2030 read_method -> AddThrows(member -> Throws(j));
2031
2032 AstExpression* base;
2033 if (! member -> ACC_STATIC() && base_type == super)
2034 {
2035 //
2036 // Special case - for Outer.super.m() where m() is an instance
2037 // method, we mark the field access as a super access, to
2038 // make sure we emit invokespecial instead of invokevirtual in
2039 // bytecode.cpp. Notice that in this case,
2040 // ((Super) Outer.this).m() cannot generate an accessor method
2041 // (either m() is public or in the same package and thus already
2042 // accessible, or m is protected in a different package and
2043 // therefore inaccessible), so we don't have to worry about a
2044 // conflict in accessor methods for the same base type.
2045 //
2046 base = ast_pool -> GenSuperExpression(loc);
2047 }
2048 else base = ast_pool -> GenName(loc);
2049
2050 AstArguments* args = ast_pool -> GenArguments(loc, loc);
2051 args -> AllocateArguments(parameter_count);
2052
2053 AstMethodInvocation* method_invocation =
2054 ast_pool -> GenMethodInvocation(loc);
2055 method_invocation -> base_opt = base;
2056 method_invocation -> arguments = args;
2057 method_invocation -> symbol = member;
2058
2059 AstMethodDeclarator* method_declarator =
2060 ast_pool -> GenMethodDeclarator();
2061 method_declarator -> identifier_token = loc;
2062 method_declarator -> left_parenthesis_token = loc;
2063 method_declarator -> right_parenthesis_token = loc;
2064
2065 if (member -> ACC_STATIC())
2066 {
2067 method_declarator -> AllocateFormalParameters(parameter_count);
2068 base -> symbol = base_type;
2069 }
2070 else
2071 {
2072 method_declarator -> AllocateFormalParameters(parameter_count + 1);
2073 NameSymbol* instance_name = control.MakeParameter(1);
2074
2075 VariableSymbol* instance =
2076 block_symbol -> InsertVariableSymbol(instance_name);
2077 instance -> SetACC_SYNTHETIC();
2078 instance -> SetType(base_type == super ? this : base_type);
2079 instance -> SetOwner(read_method);
2080 instance -> SetLocalVariableIndex(block_symbol ->
2081 max_variable_index++);
2082 instance -> MarkComplete();
2083 read_method -> AddFormalParameter(instance);
2084 base -> symbol = (base_type == super
2085 ? (Symbol*) super : (Symbol*) instance);
2086 }
2087
2088 for (unsigned i = 0; i < parameter_count; i++)
2089 {
2090 VariableSymbol* parm = block_symbol ->
2091 InsertVariableSymbol(member -> FormalParameter(i) -> Identity());
2092 parm -> SetACC_SYNTHETIC();
2093 parm -> SetType(member -> FormalParameter(i) -> Type());
2094 parm -> SetOwner(read_method);
2095 parm -> SetLocalVariableIndex(block_symbol ->
2096 max_variable_index++);
2097 parm -> MarkComplete();
2098 if (control.IsDoubleWordType(parm -> Type()))
2099 block_symbol -> max_variable_index++;
2100 read_method -> AddFormalParameter(parm);
2101
2102 AstName* simple_name = ast_pool -> GenName(loc);
2103 simple_name -> symbol = parm;
2104 args -> AddArgument(simple_name);
2105 }
2106 read_method -> SetSignature(control);
2107
2108 AstReturnStatement* return_statement =
2109 ast_pool -> GenReturnStatement();
2110 return_statement -> return_token = loc;
2111 return_statement -> semicolon_token = loc;
2112 return_statement -> is_reachable = true;
2113
2114 AstMethodBody* block = ast_pool -> GenMethodBody();
2115 block -> left_brace_token = loc;
2116 block -> right_brace_token = loc;
2117 // the symbol table associated with this block will contain no element
2118 block -> block_symbol = new BlockSymbol(0);
2119 block -> is_reachable = true;
2120
2121 if (member -> Type() == control.void_type)
2122 {
2123 AstExpressionStatement* expression_statement =
2124 ast_pool -> GenExpressionStatement();
2125 expression_statement -> expression = method_invocation;
2126 expression_statement -> semicolon_token_opt = loc;
2127 expression_statement -> is_reachable = true;
2128 expression_statement -> can_complete_normally = true;
2129
2130 block -> AllocateStatements(2);
2131 block -> AddStatement(expression_statement);
2132 }
2133 else
2134 {
2135 return_statement -> expression_opt = method_invocation;
2136 block -> AllocateStatements(1);
2137 }
2138 block -> AddStatement(return_statement);
2139
2140 AstMethodDeclaration* method_declaration =
2141 ast_pool -> GenMethodDeclaration();
2142 method_declaration -> method_symbol = read_method;
2143 method_declaration -> method_declarator = method_declarator;
2144 method_declaration -> method_body_opt = block;
2145
2146 read_method -> declaration = method_declaration;
2147 read_method -> accessed_member = member;
2148 MapSymbolToReadMethod(member, base_type, read_method);
2149 AddPrivateAccessMethod(read_method);
2150
2151 delete [] name;
2152 }
2153 return read_method;
2154 }
2155
GetReadAccessConstructor(MethodSymbol * ctor)2156 MethodSymbol* TypeSymbol::GetReadAccessConstructor(MethodSymbol* ctor)
2157 {
2158 //
2159 // Protected superconstructors are always accessible, and class instance
2160 // creation expressions can only invoke a protected constructor in the
2161 // current package, where an accessor is not needed. Also, anonymous
2162 // classes never have a private constructor.
2163 //
2164 assert((ctor -> Identity() ==
2165 semantic_environment -> sem -> control.init_name_symbol) &&
2166 ctor -> ACC_PRIVATE() && this == ctor -> containing_type &&
2167 ! Anonymous());
2168
2169 MethodSymbol* read_method = ReadMethod(ctor, this);
2170
2171 if (! read_method)
2172 {
2173 //
2174 // There are two cases for accessing a private constructor. First, as
2175 // a superclass:
2176 //
2177 // class Outer {
2178 // private Outer(Type1 $1, Type2 $2, ...) {}
2179 // static class Inner extends Outer {
2180 // Inner() { super(expr1, expr2, ...); }
2181 // }
2182 // }
2183 //
2184 // We must create a synthetic place-holder class, and expand this to:
2185 // (TODO: can someone come up with a way to do this without a
2186 // placeholder class?)
2187 //
2188 // class Outer {
2189 // private Outer(Type1 $1, Type2 $2, ...) {}
2190 // /*synthetic*/ Outer(Outer$ $0, Type1 $1, Type2 $2, ...)
2191 // {
2192 // this($1, $2, ...);
2193 // }
2194 // }
2195 // /*synthetic*/ class Outer$ {} // placeholder only
2196 // class Outer$Inner extends Outer {
2197 // Outer$Inner() { super((Outer$) null, expr1, expr2, ...); }
2198 // }
2199 //
2200 // The other use is in class instance creation expressions (recall
2201 // that the default constructor for a private class is private):
2202 //
2203 // class Outer {
2204 // private class Inner {}
2205 // Inner i = new Inner();
2206 // }
2207 //
2208 // Here again, we create a place-holder class for now. TODO:
2209 // alternatives have been proposed, such as using a static generator
2210 // method instead of an alternate constructor.
2211 //
2212 // class Outer {
2213 // Outer$Inner i = new Outer$Inner(this, (Outer$) null);
2214 // }
2215 // /*synthetic*/ class Outer$ {} // placeholder only
2216 // class Outer$Inner {
2217 // private final Outer this$0;
2218 // private Outer$Inner(Outer $0) { super(); this$0 = $0; }
2219 // /*synthetic*/ Outer$Inner(Outer $0, Outer$ $1) { this($0); }
2220 // }
2221 //
2222 Semantic* sem = semantic_environment -> sem;
2223 assert(sem);
2224 //
2225 // A clone situation exists only when trying to determine a final
2226 // value for a field. As obtaining a final value does not need an
2227 // access method, we delay creating the accessor until out of the
2228 // clone (otherwise, the placeholder type might be incorrect).
2229 //
2230 if (sem -> error && sem -> error -> InClone())
2231 return ctor;
2232
2233 Control& control = sem -> control;
2234 StoragePool* ast_pool = sem -> compilation_unit -> ast_pool;
2235
2236 // +3 to allow for dummy parameter, local variable shadows
2237 BlockSymbol* block_symbol =
2238 new BlockSymbol(ctor -> NumFormalParameters() + 3);
2239
2240 //
2241 // Add the method instead of inserting it, so it is not an overload
2242 // candidate.
2243 //
2244 read_method = new MethodSymbol(control.init_name_symbol);
2245 Table() -> AddMethodSymbol(read_method);
2246 read_method -> SetType(this);
2247 read_method -> SetContainingType(this);
2248 read_method -> SetBlockSymbol(block_symbol);
2249 read_method -> SetACC_SYNTHETIC();
2250 if (ctor -> ACC_STRICTFP())
2251 read_method -> SetACC_STRICTFP();
2252
2253 for (unsigned j = 0; j < ctor -> NumThrows(); j++)
2254 read_method -> AddThrows(ctor -> Throws(j));
2255
2256 block_symbol -> max_variable_index = 1;
2257 read_method -> SetExternalIdentity(ctor -> Identity());
2258
2259 Ast* declaration = ctor -> declaration;
2260 AstMethodDeclarator* declarator =
2261 ((AstConstructorDeclaration*) declaration) -> constructor_declarator;
2262 assert(declarator);
2263 TokenIndex loc = declarator -> identifier_token;
2264
2265 AstMethodDeclarator* method_declarator =
2266 ast_pool -> GenMethodDeclarator();
2267 method_declarator -> identifier_token = loc;
2268 method_declarator -> left_parenthesis_token =
2269 declarator -> LeftToken();
2270 method_declarator -> right_parenthesis_token =
2271 declarator -> RightToken();
2272
2273 AstArguments* args = ast_pool -> GenArguments(loc, loc);
2274 args -> AllocateArguments(ctor -> NumFormalParameters());
2275
2276 AstThisCall* this_call = ast_pool -> GenThisCall();
2277 this_call -> this_token = loc;
2278 this_call -> arguments = args;
2279 this_call -> semicolon_token = loc;
2280 this_call -> symbol = ctor;
2281
2282 VariableSymbol* this0_variable = NULL;
2283 if (EnclosingType())
2284 {
2285 this0_variable = block_symbol ->
2286 InsertVariableSymbol(control.this_name_symbol);
2287 this0_variable -> SetACC_SYNTHETIC();
2288 this0_variable -> SetType(ContainingType());
2289 this0_variable -> SetOwner(read_method);
2290 this0_variable -> SetLocalVariableIndex(block_symbol ->
2291 max_variable_index++);
2292 this0_variable -> MarkComplete();
2293 }
2294
2295 //
2296 // Since private_access_constructors will be compiled (see
2297 // body.cpp), we must create valid ast_simple_names for its
2298 // parameters.
2299 //
2300 VariableSymbol* parm;
2301 for (unsigned i = 0; i < ctor -> NumFormalParameters(); i++)
2302 {
2303 parm = block_symbol -> InsertVariableSymbol(ctor -> FormalParameter(i) -> Identity());
2304 parm -> SetACC_SYNTHETIC();
2305 parm -> SetType(ctor -> FormalParameter(i) -> Type());
2306 parm -> SetOwner(read_method);
2307 parm -> SetLocalVariableIndex(block_symbol ->
2308 max_variable_index++);
2309 parm -> MarkComplete();
2310 if (control.IsDoubleWordType(parm -> Type()))
2311 block_symbol -> max_variable_index++;
2312 read_method -> AddFormalParameter(parm);
2313
2314 AstVariableDeclaratorId* variable_declarator_name =
2315 declarator -> FormalParameter(i) -> formal_declarator ->
2316 variable_declarator_name;
2317 AstName* simple_name = ast_pool ->
2318 GenName(variable_declarator_name -> identifier_token);
2319 simple_name -> symbol = parm;
2320 args -> AddArgument(simple_name);
2321 }
2322
2323 //
2324 // Any local variable shadow parameters will be taken care of later,
2325 // possibly changing this signature.
2326 //
2327 read_method -> SetSignature(control,
2328 outermost_type -> GetPlaceholderType());
2329
2330 AstReturnStatement* return_statement =
2331 ast_pool -> GenReturnStatement();
2332 return_statement -> return_token = loc;
2333 return_statement -> semicolon_token = loc;
2334 return_statement -> is_reachable = true;
2335
2336 AstMethodBody* constructor_block = ast_pool -> GenMethodBody();
2337 // This symbol table will be empty.
2338 constructor_block -> block_symbol = new BlockSymbol(0);
2339 constructor_block -> block_symbol -> max_variable_index =
2340 block_symbol -> max_variable_index;
2341 constructor_block -> left_brace_token = loc;
2342 constructor_block -> right_brace_token = loc;
2343 constructor_block -> AllocateStatements(1);
2344 constructor_block -> AddStatement(return_statement);
2345 constructor_block -> explicit_constructor_opt = this_call;
2346
2347 AstConstructorDeclaration* constructor_declaration =
2348 ast_pool -> GenConstructorDeclaration();
2349 constructor_declaration -> constructor_declarator = method_declarator;
2350 constructor_declaration -> constructor_body = constructor_block;
2351
2352 constructor_declaration -> constructor_symbol = read_method;
2353 read_method -> declaration = constructor_declaration;
2354
2355 AddPrivateAccessConstructor(read_method);
2356
2357 read_method -> accessed_member = ctor;
2358 MapSymbolToReadMethod(ctor, this, read_method);
2359 }
2360 return read_method;
2361 }
2362
2363
GetReadAccessMethod(VariableSymbol * member,TypeSymbol * base_type)2364 MethodSymbol* TypeSymbol::GetReadAccessMethod(VariableSymbol* member,
2365 TypeSymbol* base_type)
2366 {
2367 TypeSymbol* containing_type = member -> owner -> TypeCast();
2368 if (! base_type)
2369 base_type = this;
2370
2371 assert((member -> ACC_PRIVATE() && this == containing_type) ||
2372 (member -> ACC_PROTECTED() &&
2373 (! semantic_environment -> sem -> ProtectedAccessCheck(containing_type) ||
2374 (base_type == super && ! member -> ACC_STATIC()))));
2375
2376 MethodSymbol* read_method = ReadMethod(member, base_type);
2377
2378 if (! read_method)
2379 {
2380 //
2381 // BaseType is the qualifying type of we are accessing. If the
2382 // variable is private, BaseType should be this type, but for
2383 // protected variables, BaseType should be a superclass or subclass
2384 // of this type that is not in this package.
2385 //
2386 // If we are accessing "static Type name;", expand to:
2387 //
2388 // /*synthetic*/ static Type access$<num>()
2389 // {
2390 // return BaseType.name;
2391 // }
2392 //
2393 // If we are accessing "Type name;", expand to:
2394 //
2395 // /*synthetic*/ static Type access$<num>(BaseType $1)
2396 // {
2397 // return $1.name;
2398 // }
2399 //
2400 // In 1.5 and later, we use the prefix "-" instead of "access$".
2401 //
2402 Semantic* sem = semantic_environment -> sem;
2403 assert(sem);
2404
2405 Control& control = sem -> control;
2406 StoragePool* ast_pool = sem -> compilation_unit -> ast_pool;
2407
2408 IntToWstring value(NumPrivateAccessMethods());
2409
2410 int length = control.access_name_symbol -> NameLength() +
2411 value.Length();
2412 wchar_t* name = new wchar_t[length + 1]; // +1 for '\0';
2413 wcscpy(name, control.access_name_symbol -> Name());
2414 wcscat(name, value.String());
2415
2416 //
2417 // Use the location of the class name for all elements of this method.
2418 //
2419 TokenIndex loc = declaration -> identifier_token;
2420
2421 //
2422 // Add the method instead of inserting it, so it is not an overload
2423 // candidate.
2424 //
2425 read_method = new MethodSymbol(control.FindOrInsertName(name, length));
2426 Table() -> AddMethodSymbol(read_method);
2427 read_method -> SetType(member -> Type());
2428 read_method -> SetFlags(ACCESS_STATIC | ACCESS_SYNTHETIC);
2429 if (ACC_STRICTFP())
2430 read_method -> SetACC_STRICTFP();
2431 if (ACC_FINAL())
2432 read_method -> SetACC_FINAL();
2433 read_method -> SetContainingType(this);
2434
2435 //
2436 // A read access method for a field has 1 formal parameter if the
2437 // member in question is not static
2438 //
2439 BlockSymbol* block_symbol =
2440 new BlockSymbol(member -> ACC_STATIC() ? 0 : 1);
2441 block_symbol -> max_variable_index = 0;
2442 read_method -> SetBlockSymbol(block_symbol);
2443
2444 AstExpression* base;
2445 if (! member -> ACC_STATIC() && base_type == super)
2446 {
2447 //
2448 // Special case - for Outer.super.i where i is an instance field,
2449 // we mark the field access as a super access, to make sure we use
2450 // the correct qualifying instance. Notice that in this case,
2451 // ((Super) Outer.this).i cannot generate an accessor method
2452 // (either i is public or in the same package and thus already
2453 // accessible, or i is protected in a different package and
2454 // therefore inaccessible), so we don't have to worry about a
2455 // conflict in accessor methods for the same base type.
2456 //
2457 base = ast_pool -> GenSuperExpression(loc);
2458 }
2459 else base = ast_pool -> GenName(loc);
2460
2461 AstFieldAccess* field_access = ast_pool -> GenFieldAccess();
2462 field_access -> base = base;
2463 field_access -> identifier_token = loc;
2464 field_access -> symbol = member;
2465
2466 AstMethodDeclarator* method_declarator =
2467 ast_pool -> GenMethodDeclarator();
2468 method_declarator -> identifier_token = loc;
2469 method_declarator -> left_parenthesis_token = loc;
2470 method_declarator -> right_parenthesis_token = loc;
2471
2472 if (member -> ACC_STATIC())
2473 {
2474 base -> symbol = base_type;
2475 }
2476 else
2477 {
2478 method_declarator -> AllocateFormalParameters(1);
2479
2480 NameSymbol* instance_name = control.MakeParameter(1);
2481
2482 VariableSymbol* instance =
2483 block_symbol -> InsertVariableSymbol(instance_name);
2484 instance -> SetACC_SYNTHETIC();
2485 instance -> SetType(base_type == super ? this : base_type);
2486 instance -> SetOwner(read_method);
2487 instance -> SetLocalVariableIndex(block_symbol ->
2488 max_variable_index++);
2489 instance -> MarkComplete();
2490 read_method -> AddFormalParameter(instance);
2491 base -> symbol = (base_type == super
2492 ? (Symbol*) super : (Symbol*) instance);
2493 }
2494
2495 // A read access method has no throws clause !
2496 read_method -> SetSignature(control);
2497
2498 AstReturnStatement* return_statement =
2499 ast_pool -> GenReturnStatement();
2500 return_statement -> return_token = loc;
2501 return_statement -> expression_opt = field_access;
2502 return_statement -> semicolon_token = loc;
2503 return_statement -> is_reachable = true;
2504
2505 AstMethodBody* block = ast_pool -> GenMethodBody();
2506 block -> left_brace_token = loc;
2507 block -> right_brace_token = loc;
2508 block -> block_symbol = new BlockSymbol(0);
2509 block -> is_reachable = true;
2510 block -> AllocateStatements(1);
2511 block -> AddStatement(return_statement);
2512
2513 AstMethodDeclaration* method_declaration =
2514 ast_pool -> GenMethodDeclaration();
2515 method_declaration -> method_symbol = read_method;
2516 method_declaration -> method_declarator = method_declarator;
2517 method_declaration -> method_body_opt = block;
2518
2519 read_method -> declaration = method_declaration;
2520 read_method -> accessed_member = member;
2521 MapSymbolToReadMethod(member, base_type, read_method);
2522 AddPrivateAccessMethod(read_method);
2523
2524 delete [] name;
2525 }
2526 return read_method;
2527 }
2528
2529
GetWriteAccessMethod(VariableSymbol * member,TypeSymbol * base_type)2530 MethodSymbol* TypeSymbol::GetWriteAccessMethod(VariableSymbol* member,
2531 TypeSymbol* base_type)
2532 {
2533 TypeSymbol* containing_type = member -> owner -> TypeCast();
2534 if (! base_type)
2535 base_type = this;
2536
2537 assert((member -> ACC_PRIVATE() && this == containing_type) ||
2538 (member -> ACC_PROTECTED() &&
2539 (! semantic_environment -> sem -> ProtectedAccessCheck(containing_type) ||
2540 (base_type == super && ! member -> ACC_STATIC()))));
2541
2542 MethodSymbol* write_method = WriteMethod(member, base_type);
2543
2544 if (! write_method)
2545 {
2546 //
2547 // BaseType is the qualifying type of we are accessing. If the
2548 // variable is private, BaseType should be this type, but for
2549 // protected variables, BaseType should be a superclass or subclass
2550 // of this type that is not in this package.
2551 //
2552 // If we are accessing "static Type name;", expand to:
2553 //
2554 // /*synthetic*/ static void access$<num>(Type name)
2555 // {
2556 // BaseType.name = name;
2557 // return;
2558 // }
2559 //
2560 // If we are accessing "Type name;", expand to:
2561 //
2562 // /*synthetic*/ static void access$<num>(BaseType $1, Type name)
2563 // {
2564 // $1.name = name;
2565 // return;
2566 // }
2567 //
2568 // In 1.5 and later, we use the prefix "-" instead of "access$".
2569 //
2570 Semantic* sem = semantic_environment -> sem;
2571 assert(sem);
2572
2573 Control& control = sem -> control;
2574 StoragePool* ast_pool = sem -> compilation_unit -> ast_pool;
2575
2576 IntToWstring value(NumPrivateAccessMethods());
2577
2578 int length = control.access_name_symbol -> NameLength() +
2579 value.Length();
2580 wchar_t* name = new wchar_t[length + 1]; // +1 for '\0';
2581 wcscpy(name, control.access_name_symbol -> Name());
2582 wcscat(name, value.String());
2583
2584 //
2585 // Use the location of the class name for all elements of this method.
2586 //
2587 TokenIndex loc = declaration -> identifier_token;
2588
2589 //
2590 // Add the method instead of inserting it, so it is not an overload
2591 // candidate.
2592 //
2593 write_method =
2594 new MethodSymbol(control.FindOrInsertName(name, length));
2595 Table() -> AddMethodSymbol(write_method);
2596 write_method -> SetType(sem -> control.void_type);
2597 write_method -> SetFlags(ACCESS_STATIC | ACCESS_SYNTHETIC);
2598 if (ACC_STRICTFP())
2599 write_method -> SetACC_STRICTFP();
2600 if (ACC_FINAL())
2601 write_method -> SetACC_FINAL();
2602 write_method -> SetContainingType(this);
2603
2604 BlockSymbol* block_symbol =
2605 new BlockSymbol(member -> ACC_STATIC() ? 1 : 2);
2606 block_symbol -> max_variable_index = 0;
2607 write_method -> SetBlockSymbol(block_symbol);
2608
2609 AstExpression* base;
2610 if (! member -> ACC_STATIC() && base_type == super)
2611 {
2612 //
2613 // Special case - for Outer.super.i where i is an instance field,
2614 // we mark the field access as a super access, to make sure we use
2615 // the correct qualifying instance. Notice that in this case,
2616 // ((Super) Outer.this).i cannot generate an accessor method
2617 // (either i is public or in the same package and thus already
2618 // accessible, or i is protected in a different package and
2619 // therefore inaccessible), so we don't have to worry about a
2620 // conflict in accessor methods for the same base type.
2621 //
2622 base = ast_pool -> GenSuperExpression(loc);
2623 }
2624 else base = ast_pool -> GenName(loc);
2625
2626 AstFieldAccess* left_hand_side = ast_pool -> GenFieldAccess();
2627 left_hand_side -> base = base;
2628 left_hand_side -> identifier_token = loc;
2629 left_hand_side -> symbol = member;
2630
2631 AstMethodDeclarator* method_declarator =
2632 ast_pool -> GenMethodDeclarator();
2633 method_declarator -> identifier_token = loc;
2634 method_declarator -> left_parenthesis_token = loc;
2635 method_declarator -> right_parenthesis_token = loc;
2636
2637 if (member -> ACC_STATIC())
2638 {
2639 method_declarator -> AllocateFormalParameters(1);
2640 base -> symbol = base_type;
2641 }
2642 else
2643 {
2644 method_declarator -> AllocateFormalParameters(2);
2645
2646 NameSymbol* instance_name = control.MakeParameter(1);
2647
2648 VariableSymbol* instance =
2649 block_symbol -> InsertVariableSymbol(instance_name);
2650 instance -> SetACC_SYNTHETIC();
2651 instance -> SetType(base_type == super ? this : base_type);
2652 instance -> SetOwner(write_method);
2653 instance -> SetLocalVariableIndex(block_symbol ->
2654 max_variable_index++);
2655 instance -> MarkComplete();
2656 write_method -> AddFormalParameter(instance);
2657 base -> symbol = (base_type == super
2658 ? (Symbol*) super : (Symbol*) instance);
2659 }
2660
2661 VariableSymbol* symbol =
2662 block_symbol -> InsertVariableSymbol(member -> Identity());
2663 symbol -> SetACC_SYNTHETIC();
2664 symbol -> SetType(member -> Type());
2665 symbol -> SetOwner(write_method);
2666 symbol -> SetLocalVariableIndex(block_symbol -> max_variable_index++);
2667 symbol -> MarkComplete();
2668
2669 if (control.IsDoubleWordType(member -> Type()))
2670 block_symbol -> max_variable_index++;
2671 write_method -> AddFormalParameter(symbol);
2672 // A write access method has no throws clause !
2673 write_method -> SetSignature(control);
2674
2675 AstName* simple_name = ast_pool -> GenName(loc);
2676 simple_name -> symbol = symbol;
2677
2678 AstAssignmentExpression* assignment_expression = ast_pool ->
2679 GenAssignmentExpression(AstAssignmentExpression::SIMPLE_EQUAL,
2680 loc);
2681 assignment_expression -> left_hand_side = left_hand_side;
2682 assignment_expression -> expression = simple_name;
2683
2684 AstExpressionStatement* expression_statement =
2685 ast_pool -> GenExpressionStatement();
2686 expression_statement -> expression = assignment_expression;
2687 expression_statement -> semicolon_token_opt = loc;
2688 expression_statement -> is_reachable = true;
2689 expression_statement -> can_complete_normally = true;
2690
2691 AstReturnStatement* return_statement =
2692 ast_pool -> GenReturnStatement();
2693 return_statement -> return_token = loc;
2694 return_statement -> semicolon_token = loc;
2695 return_statement -> is_reachable = true;
2696
2697 AstMethodBody* block = ast_pool -> GenMethodBody();
2698 block -> left_brace_token = loc;
2699 block -> right_brace_token = loc;
2700 block -> block_symbol = new BlockSymbol(0);
2701 block -> is_reachable = true;
2702 block -> AllocateStatements(2);
2703 block -> AddStatement(expression_statement);
2704 block -> AddStatement(return_statement);
2705
2706 AstMethodDeclaration* method_declaration =
2707 ast_pool -> GenMethodDeclaration();
2708 method_declaration -> method_symbol = write_method;
2709 method_declaration -> method_declarator = method_declarator;
2710 method_declaration -> method_body_opt = block;
2711
2712 write_method -> declaration = method_declaration;
2713 write_method -> accessed_member = member;
2714 MapSymbolToWriteMethod(member, base_type, write_method);
2715 AddPrivateAccessMethod(write_method);
2716
2717 delete [] name;
2718 }
2719 return write_method;
2720 }
2721
2722
GetWriteAccessFromReadAccess(MethodSymbol * read_method)2723 MethodSymbol* TypeSymbol::GetWriteAccessFromReadAccess(MethodSymbol* read_method)
2724 {
2725 assert(read_method && read_method -> ACC_SYNTHETIC() &&
2726 read_method -> containing_type == this);
2727 VariableSymbol* variable =
2728 DYNAMIC_CAST<VariableSymbol*> (read_method -> accessed_member);
2729 AstMethodDeclaration* method_declaration =
2730 DYNAMIC_CAST<AstMethodDeclaration*> (read_method -> declaration);
2731 AstMethodBody* block = method_declaration -> method_body_opt;
2732 AstReturnStatement* return_statement =
2733 DYNAMIC_CAST<AstReturnStatement*> (block -> Statement(0));
2734 AstFieldAccess* field_access =
2735 DYNAMIC_CAST<AstFieldAccess*> (return_statement -> expression_opt);
2736 return GetWriteAccessMethod(variable, field_access -> base -> Type());
2737 }
2738
2739
2740 //
2741 // Create a new placeholder type in order to create a unique parameter in
2742 // accessor constructors. The first anonymous type created in an outer class
2743 // can be used as the placeholder.
2744 //
GetPlaceholderType()2745 TypeSymbol* TypeSymbol::GetPlaceholderType()
2746 {
2747 assert(outermost_type == this);
2748 if (! placeholder_type)
2749 {
2750 //
2751 // Use the location of the class name for all elements of the
2752 // placeholder.
2753 //
2754 Semantic* sem = semantic_environment -> sem;
2755 sem -> state_stack.Push(semantic_environment);
2756 TokenIndex loc = declaration -> identifier_token;
2757 Control& control = sem -> control;
2758 StoragePool* ast_pool = sem -> compilation_unit -> ast_pool;
2759
2760 AstClassBody* class_body = ast_pool -> GenClassBody();
2761 class_body -> left_brace_token = loc;
2762 class_body -> right_brace_token = loc;
2763 AstName* ast_type = ast_pool -> GenName(loc);
2764
2765 AstClassCreationExpression* class_creation =
2766 ast_pool -> GenClassCreationExpression();
2767 class_creation -> new_token = loc;
2768 class_creation -> class_type = ast_pool -> GenTypeName(ast_type);
2769 class_creation -> arguments = ast_pool -> GenArguments(loc, loc);
2770 class_creation -> class_body_opt = class_body;
2771
2772 sem -> GetAnonymousType(class_creation, control.Object());
2773 sem -> state_stack.Pop();
2774 assert(placeholder_type);
2775 placeholder_type -> SetACC_SYNTHETIC();
2776 }
2777 return placeholder_type;
2778 }
2779
2780 #ifdef HAVE_JIKES_NAMESPACE
2781 } // Close namespace Jikes block
2782 #endif
2783
2784