1 // $Id: init.cpp,v 1.28 2004/05/03 21:20:23 elliott-oss Exp $
2 //
3 // This software is subject to the terms of the IBM Jikes Compiler
4 // License Agreement available at the following URL:
5 // http://ibm.com/developerworks/opensource/jikes.
6 // Copyright (C) 1996, 2004 IBM Corporation and others.  All Rights Reserved.
7 // You must accept the terms of that agreement to use this software.
8 //
9 
10 #include "platform.h"
11 #include "semantic.h"
12 #include "control.h"
13 #include "stream.h"
14 
15 #ifdef HAVE_JIKES_NAMESPACE
16 namespace Jikes { // Open namespace Jikes block
17 #endif
18 
ProcessVariableInitializer(AstVariableDeclarator * variable_declarator)19 void Semantic::ProcessVariableInitializer(AstVariableDeclarator* variable_declarator)
20 {
21     VariableSymbol* symbol = variable_declarator -> symbol;
22 
23     if (! variable_declarator -> variable_initializer_opt)
24     {
25         symbol -> MarkInitialized();
26         return;
27     }
28 
29     TypeSymbol* field_type = symbol -> Type();
30     AstExpression* init =
31         (AstExpression*) variable_declarator -> variable_initializer_opt;
32     AstArrayInitializer* array_initializer = init -> ArrayInitializerCast();
33     if (array_initializer)
34         ProcessArrayInitializer(array_initializer, field_type);
35     else
36     {
37         ProcessExpressionOrStringConstant(init);
38 
39         if (field_type != init -> Type() && init -> Type() != control.no_type)
40         {
41             if (CanAssignmentConvert(field_type, init))
42             {
43                 init = ConvertToType(init, field_type);
44                 variable_declarator -> variable_initializer_opt = init;
45             }
46             else if (init -> IsConstant() &&
47                      control.IsSimpleIntegerValueType(init -> Type()) &&
48                      control.IsSimpleIntegerValueType(field_type))
49             {
50                 if (field_type == control.byte_type)
51                     ReportSemError(SemanticError::INVALID_BYTE_VALUE, init);
52                 else if (field_type == control.char_type)
53                     ReportSemError(SemanticError::INVALID_CHARACTER_VALUE,
54                                    init);
55                 else ReportSemError(SemanticError::INVALID_SHORT_VALUE, init);
56                 init -> value = NULL;
57             }
58             else
59             {
60                 ReportSemError(SemanticError::INCOMPATIBLE_TYPE_FOR_ASSIGNMENT,
61                                variable_declarator,
62                                field_type -> ContainingPackageName(),
63                                field_type -> ExternalName(),
64                                init -> Type() -> ContainingPackageName(),
65                                init -> Type() -> ExternalName());
66                 init -> value = NULL;
67             }
68         }
69 
70         if (symbol -> ACC_FINAL() &&
71             (field_type -> Primitive() || field_type == control.String()))
72         {
73             if (init -> IsConstant())
74             {
75                 symbol -> initial_value = init -> value;
76             }
77             else if (symbol -> ACC_STATIC() && ThisType() -> IsInner())
78             {
79                 ReportSemError(SemanticError::STATIC_FIELD_IN_INNER_CLASS_NOT_CONSTANT,
80                                variable_declarator,
81                                lex_stream -> NameString(variable_declarator -> LeftToken()),
82                                ThisType() -> Name(), ThisType() -> FileLoc());
83             }
84         }
85     }
86 
87     //
88     // A non-static final field initialized to a constant value wastes
89     // space in each instance, so warn about it.
90     //
91     TypeSymbol* containing_type = symbol -> owner -> TypeCast();
92     if (containing_type && ! containing_type -> ACC_INTERFACE() &&
93         ! field_type -> IsArray() &&
94         symbol -> ACC_FINAL() &&
95         ! symbol -> ACC_STATIC() &&
96         init && init -> IsConstant())
97     {
98         ReportSemError(SemanticError::NON_STATIC_FINAL_CONSTANT_FIELD,
99                        variable_declarator,
100                        lex_stream ->
101                            NameString(variable_declarator -> LeftToken()));
102     }
103 
104     symbol -> MarkInitialized();
105 }
106 
107 
ProcessArrayInitializer(AstArrayInitializer * array_initializer,TypeSymbol * type)108 void Semantic::ProcessArrayInitializer(AstArrayInitializer* array_initializer,
109                                        TypeSymbol* type)
110 {
111     if (! type -> IsArray())
112     {
113         ReportSemError(SemanticError::INIT_SCALAR_WITH_ARRAY,
114                        array_initializer, type -> Name());
115     }
116     else
117     {
118         for (unsigned i = 0;
119              i < array_initializer -> NumVariableInitializers(); i++)
120         {
121             AstArrayInitializer* sub_array_initializer = array_initializer ->
122                 VariableInitializer(i) -> ArrayInitializerCast();
123             TypeSymbol* array_subtype = type -> ArraySubtype();
124             if (sub_array_initializer)
125                  ProcessArrayInitializer(sub_array_initializer, array_subtype);
126             else
127             {
128                 AstExpression* init = (AstExpression*) array_initializer ->
129                     VariableInitializer(i);
130                 ProcessExpressionOrStringConstant(init);
131 
132                 if (array_subtype != init -> Type())
133                 {
134                     if (CanAssignmentConvert(array_subtype, init))
135                         array_initializer -> VariableInitializer(i) =
136                             ConvertToType(init, array_subtype);
137                     else if (array_subtype -> IsArray() &&
138                              init -> Type() -> Primitive())
139                     {
140                         ReportSemError(SemanticError::INIT_ARRAY_WITH_SCALAR,
141                                        init, array_subtype -> Name());
142                     }
143                     else if (init -> IsConstant() &&
144                              control.IsSimpleIntegerValueType(init -> Type()) &&
145                              control.IsSimpleIntegerValueType(array_subtype))
146                     {
147                         if (array_subtype == control.byte_type)
148                             ReportSemError(SemanticError::INVALID_BYTE_VALUE,
149                                            init);
150                         else if (array_subtype == control.char_type)
151                             ReportSemError(SemanticError::INVALID_CHARACTER_VALUE,
152                                            init);
153                         else ReportSemError(SemanticError::INVALID_SHORT_VALUE,
154                                             init);
155                     }
156                     else
157                     {
158                         ReportSemError(SemanticError::INCOMPATIBLE_TYPE_FOR_INITIALIZATION,
159                                        init,
160                                        array_subtype -> ContainingPackageName(),
161                                        array_subtype -> ExternalName(),
162                                        init -> Type() -> ContainingPackageName(),
163                                        init -> Type() -> ExternalName());
164                     }
165                 }
166             }
167         }
168     }
169 }
170 
171 
ComputeFinalValue(VariableSymbol * variable)172 void Semantic::ComputeFinalValue(VariableSymbol* variable)
173 {
174     AstVariableDeclarator* variable_declarator = variable -> declarator;
175     assert(variable_declarator && variable -> ACC_FINAL());
176     if (! variable -> IsInitialized())
177     {
178         if (variable_declarator -> pending ||
179             ! variable_declarator -> variable_initializer_opt)
180         {
181             //
182             // Break loops, and ignore non-initialized fields.
183             //
184             variable -> MarkInitialized();
185             return;
186         }
187 
188         //
189         // Create a clone and process that, to avoid triggering errors now.
190         // Later, we will issue the errors for real when processing the field
191         // initializer when we get to its source file.
192         //
193         TypeSymbol* type = variable -> ContainingType();
194         Semantic* sem = type -> semantic_environment -> sem;
195 
196         if (! sem -> error)
197             sem -> error =
198                 new SemanticError(control, sem -> source_file_symbol);
199         sem -> error -> EnteringClone();
200         sem -> state_stack.Push(type -> semantic_environment);
201         MethodSymbol* calling_method = sem -> ThisMethod();
202         VariableSymbol* calling_var = sem -> ThisVariable();
203         sem -> ThisMethod() = NULL;
204         sem -> ThisVariable() = variable;
205         variable_declarator -> pending = true;
206 
207         StoragePool pool(variable_declarator -> RightToken() -
208                          variable_declarator -> LeftToken());
209         AstVariableDeclarator* clone = (AstVariableDeclarator*)
210             variable_declarator -> Clone(&pool);
211         clone -> symbol = variable;
212         sem -> ProcessVariableInitializer(clone);
213         assert(variable -> IsInitialized());
214 
215         variable_declarator -> pending = false;
216         sem -> ThisMethod() = calling_method;
217         sem -> ThisVariable() = calling_var;
218         sem -> state_stack.Pop();
219         sem -> error -> ExitingClone();
220     }
221 }
222 
223 #ifdef HAVE_JIKES_NAMESPACE
224 } // Close namespace Jikes block
225 #endif
226 
227