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