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