adlint 2.6.0 → 2.6.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/ChangeLog +122 -0
- data/MANIFEST +1 -0
- data/NEWS +23 -4
- data/README +1 -1
- data/Rakefile +1 -1
- data/etc/mesg.d/c_builtin/en_US/messages.yml +8 -8
- data/etc/mesg.d/c_builtin/ja_JP/messages.yml +8 -8
- data/etc/mesg.d/core/en_US/messages.yml +1 -1
- data/etc/mesg.d/core/ja_JP/messages.yml +1 -1
- data/features/code_check/W0599.feature +71 -0
- data/lib/adlint/c/builtin.rb +1 -1
- data/lib/adlint/c/const.rb +60 -60
- data/lib/adlint/c/conv.rb +3 -3
- data/lib/adlint/c/ctrlexpr.rb +278 -357
- data/lib/adlint/c/expr.rb +1232 -1637
- data/lib/adlint/c/format.rb +26 -26
- data/lib/adlint/c/interp.rb +339 -391
- data/lib/adlint/c/mediator.rb +1 -2
- data/lib/adlint/c/object.rb +8 -9
- data/lib/adlint/c/seqp.rb +1 -1
- data/lib/adlint/c/syntax.rb +6 -6
- data/lib/adlint/c/type.rb +8 -8
- data/lib/adlint/cpp/eval.rb +1 -1
- data/lib/adlint/cpp/macro.rb +4 -4
- data/lib/adlint/cpp/util.rb +1 -1
- data/lib/adlint/exam/c_builtin/c_check.rb +93 -95
- data/lib/adlint/exam/c_builtin/ld_check.rb +4 -4
- data/lib/adlint/traits.rb +7 -16
- data/lib/adlint/util.rb +12 -0
- data/lib/adlint/version.rb +2 -2
- data/share/doc/developers_guide_ja.html +3 -3
- data/share/doc/developers_guide_ja.texi +1 -1
- data/share/doc/users_guide_en.html +32 -32
- data/share/doc/users_guide_en.texi +30 -30
- data/share/doc/users_guide_ja.html +32 -32
- data/share/doc/users_guide_ja.texi +30 -30
- metadata +4 -3
data/lib/adlint/c/expr.rb
CHANGED
@@ -37,1926 +37,1521 @@ require "adlint/c/seqp"
|
|
37
37
|
module AdLint #:nodoc:
|
38
38
|
module C #:nodoc:
|
39
39
|
|
40
|
-
module
|
41
|
-
# NOTE: Host class of this module must include InterpreterMediator
|
42
|
-
#
|
43
|
-
|
44
|
-
def execute_object_specifier(node)
|
45
|
-
if variable = variable_named(node.identifier.value)
|
46
|
-
variable.declarations_and_definitions.each do |decl_or_def|
|
47
|
-
decl_or_def.mark_as_referred_by(node.identifier)
|
48
|
-
end
|
49
|
-
_notify_object_referred(node, variable)
|
50
|
-
# NOTE: Array object will be converted into its start address by the
|
51
|
-
# outer expression. So, it is correct to return an array object
|
52
|
-
# itself.
|
53
|
-
return variable
|
54
|
-
end
|
55
|
-
|
56
|
-
if function = function_named(node.identifier.value)
|
57
|
-
function.declarations_and_definitions.each do |decl_or_def|
|
58
|
-
decl_or_def.mark_as_referred_by(node.identifier)
|
59
|
-
end
|
60
|
-
_notify_object_referred(node, function)
|
61
|
-
return function
|
62
|
-
end
|
63
|
-
|
64
|
-
if enumerator = enumerator_named(node.identifier.value)
|
65
|
-
enumerator.mark_as_referred_by(node.identifier)
|
66
|
-
return temporary_variable(enumerator.type,
|
67
|
-
ScalarValue.of(enumerator.value))
|
68
|
-
end
|
69
|
-
|
70
|
-
define_implicit_function(node.identifier.value)
|
71
|
-
end
|
72
|
-
|
73
|
-
def execute_array_subscript_expression(node, object, subscript)
|
74
|
-
unless object.variable? && (object.type.array? || object.type.pointer?)
|
75
|
-
return temporary_variable
|
76
|
-
end
|
77
|
-
|
78
|
-
array_or_pointer = object
|
79
|
-
result_type = array_or_pointer.type.unqualify.base_type
|
80
|
-
|
81
|
-
case
|
82
|
-
when array_or_pointer.type.array?
|
83
|
-
array = array_or_pointer
|
84
|
-
# NOTE: An array-subscript-expression with an array object only refers
|
85
|
-
# the array object, never refer the value of the array object.
|
86
|
-
when array_or_pointer.type.pointer?
|
87
|
-
if pointee = pointee_of(array_or_pointer) and pointee.type.array?
|
88
|
-
array = pointee
|
89
|
-
end
|
90
|
-
# NOTE: An array-subscript-expression with a pointer object do refers
|
91
|
-
# the value of the pointer object.
|
92
|
-
_notify_variable_value_referred(node, array_or_pointer)
|
93
|
-
end
|
94
|
-
|
95
|
-
unless subscript.variable? and
|
96
|
-
subscript.value.scalar? && subscript.value.exist? or
|
97
|
-
subscript.type.void?
|
98
|
-
# NOTE: To detect bad value reference of `void' expressions.
|
99
|
-
return temporary_variable(result_type)
|
100
|
-
end
|
101
|
-
_notify_variable_value_referred(node, subscript)
|
102
|
-
|
103
|
-
# NOTE: An array subscript converted to `int' implicitly.
|
104
|
-
if subscript.type.same_as?(int_type)
|
105
|
-
int_subscript = subscript
|
106
|
-
else
|
107
|
-
if int_subscript = do_conversion(subscript, int_type)
|
108
|
-
notify_implicit_conv_performed(node.array_subscript,
|
109
|
-
subscript, int_subscript)
|
110
|
-
else
|
111
|
-
return temporary_variable(result_type)
|
112
|
-
end
|
113
|
-
end
|
114
|
-
|
115
|
-
# FIXME: Domain of the subscript may have multiple values.
|
116
|
-
subscript_value = int_subscript.value.unique_sample
|
117
|
-
if array and inner_variable = array.inner_variable_at(subscript_value)
|
118
|
-
_notify_object_referred(node, inner_variable)
|
119
|
-
if inner_variable.type.same_as?(result_type)
|
120
|
-
result = inner_variable
|
121
|
-
end
|
122
|
-
end
|
123
|
-
result ||= temporary_variable(result_type)
|
124
|
-
|
125
|
-
notify_array_subscript_expr_evaled(node, array_or_pointer,
|
126
|
-
int_subscript, array, result)
|
127
|
-
result
|
128
|
-
end
|
129
|
-
|
130
|
-
def execute_function_call_expression(node, object, args)
|
131
|
-
if object.function?
|
132
|
-
function = object
|
133
|
-
else
|
134
|
-
if object.type.pointer? && object.type.unqualify.base_type.function?
|
135
|
-
if pointee = pointee_of(object) and pointee.function?
|
136
|
-
function = pointee
|
137
|
-
else
|
138
|
-
function_type = object.type.unqualify.base_type
|
139
|
-
function = define_anonymous_function(function_type)
|
140
|
-
end
|
141
|
-
else
|
142
|
-
return temporary_variable
|
143
|
-
end
|
144
|
-
end
|
145
|
-
_notify_variable_value_referred(node, object)
|
146
|
-
|
147
|
-
# NOTE: The ISO C99 standard saids;
|
148
|
-
#
|
149
|
-
# 6.5.2.2 Function calls
|
150
|
-
#
|
151
|
-
# Semantics
|
152
|
-
#
|
153
|
-
# 10 The order of evaluation of the function designator, the actual
|
154
|
-
# arguments, and subexpressions within the actual arguments is
|
155
|
-
# unspecified, but there is a sequence point before the actual call.
|
156
|
-
notify_sequence_point_reached(SequencePoint.new(node)) unless args.empty?
|
157
|
-
|
158
|
-
result = function.call(interpreter, node, args)
|
159
|
-
unless function.builtin?
|
160
|
-
arg_variables = args.map { |arg, expr| object_to_variable(arg) }
|
161
|
-
notify_function_call_expr_evaled(node, function, arg_variables, result)
|
162
|
-
end
|
163
|
-
|
164
|
-
result
|
165
|
-
end
|
166
|
-
|
167
|
-
def execute_member_access_by_value_expression(node, object)
|
168
|
-
unless object.variable? && object.type.composite?
|
169
|
-
return temporary_variable
|
170
|
-
end
|
171
|
-
variable = object
|
172
|
-
|
173
|
-
member_variable = variable.inner_variable_named(node.identifier.value)
|
174
|
-
# NOTE: A member-access-by-value-expression only refers the composite
|
175
|
-
# object, never refer the value of the composite object.
|
176
|
-
|
177
|
-
# NOTE: `member_variable' is nil when this expression represents the
|
178
|
-
# direct member access extension.
|
179
|
-
notify_member_access_expr_evaled(node, variable, member_variable)
|
180
|
-
|
181
|
-
if member_variable
|
182
|
-
_notify_object_referred(node, member_variable)
|
183
|
-
member_variable
|
184
|
-
else
|
185
|
-
temporary_variable
|
186
|
-
end
|
187
|
-
end
|
188
|
-
|
189
|
-
def execute_member_access_by_pointer_expression(node, object)
|
190
|
-
unqualified_type = object.type.unqualify
|
191
|
-
|
192
|
-
unless object.variable? && unqualified_type.pointer? &&
|
193
|
-
unqualified_type.base_type.composite?
|
194
|
-
return temporary_variable
|
195
|
-
end
|
196
|
-
pointer = object
|
197
|
-
|
198
|
-
if pointee = pointee_of(pointer)
|
199
|
-
if pointee.type.array?
|
200
|
-
if first_element = pointee.inner_variable_at(0)
|
201
|
-
pointee = first_element
|
202
|
-
else
|
203
|
-
pointee = temporary_variable(object.type.unqualify.base_type)
|
204
|
-
end
|
205
|
-
end
|
206
|
-
end
|
207
|
-
# NOTE: A member-access-by-pointer-expression do refers the value of the
|
208
|
-
# pointer object.
|
209
|
-
_notify_variable_value_referred(node, pointer)
|
210
|
-
|
211
|
-
if pointee && pointee.type.composite?
|
212
|
-
member_variable = pointee.inner_variable_named(node.identifier.value)
|
213
|
-
else
|
214
|
-
member = unqualified_type.base_type.member_named(node.identifier.value)
|
215
|
-
member_variable = temporary_variable(member.type) if member
|
216
|
-
end
|
217
|
-
|
218
|
-
# NOTE: `member_variable' is nil when this expression represents the
|
219
|
-
# direct member access extension.
|
220
|
-
notify_member_access_expr_evaled(node, pointer, member_variable)
|
221
|
-
|
222
|
-
if member_variable
|
223
|
-
_notify_object_referred(node, member_variable)
|
224
|
-
member_variable
|
225
|
-
else
|
226
|
-
temporary_variable
|
227
|
-
end
|
228
|
-
end
|
229
|
-
|
230
|
-
def execute_postfix_increment_expression(node, object)
|
231
|
-
return temporary_variable unless object.variable? && object.type.scalar?
|
232
|
-
variable = object
|
233
|
-
|
234
|
-
result = temporary_variable(variable.type, variable.value.dup)
|
235
|
-
|
236
|
-
# NOTE: Value of the variable is referred at this point. But value
|
237
|
-
# reference should not be notified not to confuse sequence-point
|
238
|
-
# warning detections.
|
239
|
-
# _notify_variable_value_referred(node, variable)
|
240
|
-
|
241
|
-
if variable.value.scalar?
|
242
|
-
variable.assign!(variable.value + ScalarValue.of(1))
|
243
|
-
_notify_variable_value_updated(node, variable)
|
244
|
-
end
|
245
|
-
|
246
|
-
notify_postfix_increment_expr_evaled(node, variable, result)
|
247
|
-
|
248
|
-
result
|
249
|
-
end
|
250
|
-
|
251
|
-
def execute_postfix_decrement_expression(node, object)
|
252
|
-
return temporary_variable unless object.variable? && object.type.scalar?
|
253
|
-
variable = object
|
254
|
-
|
255
|
-
result = temporary_variable(variable.type, variable.value.dup)
|
256
|
-
|
257
|
-
# NOTE: Value of the variable is referred at this point. But value
|
258
|
-
# reference should not be notified not to confuse sequence-point
|
259
|
-
# warnings detections.
|
260
|
-
# _notify_variable_value_referred(node, variable)
|
261
|
-
|
262
|
-
if variable.value.scalar?
|
263
|
-
variable.assign!(variable.value - ScalarValue.of(1))
|
264
|
-
_notify_variable_value_updated(node, variable)
|
265
|
-
end
|
266
|
-
|
267
|
-
notify_postfix_decrement_expr_evaled(node, variable, result)
|
268
|
-
|
269
|
-
result
|
270
|
-
end
|
271
|
-
|
272
|
-
def execute_prefix_increment_expression(node, object)
|
273
|
-
return temporary_variable unless object.variable? && object.type.scalar?
|
274
|
-
variable = object
|
275
|
-
|
276
|
-
original_value = variable.value.dup
|
277
|
-
|
278
|
-
# NOTE: Value of the variable is referred at this point. But value
|
279
|
-
# reference should not be notified not to confuse sequence-point
|
280
|
-
# warnings detections.
|
281
|
-
# _notify_variable_value_referred(node, variable)
|
282
|
-
|
283
|
-
if variable.value.scalar?
|
284
|
-
variable.assign!(variable.value + ScalarValue.of(1))
|
285
|
-
_notify_variable_value_updated(node, variable)
|
286
|
-
end
|
287
|
-
|
288
|
-
notify_prefix_increment_expr_evaled(node, variable, original_value)
|
289
|
-
|
290
|
-
temporary_variable(variable.type, variable.value)
|
291
|
-
end
|
292
|
-
|
293
|
-
def execute_prefix_decrement_expression(node, object)
|
294
|
-
return temporary_variable unless object.variable? && object.type.scalar?
|
295
|
-
variable = object
|
296
|
-
|
297
|
-
original_value = variable.value.dup
|
298
|
-
|
299
|
-
# NOTE: Value of the variable is referred at this point. But value
|
300
|
-
# reference should not be notified not to confuse sequence-point
|
301
|
-
# warning detections.
|
302
|
-
# _notify_variable_value_referred(node, variable)
|
303
|
-
|
304
|
-
if variable.value.scalar?
|
305
|
-
variable.assign!(variable.value - ScalarValue.of(1))
|
306
|
-
_notify_variable_value_updated(node, variable)
|
307
|
-
end
|
308
|
-
|
309
|
-
notify_prefix_decrement_expr_evaled(node, variable, original_value)
|
310
|
-
|
311
|
-
temporary_variable(variable.type, variable.value)
|
312
|
-
end
|
313
|
-
|
314
|
-
def execute_address_expression(node, object)
|
315
|
-
# NOTE: An address-expression does not read the value of the object. But
|
316
|
-
# value reference should be notified to emphasize global variable
|
317
|
-
# cross-references.
|
318
|
-
_notify_variable_value_referred(node, object)
|
319
|
-
|
320
|
-
pointer = temporary_variable(pointer_type(object.type),
|
321
|
-
pointer_value_of(object))
|
322
|
-
|
323
|
-
notify_address_expr_evaled(node, object, pointer)
|
324
|
-
pointer
|
325
|
-
end
|
326
|
-
|
327
|
-
def execute_indirection_expression(node, object)
|
328
|
-
return temporary_variable unless object.variable? && object.type.pointer?
|
329
|
-
pointer = object
|
330
|
-
|
331
|
-
unqualified_type = pointer.type.unqualify
|
332
|
-
pointee = pointee_of(pointer)
|
333
|
-
_notify_variable_value_referred(node, pointer)
|
334
|
-
|
335
|
-
case
|
336
|
-
when pointee
|
337
|
-
_notify_object_referred(node, pointee)
|
338
|
-
if pointee.type.array?
|
339
|
-
if first_element = pointee.inner_variable_at(0)
|
340
|
-
pointee = first_element
|
341
|
-
else
|
342
|
-
pointee = temporary_variable(unqualified_type.base_type)
|
343
|
-
end
|
344
|
-
end
|
345
|
-
|
346
|
-
unless unqualified_type.base_type.same_as?(pointee.type)
|
347
|
-
pointee =
|
348
|
-
do_conversion(pointee, unqualified_type.base_type) ||
|
349
|
-
temporary_variable(unqualified_type.base_type)
|
350
|
-
end
|
351
|
-
when unqualified_type.base_type.function?
|
352
|
-
pointee = define_anonymous_function(unqualified_type.base_type)
|
353
|
-
else
|
354
|
-
pointee = temporary_variable(unqualified_type.base_type)
|
355
|
-
end
|
356
|
-
|
357
|
-
notify_indirection_expr_evaled(node, pointer, pointee)
|
358
|
-
|
359
|
-
pointee
|
360
|
-
end
|
361
|
-
|
362
|
-
def execute_unary_arithmetic_expression(node, object)
|
363
|
-
variable = object_to_variable(object)
|
364
|
-
unless variable.type.scalar? || variable.type.void?
|
365
|
-
# NOTE: To detect bad value reference of `void' expressions.
|
366
|
-
return temporary_variable
|
367
|
-
end
|
368
|
-
|
369
|
-
unless variable == object
|
370
|
-
notify_implicit_conv_performed(node.operand, object, variable)
|
371
|
-
end
|
372
|
-
|
373
|
-
case node.operator.type
|
374
|
-
when "+"
|
375
|
-
result = temporary_variable(variable.type, +variable.value)
|
376
|
-
when "-"
|
377
|
-
result = temporary_variable(variable.type, -variable.value)
|
378
|
-
when "~"
|
379
|
-
result = temporary_variable(variable.type, ~variable.value)
|
380
|
-
when "!"
|
381
|
-
result = temporary_variable(int_type, !variable.value)
|
382
|
-
else
|
383
|
-
__NOTREACHED__
|
384
|
-
end
|
385
|
-
_notify_variable_value_referred(node, variable)
|
40
|
+
module ExpressionEvaluator
|
41
|
+
# NOTE: Host class of this module must include InterpreterMediator and
|
42
|
+
# MonitorUtil.
|
386
43
|
|
387
|
-
|
44
|
+
include NotifierMediator
|
45
|
+
include ConstantEvaluator
|
46
|
+
include Conversion
|
388
47
|
|
389
|
-
|
48
|
+
def visit_error_expression(node)
|
49
|
+
checkpoint(node.location)
|
50
|
+
create_tempvar
|
390
51
|
end
|
391
52
|
|
392
|
-
def
|
393
|
-
|
394
|
-
|
395
|
-
variable = object_to_variable(object)
|
396
|
-
converted =
|
397
|
-
do_conversion(variable, node.type_name.type) ||
|
398
|
-
temporary_variable(node.type_name.type)
|
399
|
-
|
400
|
-
notify_explicit_conv_performed(node, variable, converted)
|
401
|
-
|
402
|
-
# NOTE: A cast-expression does not refer a source value essentially.
|
403
|
-
# But, to avoid misunderstand that a return value of a function is
|
404
|
-
# discarded when the return value is casted before assigning to a
|
405
|
-
# variable.
|
406
|
-
_notify_variable_value_referred(node, variable)
|
407
|
-
|
408
|
-
converted
|
53
|
+
def visit_object_specifier(node)
|
54
|
+
checkpoint(node.location)
|
55
|
+
eval_object_specifier(node)
|
409
56
|
end
|
410
57
|
|
411
|
-
def
|
412
|
-
|
413
|
-
unless lhs_variable.type.scalar? || lhs_variable.type.void?
|
414
|
-
# NOTE: To detect bad value reference of `void' expressions.
|
415
|
-
return temporary_variable
|
416
|
-
end
|
417
|
-
|
418
|
-
unless lhs_variable == lhs_object
|
419
|
-
notify_implicit_conv_performed(node.lhs_operand,
|
420
|
-
lhs_object, lhs_variable)
|
421
|
-
end
|
422
|
-
|
423
|
-
rhs_variable = object_to_variable(rhs_object)
|
424
|
-
unless rhs_variable.type.scalar? || rhs_variable.type.void?
|
425
|
-
# NOTE: To detect bad value reference of `void' expressions.
|
426
|
-
return temporary_variable
|
427
|
-
end
|
428
|
-
|
429
|
-
unless rhs_variable == rhs_object
|
430
|
-
notify_implicit_conv_performed(node.rhs_operand,
|
431
|
-
rhs_object, rhs_variable)
|
432
|
-
end
|
433
|
-
|
434
|
-
lhs_converted, rhs_converted =
|
435
|
-
do_usual_arithmetic_conversion(lhs_variable, rhs_variable)
|
436
|
-
|
437
|
-
unless lhs_variable == lhs_converted
|
438
|
-
notify_implicit_conv_performed(node.lhs_operand,
|
439
|
-
lhs_variable, lhs_converted)
|
440
|
-
end
|
441
|
-
|
442
|
-
unless rhs_variable == rhs_converted
|
443
|
-
notify_implicit_conv_performed(node.rhs_operand,
|
444
|
-
rhs_variable, rhs_converted)
|
445
|
-
end
|
58
|
+
def visit_constant_specifier(node)
|
59
|
+
checkpoint(node.location)
|
446
60
|
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
# min-max of the variable type.
|
451
|
-
result = temporary_variable(lhs_converted.type,
|
452
|
-
lhs_converted.value * rhs_converted.value)
|
453
|
-
when "/"
|
454
|
-
# NOTE: Domain of the arithmetic result value will be restricted by
|
455
|
-
# min-max of the variable type.
|
456
|
-
# NOTE: "Div by 0" semantics is implemented in value-value arithmetic.
|
457
|
-
result = temporary_variable(lhs_converted.type,
|
458
|
-
lhs_converted.value / rhs_converted.value)
|
459
|
-
when "%"
|
460
|
-
# NOTE: Domain of the arithmetic result value will be restricted by
|
461
|
-
# min-max of the variable type.
|
462
|
-
# NOTE: "Div by 0" semantics is implemented in value-value arithmetic.
|
463
|
-
result = temporary_variable(lhs_converted.type,
|
464
|
-
lhs_converted.value % rhs_converted.value)
|
61
|
+
if const_var = eval_constant(node)
|
62
|
+
notify_constant_referred(node, const_var)
|
63
|
+
const_var
|
465
64
|
else
|
466
|
-
|
65
|
+
create_tempvar
|
467
66
|
end
|
468
|
-
_notify_variable_value_referred(node, lhs_variable)
|
469
|
-
_notify_variable_value_referred(node, rhs_variable)
|
470
|
-
|
471
|
-
notify_multiplicative_expr_evaled(node, lhs_variable, rhs_variable,
|
472
|
-
result)
|
473
|
-
result
|
474
67
|
end
|
475
68
|
|
476
|
-
def
|
477
|
-
|
478
|
-
unless lhs_variable.type.scalar? || lhs_variable.type.void?
|
479
|
-
# NOTE: To detect bad value reference of `void' expressions.
|
480
|
-
return temporary_variable
|
481
|
-
end
|
482
|
-
|
483
|
-
unless lhs_variable == lhs_object
|
484
|
-
notify_implicit_conv_performed(node.lhs_operand,
|
485
|
-
lhs_object, lhs_variable)
|
486
|
-
end
|
487
|
-
|
488
|
-
rhs_variable = object_to_variable(rhs_object)
|
489
|
-
unless rhs_variable.type.scalar? || rhs_variable.type.void?
|
490
|
-
# NOTE: To detect bad value reference of `void' expressions.
|
491
|
-
return temporary_variable
|
492
|
-
end
|
493
|
-
|
494
|
-
unless rhs_variable == rhs_object
|
495
|
-
notify_implicit_conv_performed(node.rhs_operand,
|
496
|
-
rhs_object, rhs_variable)
|
497
|
-
end
|
498
|
-
|
499
|
-
lhs_converted, rhs_converted =
|
500
|
-
do_usual_arithmetic_conversion(lhs_variable, rhs_variable)
|
501
|
-
|
502
|
-
unless lhs_variable == lhs_converted
|
503
|
-
notify_implicit_conv_performed(node.lhs_operand,
|
504
|
-
lhs_variable, lhs_converted)
|
505
|
-
end
|
506
|
-
|
507
|
-
unless rhs_variable == rhs_converted
|
508
|
-
notify_implicit_conv_performed(node.rhs_operand,
|
509
|
-
rhs_variable, rhs_converted)
|
510
|
-
end
|
69
|
+
def visit_string_literal_specifier(node)
|
70
|
+
checkpoint(node.location)
|
511
71
|
|
512
|
-
case node.
|
513
|
-
when "
|
514
|
-
|
515
|
-
|
516
|
-
|
517
|
-
|
518
|
-
|
519
|
-
# NOTE: Domain of the arithmetic result value will be restricted by
|
520
|
-
# min-max of the variable type.
|
521
|
-
result = temporary_variable(lhs_converted.type,
|
522
|
-
lhs_converted.value - rhs_converted.value)
|
72
|
+
case node.literal.value
|
73
|
+
when /\A"(.*)"\z/
|
74
|
+
create_tempvar(array_type(char_type, $1.length + 1),
|
75
|
+
create_array_value_of_string($1))
|
76
|
+
when /\AL"(.*)"\z/i
|
77
|
+
create_tempvar(array_type(wchar_type, $1.length + 1),
|
78
|
+
create_array_value_of_string($1))
|
523
79
|
else
|
524
|
-
|
80
|
+
create_tempvar(array_type(char_type))
|
525
81
|
end
|
526
|
-
_notify_variable_value_referred(node, lhs_variable)
|
527
|
-
_notify_variable_value_referred(node, rhs_variable)
|
528
|
-
|
529
|
-
notify_additive_expr_evaled(node, lhs_variable, rhs_variable, result)
|
530
|
-
|
531
|
-
result
|
532
82
|
end
|
533
83
|
|
534
|
-
def
|
535
|
-
|
536
|
-
|
537
|
-
|
538
|
-
|
539
|
-
end
|
540
|
-
|
541
|
-
unless lhs_variable == lhs_object
|
542
|
-
notify_implicit_conv_performed(node.lhs_operand,
|
543
|
-
lhs_object, lhs_variable)
|
544
|
-
end
|
545
|
-
|
546
|
-
rhs_variable = object_to_variable(rhs_object)
|
547
|
-
unless rhs_variable.type.scalar? || rhs_variable.type.void?
|
548
|
-
# NOTE: To detect bad value reference of `void' expressions.
|
549
|
-
return temporary_variable
|
550
|
-
end
|
551
|
-
|
552
|
-
unless rhs_variable == rhs_object
|
553
|
-
notify_implicit_conv_performed(node.rhs_operand,
|
554
|
-
rhs_object, rhs_variable)
|
555
|
-
end
|
556
|
-
|
557
|
-
# NOTE: The ISO C99 standard saids;
|
558
|
-
#
|
559
|
-
# 6.5.7 Bitwise shift operators
|
560
|
-
#
|
561
|
-
# 3 The integer promotions are performed on each of the operands. The
|
562
|
-
# type of the result is that of the promoted left operand. If the
|
563
|
-
# value of the right operand is negative or is greater than or equal to
|
564
|
-
# the width of the promoted left operand, the behavior is undefined.
|
565
|
-
|
566
|
-
lhs_converted = do_integer_promotion(lhs_variable)
|
567
|
-
unless lhs_variable == lhs_converted
|
568
|
-
notify_implicit_conv_performed(node.lhs_operand,
|
569
|
-
lhs_variable, lhs_converted)
|
570
|
-
end
|
571
|
-
|
572
|
-
rhs_converted = do_integer_promotion(rhs_variable)
|
573
|
-
unless rhs_variable == rhs_converted
|
574
|
-
notify_implicit_conv_performed(node.rhs_operand,
|
575
|
-
rhs_variable, rhs_converted)
|
576
|
-
end
|
577
|
-
|
578
|
-
case node.operator.type
|
579
|
-
when "<<"
|
580
|
-
# NOTE: Domain of the arithmetic result value will be restricted by
|
581
|
-
# min-max of the variable type.
|
582
|
-
result = temporary_variable(lhs_converted.type,
|
583
|
-
lhs_converted.value << rhs_converted.value)
|
584
|
-
when ">>"
|
585
|
-
# NOTE: Domain of the arithmetic result value will be restricted by
|
586
|
-
# min-max of the variable type.
|
587
|
-
result = temporary_variable(lhs_converted.type,
|
588
|
-
lhs_converted.value >> rhs_converted.value)
|
589
|
-
else
|
590
|
-
__NOTREACHED__
|
591
|
-
end
|
592
|
-
_notify_variable_value_referred(node, lhs_variable)
|
593
|
-
_notify_variable_value_referred(node, rhs_variable)
|
594
|
-
|
595
|
-
notify_shift_expr_evaled(node, lhs_variable, rhs_variable, result)
|
596
|
-
|
597
|
-
result
|
84
|
+
def visit_null_constant_specifier(node)
|
85
|
+
checkpoint(node.location)
|
86
|
+
# TODO: NULL may not be 0 on some environments.
|
87
|
+
# Representation of NULL should be configurable?
|
88
|
+
create_tempvar(pointer_type(void_type), ScalarValue.of(0))
|
598
89
|
end
|
599
90
|
|
600
|
-
def
|
601
|
-
|
602
|
-
|
603
|
-
# NOTE: To detect bad value reference of `void' expressions.
|
604
|
-
return temporary_variable(int_type, ScalarValue.of_arbitrary)
|
605
|
-
end
|
606
|
-
|
607
|
-
unless lhs_variable == lhs_object
|
608
|
-
notify_implicit_conv_performed(node.lhs_operand,
|
609
|
-
lhs_object, lhs_variable)
|
610
|
-
end
|
611
|
-
|
612
|
-
rhs_variable = object_to_variable(rhs_object)
|
613
|
-
unless rhs_variable.type.scalar? || rhs_variable.type.void?
|
614
|
-
# NOTE: To detect bad value reference of `void' expressions.
|
615
|
-
return temporary_variable(int_type, ScalarValue.of_arbitrary)
|
616
|
-
end
|
617
|
-
|
618
|
-
unless rhs_variable == rhs_object
|
619
|
-
notify_implicit_conv_performed(node.rhs_operand,
|
620
|
-
rhs_object, rhs_variable)
|
621
|
-
end
|
622
|
-
|
623
|
-
lhs_converted, rhs_converted =
|
624
|
-
do_usual_arithmetic_conversion(lhs_variable, rhs_variable)
|
625
|
-
|
626
|
-
unless lhs_variable == lhs_converted
|
627
|
-
notify_implicit_conv_performed(node.lhs_operand,
|
628
|
-
lhs_variable, lhs_converted)
|
629
|
-
end
|
630
|
-
|
631
|
-
unless rhs_variable == rhs_converted
|
632
|
-
notify_implicit_conv_performed(node.rhs_operand,
|
633
|
-
rhs_variable, rhs_converted)
|
634
|
-
end
|
635
|
-
|
636
|
-
case node.operator.type
|
637
|
-
when "<"
|
638
|
-
result = temporary_variable(int_type,
|
639
|
-
lhs_converted.value < rhs_converted.value)
|
640
|
-
when ">"
|
641
|
-
result = temporary_variable(int_type,
|
642
|
-
lhs_converted.value > rhs_converted.value)
|
643
|
-
when "<="
|
644
|
-
result = temporary_variable(int_type,
|
645
|
-
lhs_converted.value <= rhs_converted.value)
|
646
|
-
when ">="
|
647
|
-
result = temporary_variable(int_type,
|
648
|
-
lhs_converted.value >= rhs_converted.value)
|
649
|
-
else
|
650
|
-
__NOTREACHED__
|
651
|
-
end
|
652
|
-
_notify_variable_value_referred(node, lhs_variable)
|
653
|
-
_notify_variable_value_referred(node, rhs_variable)
|
654
|
-
|
655
|
-
notify_relational_expr_evaled(node, lhs_variable, rhs_variable, result)
|
656
|
-
|
657
|
-
result
|
91
|
+
def visit_grouped_expression(node)
|
92
|
+
checkpoint(node.location)
|
93
|
+
node.expression.accept(self)
|
658
94
|
end
|
659
95
|
|
660
|
-
def
|
661
|
-
|
662
|
-
|
663
|
-
|
664
|
-
return temporary_variable(int_type, ScalarValue.of_arbitrary)
|
665
|
-
end
|
666
|
-
|
667
|
-
unless lhs_variable == lhs_object
|
668
|
-
notify_implicit_conv_performed(node.lhs_operand,
|
669
|
-
lhs_object, lhs_variable)
|
670
|
-
end
|
671
|
-
|
672
|
-
rhs_variable = object_to_variable(rhs_object)
|
673
|
-
unless rhs_variable.type.scalar? || rhs_variable.type.void?
|
674
|
-
# NOTE: To detect bad value reference of `void' expressions.
|
675
|
-
return temporary_variable(int_type, ScalarValue.of_arbitrary)
|
676
|
-
end
|
677
|
-
|
678
|
-
unless rhs_variable == rhs_object
|
679
|
-
notify_implicit_conv_performed(node.rhs_operand,
|
680
|
-
rhs_object, rhs_variable)
|
681
|
-
end
|
682
|
-
|
683
|
-
lhs_converted, rhs_converted =
|
684
|
-
do_usual_arithmetic_conversion(lhs_variable, rhs_variable)
|
685
|
-
|
686
|
-
unless lhs_variable == lhs_converted
|
687
|
-
notify_implicit_conv_performed(node.lhs_operand,
|
688
|
-
lhs_variable, lhs_converted)
|
689
|
-
end
|
690
|
-
|
691
|
-
unless rhs_variable == rhs_converted
|
692
|
-
notify_implicit_conv_performed(node.rhs_operand,
|
693
|
-
rhs_variable, rhs_converted)
|
694
|
-
end
|
695
|
-
|
696
|
-
case node.operator.type
|
697
|
-
when "=="
|
698
|
-
result = temporary_variable(int_type,
|
699
|
-
lhs_converted.value == rhs_converted.value)
|
700
|
-
when "!="
|
701
|
-
result = temporary_variable(int_type,
|
702
|
-
lhs_converted.value != rhs_converted.value)
|
703
|
-
else
|
704
|
-
__NOTREACHED__
|
705
|
-
end
|
706
|
-
_notify_variable_value_referred(node, lhs_variable)
|
707
|
-
_notify_variable_value_referred(node, rhs_variable)
|
708
|
-
|
709
|
-
notify_equality_expr_evaled(node, lhs_variable, rhs_variable, result)
|
710
|
-
|
711
|
-
result
|
96
|
+
def visit_array_subscript_expression(node)
|
97
|
+
checkpoint(node.location)
|
98
|
+
eval_array_subscript_expr(node, node.expression.accept(self),
|
99
|
+
node.array_subscript.accept(self))
|
712
100
|
end
|
713
101
|
|
714
|
-
def
|
715
|
-
|
716
|
-
|
717
|
-
|
718
|
-
return temporary_variable
|
719
|
-
end
|
720
|
-
|
721
|
-
unless lhs_variable == lhs_object
|
722
|
-
notify_implicit_conv_performed(node.lhs_operand,
|
723
|
-
lhs_object, lhs_variable)
|
724
|
-
end
|
725
|
-
|
726
|
-
rhs_variable = object_to_variable(rhs_object)
|
727
|
-
unless rhs_variable.type.scalar? || rhs_variable.type.void?
|
728
|
-
# NOTE: To detect bad value reference of `void' expressions.
|
729
|
-
return temporary_variable
|
730
|
-
end
|
731
|
-
|
732
|
-
unless rhs_variable == rhs_object
|
733
|
-
notify_implicit_conv_performed(node.rhs_operand,
|
734
|
-
rhs_object, rhs_variable)
|
735
|
-
end
|
736
|
-
|
737
|
-
lhs_converted, rhs_converted =
|
738
|
-
do_usual_arithmetic_conversion(lhs_variable, rhs_variable)
|
739
|
-
|
740
|
-
unless lhs_variable == lhs_converted
|
741
|
-
notify_implicit_conv_performed(node.lhs_operand,
|
742
|
-
lhs_variable, lhs_converted)
|
743
|
-
end
|
744
|
-
|
745
|
-
unless rhs_variable == rhs_converted
|
746
|
-
notify_implicit_conv_performed(node.rhs_operand,
|
747
|
-
rhs_variable, rhs_converted)
|
748
|
-
end
|
749
|
-
|
750
|
-
# NOTE: Domain of the arithmetic result value will be restricted by
|
751
|
-
# min-max of the variable type.
|
752
|
-
result = temporary_variable(lhs_converted.type,
|
753
|
-
lhs_converted.value & rhs_converted.value)
|
754
|
-
_notify_variable_value_referred(node, lhs_variable)
|
755
|
-
_notify_variable_value_referred(node, rhs_variable)
|
756
|
-
|
757
|
-
notify_and_expr_evaled(node, lhs_variable, rhs_variable, result)
|
758
|
-
|
759
|
-
result
|
102
|
+
def visit_function_call_expression(node)
|
103
|
+
checkpoint(node.location)
|
104
|
+
args = node.argument_expressions.map { |expr| [expr.accept(self), expr] }
|
105
|
+
eval_function_call_expr(node, node.expression.accept(self), args)
|
760
106
|
end
|
761
107
|
|
762
|
-
def
|
763
|
-
|
764
|
-
|
765
|
-
# NOTE: To detect bad value reference of `void' expressions.
|
766
|
-
return temporary_variable
|
767
|
-
end
|
768
|
-
|
769
|
-
unless lhs_variable == lhs_object
|
770
|
-
notify_implicit_conv_performed(node.lhs_operand,
|
771
|
-
lhs_object, lhs_variable)
|
772
|
-
end
|
773
|
-
|
774
|
-
rhs_variable = object_to_variable(rhs_object)
|
775
|
-
unless rhs_variable.type.scalar? || rhs_variable.type.void?
|
776
|
-
# NOTE: To detect bad value reference of `void' expressions.
|
777
|
-
return temporary_variable
|
778
|
-
end
|
779
|
-
|
780
|
-
unless rhs_variable == rhs_object
|
781
|
-
notify_implicit_conv_performed(node.rhs_operand,
|
782
|
-
rhs_object, rhs_variable)
|
783
|
-
end
|
784
|
-
|
785
|
-
lhs_converted, rhs_converted =
|
786
|
-
do_usual_arithmetic_conversion(lhs_variable, rhs_variable)
|
787
|
-
|
788
|
-
unless lhs_variable == lhs_converted
|
789
|
-
notify_implicit_conv_performed(node.lhs_operand,
|
790
|
-
lhs_variable, lhs_converted)
|
791
|
-
end
|
792
|
-
|
793
|
-
unless rhs_variable == rhs_converted
|
794
|
-
notify_implicit_conv_performed(node.rhs_operand,
|
795
|
-
rhs_variable, rhs_converted)
|
796
|
-
end
|
797
|
-
|
798
|
-
# NOTE: Domain of the arithmetic result value will be restricted by
|
799
|
-
# min-max of the variable type.
|
800
|
-
result = temporary_variable(lhs_converted.type,
|
801
|
-
lhs_converted.value ^ rhs_converted.value)
|
802
|
-
_notify_variable_value_referred(node, lhs_variable)
|
803
|
-
_notify_variable_value_referred(node, rhs_variable)
|
804
|
-
|
805
|
-
notify_exclusive_or_expr_evaled(node, lhs_variable, rhs_variable, result)
|
806
|
-
|
807
|
-
result
|
108
|
+
def visit_member_access_by_value_expression(node)
|
109
|
+
checkpoint(node.location)
|
110
|
+
eval_member_access_by_value_expr(node, node.expression.accept(self))
|
808
111
|
end
|
809
112
|
|
810
|
-
def
|
811
|
-
|
812
|
-
|
813
|
-
# NOTE: To detect bad value reference of `void' expressions.
|
814
|
-
return temporary_variable
|
815
|
-
end
|
816
|
-
|
817
|
-
unless lhs_variable == lhs_object
|
818
|
-
notify_implicit_conv_performed(node.lhs_operand,
|
819
|
-
lhs_object, lhs_variable)
|
820
|
-
end
|
821
|
-
|
822
|
-
rhs_variable = object_to_variable(rhs_object)
|
823
|
-
unless rhs_variable.type.scalar? || rhs_variable.type.void?
|
824
|
-
# NOTE: To detect bad value reference of `void' expressions.
|
825
|
-
return temporary_variable
|
826
|
-
end
|
827
|
-
|
828
|
-
unless rhs_variable == rhs_object
|
829
|
-
notify_implicit_conv_performed(node.rhs_operand,
|
830
|
-
rhs_object, rhs_variable)
|
831
|
-
end
|
832
|
-
|
833
|
-
lhs_converted, rhs_converted =
|
834
|
-
do_usual_arithmetic_conversion(lhs_variable, rhs_variable)
|
835
|
-
|
836
|
-
unless lhs_variable == lhs_converted
|
837
|
-
notify_implicit_conv_performed(node.lhs_operand,
|
838
|
-
lhs_variable, lhs_converted)
|
839
|
-
end
|
840
|
-
|
841
|
-
unless rhs_variable == rhs_converted
|
842
|
-
notify_implicit_conv_performed(node.rhs_operand,
|
843
|
-
rhs_variable, rhs_converted)
|
844
|
-
end
|
845
|
-
|
846
|
-
# NOTE: Domain of the arithmetic result value will be restricted by
|
847
|
-
# min-max of the variable type.
|
848
|
-
result = temporary_variable(lhs_converted.type,
|
849
|
-
lhs_converted.value | rhs_converted.value)
|
850
|
-
_notify_variable_value_referred(node, lhs_variable)
|
851
|
-
_notify_variable_value_referred(node, rhs_variable)
|
852
|
-
|
853
|
-
notify_inclusive_or_expr_evaled(node, lhs_variable, rhs_variable, result)
|
854
|
-
|
855
|
-
result
|
113
|
+
def visit_member_access_by_pointer_expression(node)
|
114
|
+
checkpoint(node.location)
|
115
|
+
eval_member_access_by_pointer_expr(node,node.expression.accept(self))
|
856
116
|
end
|
857
117
|
|
858
|
-
def
|
859
|
-
|
860
|
-
|
861
|
-
|
862
|
-
rhs_variable = object_to_variable(rhs_object)
|
863
|
-
unless rhs_variable == rhs_object
|
864
|
-
notify_implicit_conv_performed(node.rhs_operand,
|
865
|
-
rhs_object, rhs_variable)
|
866
|
-
end
|
867
|
-
|
868
|
-
if rhs_variable.type.same_as?(lhs_variable.type)
|
869
|
-
rhs_converted = rhs_variable
|
870
|
-
else
|
871
|
-
rhs_converted =
|
872
|
-
do_conversion(rhs_variable, lhs_variable.type) ||
|
873
|
-
temporary_variable(lhs_variable.type)
|
874
|
-
notify_implicit_conv_performed(node.rhs_operand,
|
875
|
-
rhs_variable, rhs_converted)
|
876
|
-
end
|
877
|
-
|
878
|
-
# NOTE: Domain of the arithmetic result value will be restricted by
|
879
|
-
# min-max of the variable type.
|
880
|
-
# NOTE: Even if rhs_object is a NamedVariable, new value will be
|
881
|
-
# instantiated in value-coercing.
|
882
|
-
# So, value-aliasing never occurs.
|
883
|
-
lhs_variable.assign!(rhs_converted.value.to_defined_value)
|
884
|
-
_notify_variable_value_referred(node, rhs_variable)
|
885
|
-
_notify_variable_value_updated(node, lhs_variable)
|
886
|
-
|
887
|
-
notify_assignment_expr_evaled(node, lhs_variable, rhs_variable)
|
888
|
-
|
889
|
-
lhs_variable
|
118
|
+
def visit_bit_access_by_value_expression(node)
|
119
|
+
checkpoint(node.location)
|
120
|
+
# TODO: Should support the GCC extension.
|
121
|
+
create_tempvar
|
890
122
|
end
|
891
123
|
|
892
|
-
def
|
893
|
-
|
894
|
-
|
895
|
-
|
896
|
-
lhs_variable = lhs_object
|
897
|
-
|
898
|
-
rhs_variable = object_to_variable(rhs_object)
|
899
|
-
unless rhs_variable.type.scalar? || rhs_variable.type.void?
|
900
|
-
# NOTE: To detect bad value reference of `void' expressions.
|
901
|
-
return temporary_variable
|
902
|
-
end
|
903
|
-
|
904
|
-
unless rhs_variable == rhs_object
|
905
|
-
notify_implicit_conv_performed(node.rhs_operand,
|
906
|
-
rhs_object, rhs_variable)
|
907
|
-
end
|
908
|
-
|
909
|
-
case node.operator.type
|
910
|
-
when "*="
|
911
|
-
execute_mul_then_assign_expression(node, lhs_variable, rhs_variable)
|
912
|
-
when "/="
|
913
|
-
execute_div_then_assign_expression(node, lhs_variable, rhs_variable)
|
914
|
-
when "%="
|
915
|
-
execute_mod_then_assign_expression(node, lhs_variable, rhs_variable)
|
916
|
-
when "+="
|
917
|
-
execute_add_then_assign_expression(node, lhs_variable, rhs_variable)
|
918
|
-
when "-="
|
919
|
-
execute_sub_then_assign_expression(node, lhs_variable, rhs_variable)
|
920
|
-
when "<<="
|
921
|
-
execute_shl_then_assign_expression(node, lhs_variable, rhs_variable)
|
922
|
-
when ">>="
|
923
|
-
execute_shr_then_assign_expression(node, lhs_variable, rhs_variable)
|
924
|
-
when "&="
|
925
|
-
execute_and_then_assign_expression(node, lhs_variable, rhs_variable)
|
926
|
-
when "^="
|
927
|
-
execute_xor_then_assign_expression(node, lhs_variable, rhs_variable)
|
928
|
-
when "|="
|
929
|
-
execute_ior_then_assign_expression(node, lhs_variable, rhs_variable)
|
930
|
-
end
|
931
|
-
|
932
|
-
lhs_variable
|
124
|
+
def visit_bit_access_by_pointer_expression(node)
|
125
|
+
checkpoint(node.location)
|
126
|
+
# TODO: Should support the GCC extension.
|
127
|
+
create_tempvar
|
933
128
|
end
|
934
129
|
|
935
|
-
def
|
936
|
-
|
937
|
-
|
938
|
-
|
939
|
-
unless lhs_variable == lhs_converted
|
940
|
-
notify_implicit_conv_performed(node.lhs_operand,
|
941
|
-
lhs_variable, lhs_converted)
|
942
|
-
end
|
943
|
-
|
944
|
-
unless rhs_variable == rhs_converted
|
945
|
-
notify_implicit_conv_performed(node.rhs_operand,
|
946
|
-
rhs_variable, rhs_converted)
|
947
|
-
end
|
948
|
-
|
949
|
-
if lhs_converted.value.scalar? && rhs_converted.value.scalar?
|
950
|
-
result_value = lhs_converted.value * rhs_converted.value
|
951
|
-
else
|
952
|
-
result_value = lhs_converted.value
|
953
|
-
end
|
954
|
-
|
955
|
-
# NOTE: Value of the lhs_variable is referred at this point. But value
|
956
|
-
# reference should not be notified not to confuse sequence-point
|
957
|
-
# warning detections.
|
958
|
-
# _notify_variable_value_referred(node, lhs_variable)
|
959
|
-
|
960
|
-
_notify_variable_value_referred(node, rhs_variable)
|
961
|
-
|
962
|
-
result_variable = temporary_variable(lhs_converted.type, result_value)
|
963
|
-
|
964
|
-
notify_multiplicative_expr_evaled(node, lhs_variable, rhs_variable,
|
965
|
-
result_variable)
|
966
|
-
|
967
|
-
if result_variable.type.same_as?(lhs_variable.type)
|
968
|
-
result_converted = result_variable
|
969
|
-
else
|
970
|
-
result_converted =
|
971
|
-
do_conversion(result_variable, lhs_variable.type) ||
|
972
|
-
temporary_variable(lhs_variable.type)
|
973
|
-
notify_implicit_conv_performed(node.lhs_operand,
|
974
|
-
result_variable, result_converted)
|
975
|
-
end
|
976
|
-
|
977
|
-
# NOTE: Domain of the arithmetic result value will be restricted by
|
978
|
-
# min-max of the variable type.
|
979
|
-
lhs_variable.assign!(result_converted.value)
|
980
|
-
_notify_variable_value_updated(node, lhs_variable)
|
981
|
-
|
982
|
-
notify_assignment_expr_evaled(node, lhs_variable, result_converted)
|
130
|
+
def visit_postfix_increment_expression(node)
|
131
|
+
checkpoint(node.location)
|
132
|
+
eval_postfix_increment_expr(node, node.operand.accept(self))
|
983
133
|
end
|
984
134
|
|
985
|
-
def
|
986
|
-
|
987
|
-
|
988
|
-
|
989
|
-
unless lhs_variable == lhs_converted
|
990
|
-
notify_implicit_conv_performed(node.lhs_operand,
|
991
|
-
lhs_variable, lhs_converted)
|
992
|
-
end
|
993
|
-
|
994
|
-
unless rhs_variable == rhs_converted
|
995
|
-
notify_implicit_conv_performed(node.rhs_operand,
|
996
|
-
rhs_variable, rhs_converted)
|
997
|
-
end
|
998
|
-
|
999
|
-
if lhs_converted.value.scalar? && rhs_converted.value.scalar?
|
1000
|
-
# NOTE: "Div by 0" semantics is implemented in value-value arithmetic.
|
1001
|
-
result_value = lhs_converted.value / rhs_converted.value
|
1002
|
-
else
|
1003
|
-
result_value = lhs_converted.value
|
1004
|
-
end
|
1005
|
-
|
1006
|
-
# NOTE: Value of the lhs_variable is referred at this point. But value
|
1007
|
-
# reference should not be notified not to confuse sequence-point
|
1008
|
-
# warning detections.
|
1009
|
-
# _notify_variable_value_referred(node, lhs_variable)
|
1010
|
-
|
1011
|
-
_notify_variable_value_referred(node, rhs_variable)
|
1012
|
-
|
1013
|
-
result_variable = temporary_variable(lhs_converted.type, result_value)
|
1014
|
-
|
1015
|
-
notify_multiplicative_expr_evaled(node, lhs_variable, rhs_variable,
|
1016
|
-
result_variable)
|
1017
|
-
|
1018
|
-
if result_variable.type.same_as?(lhs_variable.type)
|
1019
|
-
result_converted = result_variable
|
1020
|
-
else
|
1021
|
-
result_converted =
|
1022
|
-
do_conversion(result_variable, lhs_variable.type) ||
|
1023
|
-
temporary_variable(lhs_variable.type)
|
1024
|
-
notify_implicit_conv_performed(node.lhs_operand,
|
1025
|
-
result_variable, result_converted)
|
1026
|
-
end
|
1027
|
-
|
1028
|
-
# NOTE: Domain of the arithmetic result value will be restricted by
|
1029
|
-
# min-max of the variable type.
|
1030
|
-
lhs_variable.assign!(result_converted.value)
|
1031
|
-
_notify_variable_value_updated(node, lhs_variable)
|
1032
|
-
|
1033
|
-
notify_assignment_expr_evaled(node, lhs_variable, result_converted)
|
135
|
+
def visit_postfix_decrement_expression(node)
|
136
|
+
checkpoint(node.location)
|
137
|
+
eval_postfix_decrement_expr(node, node.operand.accept(self))
|
1034
138
|
end
|
1035
139
|
|
1036
|
-
def
|
1037
|
-
|
1038
|
-
|
1039
|
-
|
1040
|
-
|
1041
|
-
notify_implicit_conv_performed(node.lhs_operand,
|
1042
|
-
lhs_variable, lhs_converted)
|
1043
|
-
end
|
1044
|
-
|
1045
|
-
unless rhs_variable == rhs_converted
|
1046
|
-
notify_implicit_conv_performed(node.rhs_operand,
|
1047
|
-
rhs_variable, rhs_converted)
|
1048
|
-
end
|
1049
|
-
|
1050
|
-
if lhs_converted.value.scalar? && rhs_converted.value.scalar?
|
1051
|
-
# NOTE: "Div by 0" semantics is implemented in value-value arithmetic.
|
1052
|
-
result_value = lhs_converted.value % rhs_converted.value
|
1053
|
-
else
|
1054
|
-
result_value = lhs_converted.value
|
1055
|
-
end
|
1056
|
-
|
1057
|
-
# NOTE: Value of the lhs_variable is referred at this point. But value
|
1058
|
-
# reference should not be notified not to confuse sequence-point
|
1059
|
-
# warning detections.
|
1060
|
-
# _notify_variable_value_referred(node, lhs_variable)
|
1061
|
-
|
1062
|
-
_notify_variable_value_referred(node, rhs_variable)
|
140
|
+
def visit_compound_literal_expression(node)
|
141
|
+
checkpoint(node.location)
|
142
|
+
# TODO: Should support C99 features.
|
143
|
+
create_tempvar(node.type_name.type)
|
144
|
+
end
|
1063
145
|
|
1064
|
-
|
146
|
+
def visit_prefix_increment_expression(node)
|
147
|
+
checkpoint(node.location)
|
148
|
+
eval_prefix_increment_expr(node, node.operand.accept(self))
|
149
|
+
end
|
1065
150
|
|
1066
|
-
|
1067
|
-
|
151
|
+
def visit_prefix_decrement_expression(node)
|
152
|
+
checkpoint(node.location)
|
153
|
+
eval_prefix_decrement_expr(node, node.operand.accept(self))
|
154
|
+
end
|
1068
155
|
|
1069
|
-
|
1070
|
-
|
1071
|
-
|
1072
|
-
|
1073
|
-
do_conversion(result_variable, lhs_variable.type) ||
|
1074
|
-
temporary_variable(lhs_variable.type)
|
1075
|
-
notify_implicit_conv_performed(node.lhs_operand,
|
1076
|
-
result_variable, result_converted)
|
1077
|
-
end
|
156
|
+
def visit_address_expression(node)
|
157
|
+
checkpoint(node.location)
|
158
|
+
eval_address_expr(node, node.operand.accept(self))
|
159
|
+
end
|
1078
160
|
|
1079
|
-
|
1080
|
-
|
1081
|
-
|
1082
|
-
|
161
|
+
def visit_indirection_expression(node)
|
162
|
+
checkpoint(node.location)
|
163
|
+
eval_indirection_expr(node, node.operand.accept(self))
|
164
|
+
end
|
1083
165
|
|
1084
|
-
|
166
|
+
def visit_unary_arithmetic_expression(node)
|
167
|
+
checkpoint(node.location)
|
168
|
+
eval_unary_arithmetic_expr(node, node.operand.accept(self))
|
1085
169
|
end
|
1086
170
|
|
1087
|
-
def
|
1088
|
-
|
1089
|
-
do_usual_arithmetic_conversion(lhs_variable, rhs_variable)
|
171
|
+
def visit_sizeof_expression(node)
|
172
|
+
checkpoint(node.location)
|
1090
173
|
|
1091
|
-
|
1092
|
-
|
1093
|
-
|
174
|
+
operand_obj = result_var = nil
|
175
|
+
eval_without_side_effect do
|
176
|
+
result_type = type_of(UserTypeId.new("size_t")) || unsigned_long_type
|
177
|
+
operand_obj = node.operand.accept(self)
|
178
|
+
if operand_obj.variable?
|
179
|
+
size = operand_obj.type.aligned_byte_size
|
180
|
+
result_var = create_tempvar(result_type, ScalarValue.of(size))
|
181
|
+
else
|
182
|
+
return create_tempvar(result_type)
|
183
|
+
end
|
1094
184
|
end
|
1095
185
|
|
1096
|
-
|
1097
|
-
|
1098
|
-
|
1099
|
-
end
|
186
|
+
notify_sizeof_expr_evaled(node, operand_obj, result_var)
|
187
|
+
result_var
|
188
|
+
end
|
1100
189
|
|
1101
|
-
|
1102
|
-
|
1103
|
-
|
1104
|
-
|
190
|
+
def visit_sizeof_type_expression(node)
|
191
|
+
checkpoint(node.location)
|
192
|
+
resolve_unresolved_type(node.operand)
|
193
|
+
|
194
|
+
result_var = nil
|
195
|
+
eval_without_side_effect do
|
196
|
+
result_type = type_of(UserTypeId.new("size_t")) || unsigned_long_type
|
197
|
+
size = node.operand.type.aligned_byte_size
|
198
|
+
result_var = create_tempvar(result_type, ScalarValue.of(size))
|
1105
199
|
end
|
1106
200
|
|
1107
|
-
|
1108
|
-
|
1109
|
-
|
1110
|
-
# _notify_variable_value_referred(node, lhs_variable)
|
201
|
+
notify_sizeof_type_expr_evaled(node, node.operand.type, result_var)
|
202
|
+
result_var
|
203
|
+
end
|
1111
204
|
|
1112
|
-
|
205
|
+
def visit_alignof_expression(node)
|
206
|
+
checkpoint(node.location)
|
1113
207
|
|
1114
|
-
|
208
|
+
eval_without_side_effect do
|
209
|
+
result_type = type_of(UserTypeId.new("size_t")) || unsigned_long_type
|
210
|
+
operand_obj = node.operand.accept(self)
|
211
|
+
if operand_obj.variable?
|
212
|
+
align = operand_obj.type.byte_alignment
|
213
|
+
create_tempvar(result_type, ScalarValue.of(align))
|
214
|
+
else
|
215
|
+
create_tempvar(result_type)
|
216
|
+
end
|
217
|
+
end
|
218
|
+
end
|
1115
219
|
|
1116
|
-
|
1117
|
-
|
220
|
+
def visit_alignof_type_expression(node)
|
221
|
+
checkpoint(node.location)
|
222
|
+
resolve_unresolved_type(node.operand)
|
1118
223
|
|
1119
|
-
|
1120
|
-
|
1121
|
-
|
1122
|
-
|
1123
|
-
do_conversion(result_variable, lhs_variable.type) ||
|
1124
|
-
temporary_variable(lhs_variable.type)
|
1125
|
-
notify_implicit_conv_performed(node.lhs_operand,
|
1126
|
-
result_variable, result_converted)
|
224
|
+
eval_without_side_effect do
|
225
|
+
result_type = type_of(UserTypeId.new("size_t")) || unsigned_long_type
|
226
|
+
align = node.operand.type.aligned_byte_size
|
227
|
+
create_tempvar(result_type, ScalarValue.of(align))
|
1127
228
|
end
|
229
|
+
end
|
1128
230
|
|
1129
|
-
|
1130
|
-
|
1131
|
-
|
1132
|
-
|
231
|
+
def visit_cast_expression(node)
|
232
|
+
checkpoint(node.location)
|
233
|
+
eval_cast_expr(node, node.operand.accept(self))
|
234
|
+
end
|
1133
235
|
|
1134
|
-
|
236
|
+
def visit_multiplicative_expression(node)
|
237
|
+
checkpoint(node.location)
|
238
|
+
eval_multiplicative_expr(node, node.lhs_operand.accept(self),
|
239
|
+
node.rhs_operand.accept(self))
|
1135
240
|
end
|
1136
241
|
|
1137
|
-
def
|
1138
|
-
|
1139
|
-
|
242
|
+
def visit_additive_expression(node)
|
243
|
+
checkpoint(node.location)
|
244
|
+
eval_additive_expr(node, node.lhs_operand.accept(self),
|
245
|
+
node.rhs_operand.accept(self))
|
246
|
+
end
|
1140
247
|
|
1141
|
-
|
1142
|
-
|
1143
|
-
|
1144
|
-
|
248
|
+
def visit_shift_expression(node)
|
249
|
+
checkpoint(node.location)
|
250
|
+
eval_shift_expr(node, node.lhs_operand.accept(self),
|
251
|
+
node.rhs_operand.accept(self))
|
252
|
+
end
|
1145
253
|
|
1146
|
-
|
1147
|
-
|
1148
|
-
|
1149
|
-
|
254
|
+
def visit_relational_expression(node)
|
255
|
+
checkpoint(node.location)
|
256
|
+
eval_relational_expr(node, node.lhs_operand.accept(self),
|
257
|
+
node.rhs_operand.accept(self))
|
258
|
+
end
|
1150
259
|
|
1151
|
-
|
1152
|
-
|
1153
|
-
|
1154
|
-
|
1155
|
-
|
260
|
+
def visit_equality_expression(node)
|
261
|
+
checkpoint(node.location)
|
262
|
+
eval_equality_expr(node, node.lhs_operand.accept(self),
|
263
|
+
node.rhs_operand.accept(self))
|
264
|
+
end
|
1156
265
|
|
1157
|
-
|
1158
|
-
|
1159
|
-
|
1160
|
-
|
266
|
+
def visit_and_expression(node)
|
267
|
+
checkpoint(node.location)
|
268
|
+
eval_and_expr(node, node.lhs_operand.accept(self),
|
269
|
+
node.rhs_operand.accept(self))
|
270
|
+
end
|
1161
271
|
|
1162
|
-
|
272
|
+
def visit_exclusive_or_expression(node)
|
273
|
+
checkpoint(node.location)
|
274
|
+
eval_exclusive_or_expr(node, node.lhs_operand.accept(self),
|
275
|
+
node.rhs_operand.accept(self))
|
276
|
+
end
|
1163
277
|
|
1164
|
-
|
278
|
+
def visit_inclusive_or_expression(node)
|
279
|
+
checkpoint(node.location)
|
280
|
+
eval_inclusive_or_expr(node, node.lhs_operand.accept(self),
|
281
|
+
node.rhs_operand.accept(self))
|
282
|
+
end
|
1165
283
|
|
1166
|
-
|
1167
|
-
|
284
|
+
def visit_logical_and_expression(node)
|
285
|
+
checkpoint(node.location)
|
1168
286
|
|
1169
|
-
|
1170
|
-
|
287
|
+
lhs_obj = node.lhs_operand.accept(self)
|
288
|
+
if lhs_obj.variable?
|
289
|
+
lhs_var = lhs_obj
|
1171
290
|
else
|
1172
|
-
|
1173
|
-
do_conversion(result_variable, lhs_variable.type) ||
|
1174
|
-
temporary_variable(lhs_variable.type)
|
1175
|
-
notify_implicit_conv_performed(node.lhs_operand,
|
1176
|
-
result_variable, result_converted)
|
291
|
+
return create_tempvar(int_type)
|
1177
292
|
end
|
1178
293
|
|
1179
|
-
# NOTE:
|
1180
|
-
#
|
1181
|
-
|
1182
|
-
_notify_variable_value_updated(node, lhs_variable)
|
1183
|
-
|
1184
|
-
notify_assignment_expr_evaled(node, lhs_variable, result_converted)
|
1185
|
-
end
|
1186
|
-
|
1187
|
-
def execute_shl_then_assign_expression(node, lhs_variable, rhs_variable)
|
1188
|
-
# NOTE: The ISO C99 standard saids;
|
294
|
+
# NOTE: The ISO C99 standard says;
|
295
|
+
#
|
296
|
+
# 6.5.13 Logical AND operator
|
1189
297
|
#
|
1190
|
-
#
|
298
|
+
# Semantics
|
1191
299
|
#
|
1192
|
-
#
|
1193
|
-
#
|
1194
|
-
#
|
1195
|
-
#
|
1196
|
-
|
1197
|
-
|
1198
|
-
unless lhs_variable == lhs_converted
|
1199
|
-
notify_implicit_conv_performed(node.lhs_operand,
|
1200
|
-
lhs_variable, lhs_converted)
|
1201
|
-
end
|
300
|
+
# 4 Unlike the bitwise binary & operator, the && operator guarantees
|
301
|
+
# left-to-right evaluation; there is a sequence point after the
|
302
|
+
# evaluation of the first operand. If the first operand compares equal
|
303
|
+
# to 0, the second operand is not evaluated.
|
304
|
+
notify_sequence_point_reached(SequencePoint.new(node.lhs_operand))
|
305
|
+
lhs_val = lhs_var.value
|
1202
306
|
|
1203
|
-
|
1204
|
-
|
1205
|
-
|
1206
|
-
|
307
|
+
if lhs_val.scalar? && lhs_val.must_be_false?
|
308
|
+
# NOTE: Doing the short-circuit evaluation.
|
309
|
+
notify_variable_value_referred(node, lhs_var)
|
310
|
+
return create_tempvar(int_type, ScalarValue.of_false)
|
1207
311
|
end
|
1208
312
|
|
1209
|
-
|
1210
|
-
|
313
|
+
rhs_obj = node.rhs_operand.accept(self)
|
314
|
+
if rhs_obj.variable?
|
315
|
+
rhs_var = rhs_obj
|
1211
316
|
else
|
1212
|
-
|
317
|
+
return create_tempvar(int_type)
|
1213
318
|
end
|
1214
319
|
|
1215
|
-
|
1216
|
-
|
1217
|
-
# warning detections.
|
1218
|
-
# _notify_variable_value_referred(node, lhs_variable)
|
320
|
+
notify_sequence_point_reached(SequencePoint.new(node.rhs_operand))
|
321
|
+
rhs_val = rhs_var.value
|
1219
322
|
|
1220
|
-
|
323
|
+
if lhs_val.scalar? && rhs_val.scalar?
|
324
|
+
# NOTE: No usual-arithmetic-conversion.
|
325
|
+
result_var = create_tempvar(int_type, lhs_val.logical_and(rhs_val))
|
326
|
+
else
|
327
|
+
result_var = create_tempvar(int_type)
|
328
|
+
end
|
329
|
+
notify_variable_value_referred(node, lhs_var)
|
330
|
+
notify_variable_value_referred(node, rhs_var)
|
1221
331
|
|
1222
|
-
|
332
|
+
notify_logical_and_expr_evaled(node, lhs_var, rhs_var, result_var)
|
333
|
+
result_var
|
334
|
+
end
|
1223
335
|
|
1224
|
-
|
1225
|
-
|
336
|
+
def visit_logical_or_expression(node)
|
337
|
+
checkpoint(node.location)
|
1226
338
|
|
1227
|
-
|
1228
|
-
|
339
|
+
lhs_obj = node.lhs_operand.accept(self)
|
340
|
+
if lhs_obj.variable?
|
341
|
+
lhs_var = lhs_obj
|
1229
342
|
else
|
1230
|
-
|
1231
|
-
do_conversion(result_variable, lhs_variable.type) ||
|
1232
|
-
temporary_variable(lhs_variable.type)
|
1233
|
-
notify_implicit_conv_performed(node.lhs_operand,
|
1234
|
-
result_variable, result_converted)
|
343
|
+
return create_tempvar(int_type)
|
1235
344
|
end
|
1236
345
|
|
1237
|
-
# NOTE:
|
1238
|
-
#
|
1239
|
-
|
1240
|
-
_notify_variable_value_updated(node, lhs_variable)
|
1241
|
-
|
1242
|
-
notify_assignment_expr_evaled(node, lhs_variable, result_converted)
|
1243
|
-
end
|
1244
|
-
|
1245
|
-
def execute_shr_then_assign_expression(node, lhs_variable, rhs_variable)
|
1246
|
-
# NOTE: The ISO C99 standard saids;
|
346
|
+
# NOTE: The ISO C99 standard says;
|
347
|
+
#
|
348
|
+
# 6.5.14 Logical OR operator
|
1247
349
|
#
|
1248
|
-
#
|
350
|
+
# Semantics
|
1249
351
|
#
|
1250
|
-
#
|
1251
|
-
#
|
1252
|
-
#
|
1253
|
-
#
|
1254
|
-
|
1255
|
-
|
1256
|
-
unless lhs_variable == lhs_converted
|
1257
|
-
notify_implicit_conv_performed(node.lhs_operand,
|
1258
|
-
lhs_variable, lhs_converted)
|
1259
|
-
end
|
352
|
+
# 4 Unlike the bitwise | operator, the || operator guarantees
|
353
|
+
# left-to-right evaluation; there is a sequence point after the
|
354
|
+
# evaluation of the first operand. If the first operand compares
|
355
|
+
# unequal to 0, the second operand is not evaluated.
|
356
|
+
notify_sequence_point_reached(SequencePoint.new(node.lhs_operand))
|
357
|
+
lhs_val = lhs_var.value
|
1260
358
|
|
1261
|
-
|
1262
|
-
|
1263
|
-
|
1264
|
-
|
359
|
+
if lhs_val.scalar? && lhs_val.must_be_true?
|
360
|
+
# NOTE: Doing the short-circuit evaluation.
|
361
|
+
notify_variable_value_referred(node, lhs_var)
|
362
|
+
return create_tempvar(int_type, ScalarValue.of_true)
|
1265
363
|
end
|
1266
364
|
|
1267
|
-
|
1268
|
-
|
365
|
+
rhs_obj = node.rhs_operand.accept(self)
|
366
|
+
if rhs_obj.variable?
|
367
|
+
rhs_var = rhs_obj
|
1269
368
|
else
|
1270
|
-
|
369
|
+
return create_tempvar(int_type)
|
1271
370
|
end
|
1272
371
|
|
1273
|
-
|
1274
|
-
|
1275
|
-
# warning detections.
|
1276
|
-
# _notify_variable_value_referred(node, lhs_variable)
|
1277
|
-
|
1278
|
-
_notify_variable_value_referred(node, rhs_variable)
|
1279
|
-
|
1280
|
-
result_variable = temporary_variable(lhs_converted.type, result_value)
|
1281
|
-
|
1282
|
-
notify_shift_expr_evaled(node, lhs_variable, rhs_variable,
|
1283
|
-
result_variable)
|
372
|
+
notify_sequence_point_reached(SequencePoint.new(node.rhs_operand))
|
373
|
+
rhs_val = rhs_var.value
|
1284
374
|
|
1285
|
-
if
|
1286
|
-
|
375
|
+
if lhs_val.scalar? && rhs_val.scalar?
|
376
|
+
# NOTE: No usual-arithmetic-conversion.
|
377
|
+
result_var = create_tempvar(int_type, lhs_val.logical_or(rhs_val))
|
1287
378
|
else
|
1288
|
-
|
1289
|
-
do_conversion(result_variable, lhs_variable.type) ||
|
1290
|
-
temporary_variable(lhs_variable.type)
|
1291
|
-
notify_implicit_conv_performed(node.lhs_operand,
|
1292
|
-
result_variable, result_converted)
|
379
|
+
result_var = create_tempvar(int_type)
|
1293
380
|
end
|
381
|
+
notify_variable_value_referred(node, lhs_var)
|
382
|
+
notify_variable_value_referred(node, rhs_var)
|
1294
383
|
|
1295
|
-
|
1296
|
-
|
1297
|
-
|
1298
|
-
_notify_variable_value_updated(node, lhs_variable)
|
384
|
+
notify_logical_or_expr_evaled(node, lhs_var, rhs_var, result_var)
|
385
|
+
result_var
|
386
|
+
end
|
1299
387
|
|
1300
|
-
|
388
|
+
def visit_simple_assignment_expression(node)
|
389
|
+
checkpoint(node.location)
|
390
|
+
eval_simple_assignment_expr(node, node.lhs_operand.accept(self),
|
391
|
+
node.rhs_operand.accept(self))
|
1301
392
|
end
|
1302
393
|
|
1303
|
-
def
|
1304
|
-
|
1305
|
-
|
394
|
+
def visit_compound_assignment_expression(node)
|
395
|
+
checkpoint(node.location)
|
396
|
+
eval_compound_assignment_expr(node, node.lhs_operand.accept(self),
|
397
|
+
node.rhs_operand.accept(self))
|
398
|
+
end
|
1306
399
|
|
1307
|
-
|
1308
|
-
|
1309
|
-
|
1310
|
-
|
400
|
+
def visit_comma_separated_expression(node)
|
401
|
+
checkpoint(node.location)
|
402
|
+
node.expressions.map { |expr| expr.accept(self) }.last
|
403
|
+
end
|
1311
404
|
|
1312
|
-
|
1313
|
-
|
1314
|
-
|
405
|
+
private
|
406
|
+
def eval_without_side_effect(&block)
|
407
|
+
originally_quiet = interpreter.quiet_without_side_effect?
|
408
|
+
unless originally_quiet
|
409
|
+
interpreter._quiet_without_side_effect = true
|
1315
410
|
end
|
1316
|
-
|
1317
|
-
|
1318
|
-
|
1319
|
-
|
1320
|
-
|
411
|
+
yield
|
412
|
+
ensure
|
413
|
+
unless originally_quiet
|
414
|
+
interpreter._quiet_without_side_effect = false
|
415
|
+
# FIXME: Evaluation of an object-specifier doesn't refer to value
|
416
|
+
# of a variable. Thus, no cross-reference record on a
|
417
|
+
# sizeof-expression because cross-reference extraction
|
418
|
+
# watches variable value reference not variable reference.
|
419
|
+
# collect_object_specifiers(node).each { |os| os.accept(self) }
|
1321
420
|
end
|
421
|
+
end
|
422
|
+
|
423
|
+
def create_array_value_of_string(str)
|
424
|
+
ArrayValue.new(str.chars.map { |ch| ScalarValue.of(ch.ord) } +
|
425
|
+
[ScalarValue.of("\0".ord)])
|
426
|
+
end
|
1322
427
|
|
1323
|
-
|
1324
|
-
#
|
1325
|
-
#
|
1326
|
-
# _notify_variable_value_referred(node, lhs_variable)
|
428
|
+
module Impl
|
429
|
+
# NOTE: Host class of this module must include InterpreterMediator,
|
430
|
+
# NotifierMediator and Conversion.
|
1327
431
|
|
1328
|
-
|
432
|
+
def eval_object_specifier(node)
|
433
|
+
if var = variable_named(node.identifier.value)
|
434
|
+
var.declarations_and_definitions.each do |dcl_or_def|
|
435
|
+
dcl_or_def.mark_as_referred_by(node.identifier)
|
436
|
+
end
|
437
|
+
_notify_object_referred(node, var)
|
438
|
+
# NOTE: Array object will be converted into its start address by the
|
439
|
+
# outer expression. So, it is correct to return an array
|
440
|
+
# object itself.
|
441
|
+
return var
|
442
|
+
end
|
1329
443
|
|
1330
|
-
|
444
|
+
if func = function_named(node.identifier.value)
|
445
|
+
func.declarations_and_definitions.each do |dcl_or_def|
|
446
|
+
dcl_or_def.mark_as_referred_by(node.identifier)
|
447
|
+
end
|
448
|
+
_notify_object_referred(node, func)
|
449
|
+
return func
|
450
|
+
end
|
1331
451
|
|
1332
|
-
|
452
|
+
if enum = enumerator_named(node.identifier.value)
|
453
|
+
enum.mark_as_referred_by(node.identifier)
|
454
|
+
return create_tempvar(enum.type, ScalarValue.of(enum.value))
|
455
|
+
end
|
1333
456
|
|
1334
|
-
|
1335
|
-
result_converted = result_variable
|
1336
|
-
else
|
1337
|
-
result_converted =
|
1338
|
-
do_conversion(result_variable, lhs_variable.type) ||
|
1339
|
-
temporary_variable(lhs_variable.type)
|
1340
|
-
notify_implicit_conv_performed(node.lhs_operand,
|
1341
|
-
result_variable, result_converted)
|
457
|
+
define_implicit_function(node.identifier.value)
|
1342
458
|
end
|
1343
459
|
|
1344
|
-
|
1345
|
-
|
1346
|
-
|
1347
|
-
|
460
|
+
def eval_array_subscript_expr(node, obj, subs)
|
461
|
+
unless obj.variable? && (obj.type.array? || obj.type.pointer?)
|
462
|
+
return create_tempvar
|
463
|
+
end
|
1348
464
|
|
1349
|
-
|
1350
|
-
|
465
|
+
ary_or_ptr = obj
|
466
|
+
result_type = ary_or_ptr.type.unqualify.base_type
|
467
|
+
|
468
|
+
case
|
469
|
+
when ary_or_ptr.type.array?
|
470
|
+
ary = ary_or_ptr
|
471
|
+
# NOTE: An array-subscript-expression with an array object only
|
472
|
+
# refers the array object, never refer the value of the array
|
473
|
+
# object.
|
474
|
+
when ary_or_ptr.type.pointer?
|
475
|
+
ptr = ary_or_ptr
|
476
|
+
if pointee = pointee_of(ptr) and pointee.type.array?
|
477
|
+
ary = pointee
|
478
|
+
end
|
479
|
+
# NOTE: An array-subscript-expression with a pointer object do refers
|
480
|
+
# the value of the pointer object.
|
481
|
+
_notify_variable_value_referred(node, ptr)
|
482
|
+
end
|
1351
483
|
|
1352
|
-
|
1353
|
-
|
1354
|
-
|
484
|
+
unless subs.variable? and
|
485
|
+
subs.value.scalar? && subs.value.exist? or subs.type.void?
|
486
|
+
# NOTE: To detect bad value reference of `void' expressions.
|
487
|
+
return create_tempvar(result_type)
|
488
|
+
end
|
489
|
+
_notify_variable_value_referred(node, subs)
|
490
|
+
|
491
|
+
# NOTE: An array subscript converted to `int' implicitly.
|
492
|
+
unless subs.type.same_as?(int_type)
|
493
|
+
if int_subs = do_conversion(subs, int_type)
|
494
|
+
notify_implicit_conv_performed(node.array_subscript,
|
495
|
+
subs, int_subs)
|
496
|
+
subs = int_subs
|
497
|
+
else
|
498
|
+
return create_tempvar(result_type)
|
499
|
+
end
|
500
|
+
end
|
1355
501
|
|
1356
|
-
|
1357
|
-
|
1358
|
-
|
1359
|
-
|
502
|
+
# FIXME: Domain of the subscript may have multiple values.
|
503
|
+
subs_val = subs.value.unique_sample
|
504
|
+
if ary and inner_var = ary.inner_variable_at(subs_val)
|
505
|
+
_notify_object_referred(node, inner_var)
|
506
|
+
if inner_var.type.same_as?(result_type)
|
507
|
+
result_var = inner_var
|
508
|
+
end
|
509
|
+
end
|
510
|
+
result_var ||= create_tempvar(result_type)
|
1360
511
|
|
1361
|
-
|
1362
|
-
|
1363
|
-
|
512
|
+
notify_array_subscript_expr_evaled(node, ary_or_ptr, subs, ary,
|
513
|
+
result_var)
|
514
|
+
result_var
|
1364
515
|
end
|
1365
516
|
|
1366
|
-
|
1367
|
-
|
1368
|
-
|
1369
|
-
|
1370
|
-
|
517
|
+
def eval_function_call_expr(node, obj, args)
|
518
|
+
if obj.function?
|
519
|
+
func = obj
|
520
|
+
else
|
521
|
+
return create_tempvar unless obj.type.pointer?
|
522
|
+
obj_base_type = obj.type.unqualify.base_type
|
523
|
+
if obj_base_type.function?
|
524
|
+
if pointee = pointee_of(obj) and pointee.function?
|
525
|
+
func = pointee
|
526
|
+
else
|
527
|
+
func = define_anonymous_function(obj_base_type)
|
528
|
+
end
|
529
|
+
end
|
530
|
+
end
|
531
|
+
_notify_variable_value_referred(node, obj)
|
532
|
+
|
533
|
+
# NOTE: The ISO C99 standard says;
|
534
|
+
#
|
535
|
+
# 6.5.2.2 Function calls
|
536
|
+
#
|
537
|
+
# Semantics
|
538
|
+
#
|
539
|
+
# 10 The order of evaluation of the function designator, the actual
|
540
|
+
# arguments, and subexpressions within the actual arguments is
|
541
|
+
# unspecified, but there is a sequence point before the actual call.
|
542
|
+
unless args.empty?
|
543
|
+
notify_sequence_point_reached(SequencePoint.new(node))
|
544
|
+
end
|
545
|
+
|
546
|
+
result_var = func.call(interpreter, node, args)
|
547
|
+
unless func.builtin?
|
548
|
+
arg_vars = args.map { |arg_obj, *| object_to_variable(arg_obj) }
|
549
|
+
notify_function_call_expr_evaled(node, func, arg_vars, result_var)
|
550
|
+
end
|
1371
551
|
|
1372
|
-
|
1373
|
-
|
1374
|
-
# warning detections.
|
1375
|
-
# _notify_variable_value_referred(node, lhs_variable)
|
552
|
+
result_var
|
553
|
+
end
|
1376
554
|
|
1377
|
-
|
555
|
+
def eval_member_access_by_value_expr(node, obj)
|
556
|
+
if obj.variable? && obj.type.composite?
|
557
|
+
outer_var = obj
|
558
|
+
else
|
559
|
+
return create_tempvar
|
560
|
+
end
|
1378
561
|
|
1379
|
-
|
562
|
+
memb_var = outer_var.inner_variable_named(node.identifier.value)
|
563
|
+
# NOTE: A member-access-by-value-expression only refers the composite
|
564
|
+
# object, never refer the value of the composite object.
|
1380
565
|
|
1381
|
-
|
1382
|
-
|
566
|
+
# NOTE: `memb_var' is nil when this expression represents the direct
|
567
|
+
# member access extension.
|
568
|
+
notify_member_access_expr_evaled(node, outer_var, memb_var)
|
1383
569
|
|
1384
|
-
|
1385
|
-
|
1386
|
-
|
1387
|
-
|
1388
|
-
|
1389
|
-
|
1390
|
-
notify_implicit_conv_performed(node.lhs_operand,
|
1391
|
-
result_variable, result_converted)
|
570
|
+
if memb_var
|
571
|
+
_notify_object_referred(node, memb_var)
|
572
|
+
memb_var
|
573
|
+
else
|
574
|
+
create_tempvar
|
575
|
+
end
|
1392
576
|
end
|
1393
577
|
|
1394
|
-
|
1395
|
-
|
1396
|
-
|
1397
|
-
|
1398
|
-
|
1399
|
-
|
1400
|
-
|
578
|
+
def eval_member_access_by_pointer_expr(node, obj)
|
579
|
+
obj_type = obj.type.unqualify
|
580
|
+
if obj.variable? && obj_type.pointer? && obj_type.base_type.composite?
|
581
|
+
ptr = obj
|
582
|
+
else
|
583
|
+
return create_tempvar
|
584
|
+
end
|
1401
585
|
|
1402
|
-
|
1403
|
-
|
1404
|
-
|
586
|
+
if pointee = pointee_of(ptr)
|
587
|
+
if pointee.type.array?
|
588
|
+
if first_elem = pointee.inner_variable_at(0)
|
589
|
+
pointee = first_elem
|
590
|
+
else
|
591
|
+
pointee = create_tempvar(obj_type.base_type)
|
592
|
+
end
|
593
|
+
end
|
594
|
+
end
|
595
|
+
# NOTE: A member-access-by-pointer-expression do refers the value of
|
596
|
+
# the pointer object.
|
597
|
+
_notify_variable_value_referred(node, ptr)
|
1405
598
|
|
1406
|
-
|
1407
|
-
|
1408
|
-
|
1409
|
-
|
599
|
+
if pointee && pointee.type.composite?
|
600
|
+
outer_var = pointee
|
601
|
+
memb_var = outer_var.inner_variable_named(node.identifier.value)
|
602
|
+
else
|
603
|
+
if memb = obj_type.base_type.member_named(node.identifier.value)
|
604
|
+
memb_var = create_tempvar(memb.type)
|
605
|
+
end
|
606
|
+
end
|
1410
607
|
|
1411
|
-
|
1412
|
-
|
1413
|
-
|
1414
|
-
end
|
608
|
+
# NOTE: `memb_var' is nil when this expression represents the direct
|
609
|
+
# member access extension.
|
610
|
+
notify_member_access_expr_evaled(node, ptr, memb_var)
|
1415
611
|
|
1416
|
-
|
1417
|
-
|
1418
|
-
|
1419
|
-
|
612
|
+
if memb_var
|
613
|
+
_notify_object_referred(node, memb_var)
|
614
|
+
memb_var
|
615
|
+
else
|
616
|
+
create_tempvar
|
617
|
+
end
|
1420
618
|
end
|
1421
619
|
|
1422
|
-
|
1423
|
-
|
1424
|
-
|
1425
|
-
|
620
|
+
def eval_postfix_increment_expr(node, obj)
|
621
|
+
if obj.variable? && obj.type.scalar?
|
622
|
+
var = obj
|
623
|
+
else
|
624
|
+
return create_tempvar
|
625
|
+
end
|
1426
626
|
|
1427
|
-
|
627
|
+
result_var = create_tempvar(var.type, var.value.dup)
|
1428
628
|
|
1429
|
-
|
629
|
+
# NOTE: Value of the variable is referred at this point. But value
|
630
|
+
# reference should not be notified not to confuse sequence-point
|
631
|
+
# warning detections.
|
632
|
+
# _notify_variable_value_referred(node, var)
|
1430
633
|
|
1431
|
-
|
1432
|
-
|
634
|
+
if var.value.scalar?
|
635
|
+
var.assign!(var.value + ScalarValue.of(1))
|
636
|
+
_notify_variable_value_updated(node, var)
|
637
|
+
end
|
1433
638
|
|
1434
|
-
|
1435
|
-
|
1436
|
-
else
|
1437
|
-
result_converted =
|
1438
|
-
do_conversion(result_variable, lhs_variable.type) ||
|
1439
|
-
temporary_variable(lhs_variable.type)
|
1440
|
-
notify_implicit_conv_performed(node.lhs_operand,
|
1441
|
-
result_variable, result_converted)
|
639
|
+
notify_postfix_increment_expr_evaled(node, var, result_var)
|
640
|
+
result_var
|
1442
641
|
end
|
1443
642
|
|
1444
|
-
|
1445
|
-
|
1446
|
-
|
1447
|
-
|
643
|
+
def eval_postfix_decrement_expr(node, obj)
|
644
|
+
if obj.variable? && obj.type.scalar?
|
645
|
+
var = obj
|
646
|
+
else
|
647
|
+
return create_tempvar
|
648
|
+
end
|
1448
649
|
|
1449
|
-
|
1450
|
-
end
|
650
|
+
result_var = create_tempvar(var.type, var.value.dup)
|
1451
651
|
|
1452
|
-
|
1453
|
-
|
1454
|
-
|
1455
|
-
|
1456
|
-
|
1457
|
-
|
1458
|
-
|
1459
|
-
|
652
|
+
# NOTE: Value of the variable is referred at this point. But value
|
653
|
+
# reference should not be notified not to confuse sequence-point
|
654
|
+
# warnings detections.
|
655
|
+
# _notify_variable_value_referred(node, var)
|
656
|
+
|
657
|
+
if var.value.scalar?
|
658
|
+
var.assign!(var.value - ScalarValue.of(1))
|
659
|
+
_notify_variable_value_updated(node, var)
|
660
|
+
end
|
1460
661
|
|
1461
|
-
|
1462
|
-
|
1463
|
-
interpreter.notify_variable_value_referred(node, object)
|
662
|
+
notify_postfix_decrement_expr_evaled(node, var, result_var)
|
663
|
+
result_var
|
1464
664
|
end
|
1465
665
|
|
1466
|
-
|
1467
|
-
|
1468
|
-
|
1469
|
-
|
666
|
+
def eval_prefix_increment_expr(node, obj)
|
667
|
+
if obj.variable? && obj.type.scalar?
|
668
|
+
var = obj
|
669
|
+
else
|
670
|
+
return create_tempvar
|
671
|
+
end
|
672
|
+
|
673
|
+
orig_val = var.value.dup
|
674
|
+
|
675
|
+
# NOTE: Value of the variable is referred at this point. But value
|
676
|
+
# reference should not be notified not to confuse sequence-point
|
677
|
+
# warnings detections.
|
678
|
+
# _notify_variable_value_referred(node, var)
|
1470
679
|
|
1471
|
-
|
1472
|
-
|
1473
|
-
|
1474
|
-
if object.inner?
|
1475
|
-
# NOTE: When a value of the inner-variable of array or composite
|
1476
|
-
# object is updated, the outer variable's value should also be
|
1477
|
-
# notified to be updated.
|
1478
|
-
_notify_variable_value_updated(node, object.owner)
|
680
|
+
if var.value.scalar?
|
681
|
+
var.assign!(var.value + ScalarValue.of(1))
|
682
|
+
_notify_variable_value_updated(node, var)
|
1479
683
|
end
|
684
|
+
|
685
|
+
notify_prefix_increment_expr_evaled(node, var, orig_val)
|
686
|
+
create_tempvar(var.type, var.value)
|
1480
687
|
end
|
1481
|
-
end
|
1482
688
|
|
1483
|
-
|
1484
|
-
|
1485
|
-
|
1486
|
-
|
689
|
+
def eval_prefix_decrement_expr(node, obj)
|
690
|
+
if obj.variable? && obj.type.scalar?
|
691
|
+
var = obj
|
692
|
+
else
|
693
|
+
return create_tempvar
|
694
|
+
end
|
1487
695
|
|
1488
|
-
|
1489
|
-
chars = string_literal.chars.map { |ch| ScalarValue.of(ch.ord) }
|
1490
|
-
ArrayValue.new(chars + [ScalarValue.of("\0".ord)])
|
1491
|
-
end
|
1492
|
-
end
|
696
|
+
orig_val = var.value.dup
|
1493
697
|
|
1494
|
-
|
1495
|
-
|
1496
|
-
|
698
|
+
# NOTE: Value of the variable is referred at this point. But value
|
699
|
+
# reference should not be notified not to confuse sequence-point
|
700
|
+
# warning detections.
|
701
|
+
# _notify_variable_value_referred(node, var)
|
1497
702
|
|
1498
|
-
|
1499
|
-
|
1500
|
-
|
1501
|
-
|
703
|
+
if var.value.scalar?
|
704
|
+
var.assign!(var.value - ScalarValue.of(1))
|
705
|
+
_notify_variable_value_updated(node, var)
|
706
|
+
end
|
1502
707
|
|
1503
|
-
|
1504
|
-
|
708
|
+
notify_prefix_decrement_expr_evaled(node, var, orig_val)
|
709
|
+
create_tempvar(var.type, var.value)
|
710
|
+
end
|
1505
711
|
|
1506
|
-
|
1507
|
-
|
712
|
+
def eval_address_expr(node, obj)
|
713
|
+
# NOTE: An address-expression does not read the value of the object.
|
714
|
+
# But value reference should be notified to emphasize global
|
715
|
+
# variable cross-references.
|
716
|
+
_notify_variable_value_referred(node, obj)
|
1508
717
|
|
1509
|
-
|
1510
|
-
|
718
|
+
ptr = create_tempvar(pointer_type(obj.type), pointer_value_of(obj))
|
719
|
+
notify_address_expr_evaled(node, obj, ptr)
|
720
|
+
ptr
|
721
|
+
end
|
1511
722
|
|
1512
|
-
|
1513
|
-
|
723
|
+
def eval_indirection_expr(node, obj)
|
724
|
+
if obj.variable? && obj.type.pointer?
|
725
|
+
ptr = obj
|
726
|
+
else
|
727
|
+
return create_tempvar
|
728
|
+
end
|
1514
729
|
|
1515
|
-
|
1516
|
-
|
730
|
+
pointee = pointee_of(ptr)
|
731
|
+
_notify_variable_value_referred(node, ptr)
|
1517
732
|
|
1518
|
-
|
1519
|
-
notify_constant_referred(node, variable)
|
1520
|
-
variable
|
1521
|
-
else
|
1522
|
-
temporary_variable
|
1523
|
-
end
|
1524
|
-
end
|
733
|
+
ptr_base_type = ptr.type.unqualify.base_type
|
1525
734
|
|
1526
|
-
|
1527
|
-
|
735
|
+
case
|
736
|
+
when pointee
|
737
|
+
_notify_object_referred(node, pointee)
|
738
|
+
if pointee.type.array?
|
739
|
+
if first_elem = pointee.inner_variable_at(0)
|
740
|
+
pointee = first_elem
|
741
|
+
else
|
742
|
+
pointee = create_tempvar(ptr_base_type)
|
743
|
+
end
|
744
|
+
end
|
1528
745
|
|
1529
|
-
|
1530
|
-
|
1531
|
-
|
1532
|
-
|
1533
|
-
|
1534
|
-
|
1535
|
-
|
1536
|
-
|
1537
|
-
|
746
|
+
unless ptr_base_type.same_as?(pointee.type)
|
747
|
+
pointee = do_conversion(pointee, ptr_base_type) ||
|
748
|
+
create_tempvar(ptr_base_type)
|
749
|
+
end
|
750
|
+
when ptr_base_type.function?
|
751
|
+
pointee = define_anonymous_function(ptr_base_type)
|
752
|
+
else
|
753
|
+
pointee = create_tempvar(ptr_base_type)
|
754
|
+
end
|
755
|
+
|
756
|
+
notify_indirection_expr_evaled(node, ptr, pointee)
|
757
|
+
pointee
|
1538
758
|
end
|
1539
|
-
end
|
1540
759
|
|
1541
|
-
|
1542
|
-
|
760
|
+
def eval_unary_arithmetic_expr(node, obj)
|
761
|
+
var = object_to_variable(obj)
|
762
|
+
case
|
763
|
+
when !var.type.scalar? && !var.type.void?
|
764
|
+
# NOTE: To detect bad value reference of `void' expressions.
|
765
|
+
return create_tempvar
|
766
|
+
when var != obj
|
767
|
+
notify_implicit_conv_performed(node.operand, obj, var)
|
768
|
+
end
|
1543
769
|
|
1544
|
-
|
1545
|
-
|
1546
|
-
|
1547
|
-
|
770
|
+
case node.operator.type
|
771
|
+
when "+"
|
772
|
+
result_var = create_tempvar(var.type, +var.value)
|
773
|
+
when "-"
|
774
|
+
result_var = create_tempvar(var.type, -var.value)
|
775
|
+
when "~"
|
776
|
+
result_var = create_tempvar(var.type, ~var.value)
|
777
|
+
when "!"
|
778
|
+
result_var = create_tempvar(int_type, !var.value)
|
779
|
+
else
|
780
|
+
__NOTREACHED__
|
781
|
+
end
|
782
|
+
_notify_variable_value_referred(node, var)
|
1548
783
|
|
1549
|
-
|
1550
|
-
|
784
|
+
notify_unary_arithmetic_expr_evaled(node, var, result_var)
|
785
|
+
result_var
|
786
|
+
end
|
1551
787
|
|
1552
|
-
node
|
1553
|
-
|
788
|
+
def eval_cast_expr(node, obj)
|
789
|
+
resolve_unresolved_type(node.type_name)
|
1554
790
|
|
1555
|
-
|
1556
|
-
|
791
|
+
var = object_to_variable(obj)
|
792
|
+
result_var = do_conversion(var, node.type_name.type) ||
|
793
|
+
create_tempvar(node.type_name.type)
|
1557
794
|
|
1558
|
-
|
1559
|
-
node, node.expression.accept(self), node.array_subscript.accept(self))
|
1560
|
-
end
|
795
|
+
notify_explicit_conv_performed(node, var, result_var)
|
1561
796
|
|
1562
|
-
|
1563
|
-
|
797
|
+
# NOTE: A cast-expression does not refer a source value essentially.
|
798
|
+
# But, to avoid misunderstand that a return value of a function
|
799
|
+
# is discarded when the return value is casted before assigning
|
800
|
+
# to a variable.
|
801
|
+
_notify_variable_value_referred(node, var)
|
802
|
+
result_var
|
803
|
+
end
|
1564
804
|
|
1565
|
-
|
1566
|
-
|
805
|
+
def eval_multiplicative_expr(node, lhs_obj, rhs_obj)
|
806
|
+
lhs_var = object_to_variable(lhs_obj)
|
807
|
+
case
|
808
|
+
when !lhs_var.type.scalar? && !lhs_var.type.void?
|
809
|
+
# NOTE: To detect bad value reference of `void' expressions.
|
810
|
+
return create_tempvar
|
811
|
+
when lhs_var != lhs_obj
|
812
|
+
notify_implicit_conv_performed(node.lhs_operand, lhs_obj, lhs_var)
|
813
|
+
end
|
1567
814
|
|
1568
|
-
|
1569
|
-
|
815
|
+
rhs_var = object_to_variable(rhs_obj)
|
816
|
+
case
|
817
|
+
when !rhs_var.type.scalar? && !rhs_var.type.void?
|
818
|
+
# NOTE: To detect bad value reference of `void' expressions.
|
819
|
+
return create_tempvar
|
820
|
+
when rhs_var != rhs_obj
|
821
|
+
notify_implicit_conv_performed(node.rhs_operand, rhs_obj, rhs_var)
|
822
|
+
end
|
1570
823
|
|
1571
|
-
|
1572
|
-
|
824
|
+
lhs_conved, rhs_conved =
|
825
|
+
do_usual_arithmetic_conversion(lhs_var, rhs_var)
|
1573
826
|
|
1574
|
-
|
827
|
+
unless lhs_conved == lhs_var
|
828
|
+
notify_implicit_conv_performed(node.lhs_operand, lhs_var, lhs_conved)
|
829
|
+
end
|
830
|
+
unless rhs_conved == rhs_var
|
831
|
+
notify_implicit_conv_performed(node.rhs_operand, rhs_var, rhs_conved)
|
832
|
+
end
|
1575
833
|
|
1576
|
-
|
1577
|
-
|
834
|
+
lhs_val = lhs_conved.value
|
835
|
+
rhs_val = rhs_conved.value
|
836
|
+
|
837
|
+
case node.operator.type
|
838
|
+
when "*"
|
839
|
+
# NOTE: Domain of the arithmetic result value will be restricted by
|
840
|
+
# min-max of the variable type.
|
841
|
+
result_var = create_tempvar(lhs_conved.type, lhs_val * rhs_val)
|
842
|
+
when "/"
|
843
|
+
# NOTE: Domain of the arithmetic result value will be restricted by
|
844
|
+
# min-max of the variable type.
|
845
|
+
# NOTE: "Div by 0" semantics is implemented in value-value
|
846
|
+
# arithmetic.
|
847
|
+
result_var = create_tempvar(lhs_conved.type, lhs_val / rhs_val)
|
848
|
+
when "%"
|
849
|
+
# NOTE: Domain of the arithmetic result value will be restricted by
|
850
|
+
# min-max of the variable type.
|
851
|
+
# NOTE: "Div by 0" semantics is implemented in value-value
|
852
|
+
# arithmetic.
|
853
|
+
result_var = create_tempvar(lhs_conved.type, lhs_val % rhs_val)
|
854
|
+
else
|
855
|
+
__NOTREACHED__
|
856
|
+
end
|
857
|
+
_notify_variable_value_referred(node, lhs_var)
|
858
|
+
_notify_variable_value_referred(node, rhs_var)
|
1578
859
|
|
1579
|
-
|
1580
|
-
|
860
|
+
notify_multiplicative_expr_evaled(node, lhs_var, rhs_var, result_var)
|
861
|
+
result_var
|
862
|
+
end
|
1581
863
|
|
1582
|
-
|
864
|
+
def eval_additive_expr(node, lhs_obj, rhs_obj)
|
865
|
+
lhs_var = object_to_variable(lhs_obj)
|
866
|
+
case
|
867
|
+
when !lhs_var.type.scalar? && !lhs_var.type.void?
|
868
|
+
# NOTE: To detect bad value reference of `void' expressions.
|
869
|
+
return create_tempvar
|
870
|
+
when lhs_var != lhs_obj
|
871
|
+
notify_implicit_conv_performed(node.lhs_operand, lhs_obj, lhs_var)
|
872
|
+
end
|
1583
873
|
|
1584
|
-
|
1585
|
-
|
874
|
+
rhs_var = object_to_variable(rhs_obj)
|
875
|
+
case
|
876
|
+
when !rhs_var.type.scalar? && !rhs_var.type.void?
|
877
|
+
# NOTE: To detect bad value reference of `void' expressions.
|
878
|
+
return create_tempvar
|
879
|
+
when rhs_var != rhs_obj
|
880
|
+
notify_implicit_conv_performed(node.rhs_operand, rhs_obj, rhs_var)
|
881
|
+
end
|
1586
882
|
|
1587
|
-
|
1588
|
-
|
883
|
+
lhs_conved, rhs_conved =
|
884
|
+
do_usual_arithmetic_conversion(lhs_var, rhs_var)
|
1589
885
|
|
1590
|
-
|
1591
|
-
|
1592
|
-
|
886
|
+
unless lhs_conved == lhs_var
|
887
|
+
notify_implicit_conv_performed(node.lhs_operand, lhs_var, lhs_conved)
|
888
|
+
end
|
889
|
+
unless rhs_conved == rhs_var
|
890
|
+
notify_implicit_conv_performed(node.rhs_operand, rhs_var, rhs_conved)
|
891
|
+
end
|
1593
892
|
|
1594
|
-
|
1595
|
-
|
893
|
+
lhs_val = lhs_conved.value
|
894
|
+
rhs_val = rhs_conved.value
|
895
|
+
|
896
|
+
case node.operator.type
|
897
|
+
when "+"
|
898
|
+
# NOTE: Domain of the arithmetic result value will be restricted by
|
899
|
+
# min-max of the variable type.
|
900
|
+
result_var = create_tempvar(lhs_conved.type, lhs_val + rhs_val)
|
901
|
+
when "-"
|
902
|
+
# NOTE: Domain of the arithmetic result value will be restricted by
|
903
|
+
# min-max of the variable type.
|
904
|
+
result_var = create_tempvar(lhs_conved.type, lhs_val - rhs_val)
|
905
|
+
else
|
906
|
+
__NOTREACHED__
|
907
|
+
end
|
908
|
+
_notify_variable_value_referred(node, lhs_var)
|
909
|
+
_notify_variable_value_referred(node, rhs_var)
|
1596
910
|
|
1597
|
-
|
1598
|
-
|
1599
|
-
|
911
|
+
notify_additive_expr_evaled(node, lhs_var, rhs_var, result_var)
|
912
|
+
result_var
|
913
|
+
end
|
1600
914
|
|
1601
|
-
|
1602
|
-
|
915
|
+
def eval_shift_expr(node, lhs_obj, rhs_obj)
|
916
|
+
lhs_var = object_to_variable(lhs_obj)
|
917
|
+
case
|
918
|
+
when !lhs_var.type.scalar? && !lhs_var.type.void?
|
919
|
+
# NOTE: To detect bad value reference of `void' expressions.
|
920
|
+
return create_tempvar
|
921
|
+
when lhs_var != lhs_obj
|
922
|
+
notify_implicit_conv_performed(node.lhs_operand, lhs_obj, lhs_var)
|
923
|
+
end
|
1603
924
|
|
1604
|
-
|
925
|
+
rhs_var = object_to_variable(rhs_obj)
|
926
|
+
case
|
927
|
+
when !rhs_var.type.scalar? && !rhs_var.type.void?
|
928
|
+
# NOTE: To detect bad value reference of `void' expressions.
|
929
|
+
return create_tempvar
|
930
|
+
when rhs_var != rhs_obj
|
931
|
+
notify_implicit_conv_performed(node.rhs_operand, rhs_obj, rhs_var)
|
932
|
+
end
|
1605
933
|
|
1606
|
-
|
1607
|
-
|
934
|
+
# NOTE: The ISO C99 standard says;
|
935
|
+
#
|
936
|
+
# 6.5.7 Bitwise shift operators
|
937
|
+
#
|
938
|
+
# 3 The integer promotions are performed on each of the operands. The
|
939
|
+
# type of the result is that of the promoted left operand. If the
|
940
|
+
# value of the right operand is negative or is greater than or equal
|
941
|
+
# to the width of the promoted left operand, the behavior is
|
942
|
+
# undefined.
|
943
|
+
|
944
|
+
lhs_conved = do_integer_promotion(lhs_var)
|
945
|
+
rhs_conved = do_integer_promotion(rhs_var)
|
946
|
+
|
947
|
+
unless lhs_conved == lhs_var
|
948
|
+
notify_implicit_conv_performed(node.lhs_operand, lhs_var, lhs_conved)
|
949
|
+
end
|
950
|
+
unless rhs_conved == rhs_var
|
951
|
+
notify_implicit_conv_performed(node.rhs_operand, rhs_var, rhs_conved)
|
952
|
+
end
|
1608
953
|
|
1609
|
-
|
1610
|
-
|
954
|
+
lhs_val = lhs_conved.value
|
955
|
+
rhs_val = rhs_conved.value
|
956
|
+
|
957
|
+
case node.operator.type
|
958
|
+
when "<<"
|
959
|
+
# NOTE: Domain of the arithmetic result value will be restricted by
|
960
|
+
# min-max of the variable type.
|
961
|
+
result_var = create_tempvar(lhs_conved.type, lhs_val << rhs_val)
|
962
|
+
when ">>"
|
963
|
+
# NOTE: Domain of the arithmetic result value will be restricted by
|
964
|
+
# min-max of the variable type.
|
965
|
+
result_var = create_tempvar(lhs_conved.type, lhs_val >> rhs_val)
|
966
|
+
else
|
967
|
+
__NOTREACHED__
|
968
|
+
end
|
969
|
+
_notify_variable_value_referred(node, lhs_var)
|
970
|
+
_notify_variable_value_referred(node, rhs_var)
|
1611
971
|
|
1612
|
-
|
972
|
+
notify_shift_expr_evaled(node, lhs_var, rhs_var, result_var)
|
973
|
+
result_var
|
974
|
+
end
|
1613
975
|
|
1614
|
-
|
1615
|
-
|
976
|
+
def eval_relational_expr(node, lhs_obj, rhs_obj)
|
977
|
+
lhs_var = object_to_variable(lhs_obj)
|
978
|
+
case
|
979
|
+
when !lhs_var.type.scalar? && !lhs_var.type.void?
|
980
|
+
# NOTE: To detect bad value reference of `void' expressions.
|
981
|
+
return create_tempvar(int_type, ScalarValue.of_arbitrary)
|
982
|
+
when lhs_var != lhs_obj
|
983
|
+
notify_implicit_conv_performed(node.lhs_operand, lhs_obj, lhs_var)
|
984
|
+
end
|
1616
985
|
|
1617
|
-
|
1618
|
-
|
986
|
+
rhs_var = object_to_variable(rhs_obj)
|
987
|
+
case
|
988
|
+
when !rhs_var.type.scalar? && !rhs_var.type.void?
|
989
|
+
# NOTE: To detect bad value reference of `void' expressions.
|
990
|
+
return create_tempvar(int_type, ScalarValue.of_arbitrary)
|
991
|
+
when rhs_var != rhs_obj
|
992
|
+
notify_implicit_conv_performed(node.rhs_operand, rhs_obj, rhs_var)
|
993
|
+
end
|
1619
994
|
|
1620
|
-
|
1621
|
-
|
1622
|
-
end
|
995
|
+
lhs_conved, rhs_conved =
|
996
|
+
do_usual_arithmetic_conversion(lhs_var, rhs_var)
|
1623
997
|
|
1624
|
-
|
1625
|
-
|
998
|
+
unless lhs_conved == lhs_var
|
999
|
+
notify_implicit_conv_performed(node.lhs_operand, lhs_var, lhs_conved)
|
1000
|
+
end
|
1001
|
+
unless rhs_conved == rhs_var
|
1002
|
+
notify_implicit_conv_performed(node.rhs_operand, rhs_var, rhs_conved)
|
1003
|
+
end
|
1626
1004
|
|
1627
|
-
|
1005
|
+
lhs_val = lhs_conved.value
|
1006
|
+
rhs_val = rhs_conved.value
|
1007
|
+
|
1008
|
+
case node.operator.type
|
1009
|
+
when "<"
|
1010
|
+
result_var = create_tempvar(int_type, lhs_val < rhs_val)
|
1011
|
+
when ">"
|
1012
|
+
result_var = create_tempvar(int_type, lhs_val > rhs_val)
|
1013
|
+
when "<="
|
1014
|
+
result_var = create_tempvar(int_type, lhs_val <= rhs_val)
|
1015
|
+
when ">="
|
1016
|
+
result_var = create_tempvar(int_type, lhs_val >= rhs_val)
|
1017
|
+
else
|
1018
|
+
__NOTREACHED__
|
1019
|
+
end
|
1020
|
+
_notify_variable_value_referred(node, lhs_var)
|
1021
|
+
_notify_variable_value_referred(node, rhs_var)
|
1628
1022
|
|
1629
|
-
|
1630
|
-
|
1023
|
+
notify_relational_expr_evaled(node, lhs_var, rhs_var, result_var)
|
1024
|
+
result_var
|
1025
|
+
end
|
1631
1026
|
|
1632
|
-
|
1633
|
-
|
1027
|
+
def eval_equality_expr(node, lhs_obj, rhs_obj)
|
1028
|
+
lhs_var = object_to_variable(lhs_obj)
|
1029
|
+
case
|
1030
|
+
when !lhs_var.type.scalar? && !lhs_var.type.void?
|
1031
|
+
# NOTE: To detect bad value reference of `void' expressions.
|
1032
|
+
return create_tempvar(int_type, ScalarValue.of_arbitrary)
|
1033
|
+
when lhs_var != lhs_obj
|
1034
|
+
notify_implicit_conv_performed(node.lhs_operand, lhs_obj, lhs_var)
|
1035
|
+
end
|
1634
1036
|
|
1635
|
-
|
1037
|
+
rhs_var = object_to_variable(rhs_obj)
|
1038
|
+
case
|
1039
|
+
when !rhs_var.type.scalar? && !rhs_var.type.void?
|
1040
|
+
# NOTE: To detect bad value reference of `void' expressions.
|
1041
|
+
return create_tempvar(int_type, ScalarValue.of_arbitrary)
|
1042
|
+
when rhs_var != rhs_obj
|
1043
|
+
notify_implicit_conv_performed(node.rhs_operand, rhs_obj, rhs_var)
|
1044
|
+
end
|
1636
1045
|
|
1637
|
-
|
1638
|
-
|
1046
|
+
lhs_conved, rhs_conved =
|
1047
|
+
do_usual_arithmetic_conversion(lhs_var, rhs_var)
|
1639
1048
|
|
1640
|
-
|
1641
|
-
|
1049
|
+
unless lhs_conved == lhs_var
|
1050
|
+
notify_implicit_conv_performed(node.lhs_operand, lhs_var, lhs_conved)
|
1051
|
+
end
|
1052
|
+
unless rhs_conved == rhs_var
|
1053
|
+
notify_implicit_conv_performed(node.rhs_operand, rhs_var, rhs_conved)
|
1054
|
+
end
|
1642
1055
|
|
1643
|
-
|
1056
|
+
lhs_val = lhs_conved.value
|
1057
|
+
rhs_val = rhs_conved.value
|
1644
1058
|
|
1645
|
-
|
1646
|
-
|
1059
|
+
case node.operator.type
|
1060
|
+
when "=="
|
1061
|
+
result_var = create_tempvar(int_type, lhs_val == rhs_val)
|
1062
|
+
when "!="
|
1063
|
+
result_var = create_tempvar(int_type, lhs_val != rhs_val)
|
1064
|
+
else
|
1065
|
+
__NOTREACHED__
|
1066
|
+
end
|
1067
|
+
_notify_variable_value_referred(node, lhs_var)
|
1068
|
+
_notify_variable_value_referred(node, rhs_var)
|
1647
1069
|
|
1648
|
-
|
1649
|
-
|
1070
|
+
notify_equality_expr_evaled(node, lhs_var, rhs_var, result_var)
|
1071
|
+
result_var
|
1072
|
+
end
|
1650
1073
|
|
1651
|
-
|
1074
|
+
def eval_and_expr(node, lhs_obj, rhs_obj)
|
1075
|
+
lhs_var = object_to_variable(lhs_obj)
|
1076
|
+
case
|
1077
|
+
when !lhs_var.type.scalar? && !lhs_var.type.void?
|
1078
|
+
# NOTE: To detect bad value reference of `void' expressions.
|
1079
|
+
return create_tempvar
|
1080
|
+
when lhs_var != lhs_obj
|
1081
|
+
notify_implicit_conv_performed(node.lhs_operand, lhs_obj, lhs_var)
|
1082
|
+
end
|
1652
1083
|
|
1653
|
-
|
1654
|
-
|
1084
|
+
rhs_var = object_to_variable(rhs_obj)
|
1085
|
+
case
|
1086
|
+
when !rhs_var.type.scalar? && !rhs_var.type.void?
|
1087
|
+
# NOTE: To detect bad value reference of `void' expressions.
|
1088
|
+
return create_tempvar
|
1089
|
+
when rhs_var != rhs_obj
|
1090
|
+
notify_implicit_conv_performed(node.rhs_operand, rhs_obj, rhs_var)
|
1091
|
+
end
|
1655
1092
|
|
1656
|
-
|
1657
|
-
|
1093
|
+
lhs_conved, rhs_conved =
|
1094
|
+
do_usual_arithmetic_conversion(lhs_var, rhs_var)
|
1658
1095
|
|
1659
|
-
|
1096
|
+
unless lhs_conved == lhs_var
|
1097
|
+
notify_implicit_conv_performed(node.lhs_operand, lhs_var, lhs_conved)
|
1098
|
+
end
|
1099
|
+
unless rhs_conved == rhs_var
|
1100
|
+
notify_implicit_conv_performed(node.rhs_operand, rhs_var, rhs_conved)
|
1101
|
+
end
|
1660
1102
|
|
1661
|
-
|
1662
|
-
|
1103
|
+
lhs_val = lhs_conved.value
|
1104
|
+
rhs_val = rhs_conved.value
|
1663
1105
|
|
1664
|
-
|
1665
|
-
|
1106
|
+
# NOTE: Domain of the arithmetic result value will be restricted by
|
1107
|
+
# min-max of the variable type.
|
1108
|
+
result_var = create_tempvar(lhs_conved.type, lhs_val & rhs_val)
|
1109
|
+
_notify_variable_value_referred(node, lhs_var)
|
1110
|
+
_notify_variable_value_referred(node, rhs_var)
|
1111
|
+
|
1112
|
+
notify_and_expr_evaled(node, lhs_var, rhs_var, result_var)
|
1113
|
+
result_var
|
1114
|
+
end
|
1115
|
+
|
1116
|
+
def eval_exclusive_or_expr(node, lhs_obj, rhs_obj)
|
1117
|
+
lhs_var = object_to_variable(lhs_obj)
|
1118
|
+
case
|
1119
|
+
when !lhs_var.type.scalar? && !lhs_var.type.void?
|
1120
|
+
# NOTE: To detect bad value reference of `void' expressions.
|
1121
|
+
return create_tempvar
|
1122
|
+
when lhs_var != lhs_obj
|
1123
|
+
notify_implicit_conv_performed(node.lhs_operand, lhs_obj, lhs_var)
|
1124
|
+
end
|
1666
1125
|
|
1667
|
-
|
1668
|
-
|
1669
|
-
|
1670
|
-
|
1671
|
-
|
1672
|
-
|
1126
|
+
rhs_var = object_to_variable(rhs_obj)
|
1127
|
+
case
|
1128
|
+
when !rhs_var.type.scalar? && !rhs_var.type.void?
|
1129
|
+
# NOTE: To detect bad value reference of `void' expressions.
|
1130
|
+
return create_tempvar
|
1131
|
+
when rhs_var != rhs_obj
|
1132
|
+
notify_implicit_conv_performed(node.rhs_operand, rhs_obj, rhs_var)
|
1673
1133
|
end
|
1674
1134
|
|
1675
|
-
|
1676
|
-
|
1677
|
-
|
1678
|
-
|
1679
|
-
|
1680
|
-
|
1681
|
-
|
1135
|
+
lhs_conved, rhs_conved =
|
1136
|
+
do_usual_arithmetic_conversion(lhs_var, rhs_var)
|
1137
|
+
|
1138
|
+
unless lhs_conved == lhs_var
|
1139
|
+
notify_implicit_conv_performed(node.lhs_operand, lhs_var, lhs_conved)
|
1140
|
+
end
|
1141
|
+
unless rhs_conved == rhs_var
|
1142
|
+
notify_implicit_conv_performed(node.rhs_operand, rhs_var, rhs_conved)
|
1682
1143
|
end
|
1683
|
-
end
|
1684
1144
|
|
1685
|
-
|
1686
|
-
|
1687
|
-
end
|
1145
|
+
lhs_val = lhs_conved.value
|
1146
|
+
rhs_val = rhs_conved.value
|
1688
1147
|
|
1689
|
-
|
1690
|
-
|
1148
|
+
# NOTE: Domain of the arithmetic result value will be restricted by
|
1149
|
+
# min-max of the variable type.
|
1150
|
+
result_var = create_tempvar(lhs_conved.type, lhs_val ^ rhs_val)
|
1151
|
+
_notify_variable_value_referred(node, lhs_var)
|
1152
|
+
_notify_variable_value_referred(node, rhs_var)
|
1153
|
+
|
1154
|
+
notify_exclusive_or_expr_evaled(node, lhs_var, rhs_var, result_var)
|
1155
|
+
result_var
|
1156
|
+
end
|
1157
|
+
|
1158
|
+
def eval_inclusive_or_expr(node, lhs_obj, rhs_obj)
|
1159
|
+
lhs_var = object_to_variable(lhs_obj)
|
1160
|
+
case
|
1161
|
+
when !lhs_var.type.scalar? && !lhs_var.type.void?
|
1162
|
+
# NOTE: To detect bad value reference of `void' expressions.
|
1163
|
+
return create_tempvar
|
1164
|
+
when lhs_var != lhs_obj
|
1165
|
+
notify_implicit_conv_performed(node.lhs_operand, lhs_obj, lhs_var)
|
1166
|
+
end
|
1691
1167
|
|
1692
|
-
|
1168
|
+
rhs_var = object_to_variable(rhs_obj)
|
1169
|
+
case
|
1170
|
+
when !rhs_var.type.scalar? && !rhs_var.type.void?
|
1171
|
+
# NOTE: To detect bad value reference of `void' expressions.
|
1172
|
+
return create_tempvar
|
1173
|
+
when rhs_var != rhs_obj
|
1174
|
+
notify_implicit_conv_performed(node.rhs_operand, rhs_obj, rhs_var)
|
1175
|
+
end
|
1693
1176
|
|
1694
|
-
|
1695
|
-
|
1696
|
-
|
1697
|
-
|
1698
|
-
|
1699
|
-
|
1177
|
+
lhs_conved, rhs_conved =
|
1178
|
+
do_usual_arithmetic_conversion(lhs_var, rhs_var)
|
1179
|
+
|
1180
|
+
unless lhs_conved == lhs_var
|
1181
|
+
notify_implicit_conv_performed(node.lhs_operand, lhs_var, lhs_conved)
|
1182
|
+
end
|
1183
|
+
unless rhs_conved == rhs_var
|
1184
|
+
notify_implicit_conv_performed(node.rhs_operand, rhs_var, rhs_conved)
|
1700
1185
|
end
|
1701
1186
|
|
1702
|
-
|
1703
|
-
|
1704
|
-
end
|
1187
|
+
lhs_val = lhs_conved.value
|
1188
|
+
rhs_val = rhs_conved.value
|
1705
1189
|
|
1706
|
-
|
1707
|
-
|
1708
|
-
|
1190
|
+
# NOTE: Domain of the arithmetic result value will be restricted by
|
1191
|
+
# min-max of the variable type.
|
1192
|
+
result_var = create_tempvar(lhs_conved.type, lhs_val | rhs_val)
|
1193
|
+
_notify_variable_value_referred(node, lhs_var)
|
1194
|
+
_notify_variable_value_referred(node, rhs_var)
|
1709
1195
|
|
1710
|
-
|
1711
|
-
|
1196
|
+
notify_inclusive_or_expr_evaled(node, lhs_var, rhs_var, result_var)
|
1197
|
+
result_var
|
1198
|
+
end
|
1712
1199
|
|
1713
|
-
|
1714
|
-
if
|
1715
|
-
|
1200
|
+
def eval_simple_assignment_expr(node, lhs_obj, rhs_obj)
|
1201
|
+
if lhs_obj.variable?
|
1202
|
+
lhs_var = lhs_obj
|
1716
1203
|
else
|
1717
|
-
|
1204
|
+
return lhs_obj
|
1205
|
+
end
|
1206
|
+
|
1207
|
+
rhs_var = object_to_variable(rhs_obj)
|
1208
|
+
unless rhs_var == rhs_obj
|
1209
|
+
notify_implicit_conv_performed(node.rhs_operand, rhs_obj, rhs_var)
|
1718
1210
|
end
|
1719
1211
|
|
1720
|
-
|
1721
|
-
|
1722
|
-
variable = object
|
1723
|
-
temporary_variable(result_type,
|
1724
|
-
ScalarValue.of(variable.type.byte_alignment))
|
1212
|
+
if rhs_var.type.same_as?(lhs_var.type)
|
1213
|
+
rhs_conved = rhs_var
|
1725
1214
|
else
|
1726
|
-
|
1215
|
+
rhs_conved = do_conversion(rhs_var, lhs_var.type) ||
|
1216
|
+
create_tempvar(lhs_var.type)
|
1217
|
+
notify_implicit_conv_performed(node.rhs_operand, rhs_var, rhs_conved)
|
1727
1218
|
end
|
1728
|
-
end
|
1729
|
-
end
|
1730
1219
|
|
1731
|
-
|
1732
|
-
|
1220
|
+
# NOTE: Domain of the arithmetic result value will be restricted by
|
1221
|
+
# min-max of the variable type.
|
1222
|
+
# NOTE: Even if rhs_obj is a NamedVariable, new value will be
|
1223
|
+
# instantiated in value-coercing.
|
1224
|
+
# So, value-aliasing never occurs.
|
1225
|
+
lhs_var.assign!(rhs_conved.value.to_defined_value)
|
1226
|
+
_notify_variable_value_referred(node, rhs_var)
|
1227
|
+
_notify_variable_value_updated(node, lhs_var)
|
1733
1228
|
|
1734
|
-
|
1229
|
+
notify_assignment_expr_evaled(node, lhs_var, rhs_var)
|
1230
|
+
lhs_var
|
1231
|
+
end
|
1735
1232
|
|
1736
|
-
|
1737
|
-
if
|
1738
|
-
|
1233
|
+
def eval_compound_assignment_expr(node, lhs_obj, rhs_obj)
|
1234
|
+
if lhs_obj.variable? && lhs_obj.type.scalar?
|
1235
|
+
lhs_var = lhs_obj
|
1739
1236
|
else
|
1740
|
-
|
1237
|
+
return lhs_obj
|
1741
1238
|
end
|
1742
1239
|
|
1743
|
-
|
1744
|
-
|
1745
|
-
|
1746
|
-
|
1240
|
+
rhs_var = object_to_variable(rhs_obj)
|
1241
|
+
case
|
1242
|
+
when !rhs_var.type.scalar? && !rhs_var.type.void?
|
1243
|
+
# NOTE: To detect bad value reference of `void' expressions.
|
1244
|
+
return create_tempvar
|
1245
|
+
when rhs_var != rhs_obj
|
1246
|
+
notify_implicit_conv_performed(node.rhs_operand, rhs_obj, rhs_var)
|
1247
|
+
end
|
1747
1248
|
|
1748
|
-
|
1749
|
-
|
1249
|
+
case node.operator.type
|
1250
|
+
when "*="
|
1251
|
+
_do_mul_then_assign(node, lhs_var, rhs_var)
|
1252
|
+
when "/="
|
1253
|
+
_do_div_then_assign(node, lhs_var, rhs_var)
|
1254
|
+
when "%="
|
1255
|
+
_do_mod_then_assign(node, lhs_var, rhs_var)
|
1256
|
+
when "+="
|
1257
|
+
_do_add_then_assign(node, lhs_var, rhs_var)
|
1258
|
+
when "-="
|
1259
|
+
_do_sub_then_assign(node, lhs_var, rhs_var)
|
1260
|
+
when "<<="
|
1261
|
+
_do_shl_then_assign(node, lhs_var, rhs_var)
|
1262
|
+
when ">>="
|
1263
|
+
_do_shr_then_assign(node, lhs_var, rhs_var)
|
1264
|
+
when "&="
|
1265
|
+
_do_and_then_assign(node, lhs_var, rhs_var)
|
1266
|
+
when "^="
|
1267
|
+
_do_xor_then_assign(node, lhs_var, rhs_var)
|
1268
|
+
when "|="
|
1269
|
+
_do_ior_then_assign(node, lhs_var, rhs_var)
|
1270
|
+
end
|
1750
1271
|
|
1751
|
-
|
1752
|
-
|
1753
|
-
end
|
1272
|
+
lhs_var
|
1273
|
+
end
|
1754
1274
|
|
1755
|
-
|
1756
|
-
|
1275
|
+
private
|
1276
|
+
def _do_mul_then_assign(node, lhs_var, rhs_var)
|
1277
|
+
lhs_conved, rhs_conved = _do_uarith_conversion(node, lhs_var, rhs_var)
|
1757
1278
|
|
1758
|
-
|
1759
|
-
|
1279
|
+
lhs_val = lhs_conved.value
|
1280
|
+
rhs_val = rhs_conved.value
|
1281
|
+
result_var = create_tempvar(lhs_conved.type, lhs_val * rhs_val)
|
1760
1282
|
|
1761
|
-
|
1762
|
-
|
1283
|
+
# NOTE: Value of the lhs_var is referred at this point. But value
|
1284
|
+
# reference should not be notified not to confuse sequence-point
|
1285
|
+
# warning detections.
|
1286
|
+
# _notify_variable_value_referred(node, lhs_var)
|
1287
|
+
_notify_variable_value_referred(node, rhs_var)
|
1763
1288
|
|
1764
|
-
|
1765
|
-
checkpoint(node.location)
|
1289
|
+
notify_multiplicative_expr_evaled(node, lhs_var, rhs_var, result_var)
|
1766
1290
|
|
1767
|
-
|
1768
|
-
|
1291
|
+
_do_assign(node, lhs_var, result_var)
|
1292
|
+
end
|
1769
1293
|
|
1770
|
-
|
1771
|
-
|
1294
|
+
def _do_div_then_assign(node, lhs_var, rhs_var)
|
1295
|
+
lhs_conved, rhs_conved = _do_uarith_conversion(node, lhs_var, rhs_var)
|
1772
1296
|
|
1773
|
-
|
1774
|
-
|
1297
|
+
lhs_val = lhs_conved.value
|
1298
|
+
rhs_val = rhs_conved.value
|
1299
|
+
# NOTE: "Div by 0" semantics is implemented in value-value arithmetic.
|
1300
|
+
result_var = create_tempvar(lhs_conved.type, lhs_val / rhs_val)
|
1775
1301
|
|
1776
|
-
|
1777
|
-
|
1302
|
+
# NOTE: Value of the lhs_var is referred at this point. But value
|
1303
|
+
# reference should not be notified not to confuse sequence-point
|
1304
|
+
# warning detections.
|
1305
|
+
# _notify_variable_value_referred(node, lhs_var)
|
1306
|
+
_notify_variable_value_referred(node, rhs_var)
|
1778
1307
|
|
1779
|
-
|
1780
|
-
end
|
1308
|
+
notify_multiplicative_expr_evaled(node, lhs_var, rhs_var, result_var)
|
1781
1309
|
|
1782
|
-
|
1783
|
-
|
1310
|
+
_do_assign(node, lhs_var, result_var)
|
1311
|
+
end
|
1784
1312
|
|
1785
|
-
|
1786
|
-
|
1313
|
+
def _do_mod_then_assign(node, lhs_var, rhs_var)
|
1314
|
+
lhs_conved, rhs_conved = _do_uarith_conversion(node, lhs_var, rhs_var)
|
1787
1315
|
|
1788
|
-
|
1789
|
-
|
1316
|
+
lhs_val = lhs_conved.value
|
1317
|
+
rhs_val = rhs_conved.value
|
1318
|
+
# NOTE: "Div by 0" semantics is implemented in value-value arithmetic.
|
1319
|
+
result_var = create_tempvar(lhs_conved.type, lhs_val % rhs_val)
|
1790
1320
|
|
1791
|
-
|
1792
|
-
|
1321
|
+
# NOTE: Value of the lhs_var is referred at this point. But value
|
1322
|
+
# reference should not be notified not to confuse sequence-point
|
1323
|
+
# warning detections.
|
1324
|
+
# _notify_variable_value_referred(node, lhs_var)
|
1325
|
+
_notify_variable_value_referred(node, rhs_var)
|
1793
1326
|
|
1794
|
-
|
1795
|
-
rhs_object = node.rhs_operand.accept(self)
|
1327
|
+
notify_multiplicative_expr_evaled(node, lhs_var, rhs_var, result_var)
|
1796
1328
|
|
1797
|
-
|
1798
|
-
|
1329
|
+
_do_assign(node, lhs_var, result_var)
|
1330
|
+
end
|
1799
1331
|
|
1800
|
-
|
1801
|
-
|
1332
|
+
def _do_add_then_assign(node, lhs_var, rhs_var)
|
1333
|
+
lhs_conved, rhs_conved = _do_uarith_conversion(node, lhs_var, rhs_var)
|
1802
1334
|
|
1803
|
-
|
1804
|
-
|
1335
|
+
lhs_val = lhs_conved.value
|
1336
|
+
rhs_val = rhs_conved.value
|
1337
|
+
result_var = create_tempvar(lhs_conved.type, lhs_val + rhs_val)
|
1805
1338
|
|
1806
|
-
|
1807
|
-
|
1339
|
+
# NOTE: Value of the lhs_var is referred at this point. But value
|
1340
|
+
# reference should not be notified not to confuse sequence-point
|
1341
|
+
# warning detections.
|
1342
|
+
# _notify_variable_value_referred(node, lhs_var)
|
1343
|
+
_notify_variable_value_referred(node, rhs_var)
|
1808
1344
|
|
1809
|
-
|
1810
|
-
checkpoint(node.location)
|
1345
|
+
notify_additive_expr_evaled(node, lhs_var, rhs_var, result_var)
|
1811
1346
|
|
1812
|
-
|
1813
|
-
|
1347
|
+
_do_assign(node, lhs_var, result_var)
|
1348
|
+
end
|
1814
1349
|
|
1815
|
-
|
1816
|
-
|
1350
|
+
def _do_sub_then_assign(node, lhs_var, rhs_var)
|
1351
|
+
lhs_conved, rhs_conved = _do_uarith_conversion(node, lhs_var, rhs_var)
|
1817
1352
|
|
1818
|
-
|
1819
|
-
|
1353
|
+
lhs_val = lhs_conved.value
|
1354
|
+
rhs_val = rhs_conved.value
|
1355
|
+
result_var = create_tempvar(lhs_conved.type, lhs_val - rhs_val)
|
1820
1356
|
|
1821
|
-
|
1822
|
-
|
1357
|
+
# NOTE: Value of the lhs_var is referred at this point. But value
|
1358
|
+
# reference should not be notified not to confuse sequence-point
|
1359
|
+
# warning detections.
|
1360
|
+
# _notify_variable_value_referred(node, lhs_var)
|
1361
|
+
_notify_variable_value_referred(node, rhs_var)
|
1823
1362
|
|
1824
|
-
|
1825
|
-
end
|
1363
|
+
notify_additive_expr_evaled(node, lhs_var, rhs_var, result_var)
|
1826
1364
|
|
1827
|
-
|
1828
|
-
|
1365
|
+
_do_assign(node, lhs_var, result_var)
|
1366
|
+
end
|
1829
1367
|
|
1830
|
-
|
1831
|
-
|
1368
|
+
def _do_shl_then_assign(node, lhs_var, rhs_var)
|
1369
|
+
# NOTE: The ISO C99 standard says;
|
1370
|
+
#
|
1371
|
+
# 6.5.7 Bitwise shift operators
|
1372
|
+
#
|
1373
|
+
# 3 The integer promotions are performed on each of the operands. The
|
1374
|
+
# type of the result is that of the promoted left operand. If the
|
1375
|
+
# value of the right operand is negative or is greater than or equal
|
1376
|
+
# to the width of the promoted left operand, the behavior is
|
1377
|
+
# undefined.
|
1378
|
+
lhs_conved, rhs_conved = _do_integer_promotions(node, lhs_var, rhs_var)
|
1832
1379
|
|
1833
|
-
|
1380
|
+
lhs_val = lhs_conved.value
|
1381
|
+
rhs_val = rhs_conved.value
|
1382
|
+
result_var = create_tempvar(lhs_conved.type, lhs_val << rhs_val)
|
1834
1383
|
|
1835
|
-
|
1836
|
-
|
1837
|
-
|
1838
|
-
|
1839
|
-
|
1840
|
-
#
|
1841
|
-
# 4 Unlike the bitwise binary & operator, the && operator guarantees
|
1842
|
-
# left-to-right evaluation; there is a sequence point after the
|
1843
|
-
# evaluation of the first operand. If the first operand compares equal
|
1844
|
-
# to 0, the second operand is not evaluated.
|
1845
|
-
notify_sequence_point_reached(SequencePoint.new(node.lhs_operand))
|
1384
|
+
# NOTE: Value of the lhs_var is referred at this point. But value
|
1385
|
+
# reference should not be notified not to confuse sequence-point
|
1386
|
+
# warning detections.
|
1387
|
+
# _notify_variable_value_referred(node, lhs_var)
|
1388
|
+
_notify_variable_value_referred(node, rhs_var)
|
1846
1389
|
|
1847
|
-
|
1848
|
-
|
1849
|
-
|
1850
|
-
return temporary_variable(int_type, ScalarValue.of_false)
|
1390
|
+
notify_shift_expr_evaled(node, lhs_var, rhs_var, result_var)
|
1391
|
+
|
1392
|
+
_do_assign(node, lhs_var, result_var)
|
1851
1393
|
end
|
1852
1394
|
|
1853
|
-
|
1854
|
-
|
1395
|
+
def _do_shr_then_assign(node, lhs_var, rhs_var)
|
1396
|
+
# NOTE: The ISO C99 standard says;
|
1397
|
+
#
|
1398
|
+
# 6.5.7 Bitwise shift operators
|
1399
|
+
#
|
1400
|
+
# 3 The integer promotions are performed on each of the operands. The
|
1401
|
+
# type of the result is that of the promoted left operand. If the
|
1402
|
+
# value of the right operand is negative or is greater than or equal
|
1403
|
+
# to the width of the promoted left operand, the behavior is
|
1404
|
+
# undefined.
|
1405
|
+
lhs_conved, rhs_conved = _do_integer_promotions(node, lhs_var, rhs_var)
|
1855
1406
|
|
1856
|
-
|
1857
|
-
|
1858
|
-
|
1859
|
-
notify_variable_value_referred(node, rhs_variable)
|
1407
|
+
lhs_val = lhs_conved.value
|
1408
|
+
rhs_val = rhs_conved.value
|
1409
|
+
result_var = create_tempvar(lhs_conved.type, lhs_val >> rhs_val)
|
1860
1410
|
|
1861
|
-
|
1862
|
-
#
|
1863
|
-
|
1864
|
-
|
1865
|
-
|
1866
|
-
|
1411
|
+
# NOTE: Value of the lhs_var is referred at this point. But value
|
1412
|
+
# reference should not be notified not to confuse sequence-point
|
1413
|
+
# warning detections.
|
1414
|
+
# _notify_variable_value_referred(node, lhs_var)
|
1415
|
+
_notify_variable_value_referred(node, rhs_var)
|
1416
|
+
|
1417
|
+
notify_shift_expr_evaled(node, lhs_var, rhs_var, result_var)
|
1418
|
+
|
1419
|
+
_do_assign(node, lhs_var, result_var)
|
1867
1420
|
end
|
1868
1421
|
|
1869
|
-
|
1870
|
-
|
1871
|
-
end
|
1422
|
+
def _do_and_then_assign(node, lhs_var, rhs_var)
|
1423
|
+
lhs_conved, rhs_conved = _do_uarith_conversion(node, lhs_var, rhs_var)
|
1872
1424
|
|
1873
|
-
|
1874
|
-
|
1425
|
+
lhs_val = lhs_conved.value
|
1426
|
+
rhs_val = rhs_conved.value
|
1427
|
+
result_var = create_tempvar(lhs_conved.type, lhs_val & rhs_val)
|
1875
1428
|
|
1876
|
-
|
1877
|
-
|
1429
|
+
# NOTE: Value of the lhs_var is referred at this point. But value
|
1430
|
+
# reference should not be notified not to confuse sequence-point
|
1431
|
+
# warning detections.
|
1432
|
+
# _notify_variable_value_referred(node, lhs_var)
|
1433
|
+
_notify_variable_value_referred(node, rhs_var)
|
1878
1434
|
|
1879
|
-
|
1435
|
+
notify_and_expr_evaled(node, lhs_var, rhs_var, result_var)
|
1880
1436
|
|
1881
|
-
|
1882
|
-
|
1883
|
-
# 6.5.14 Logical OR operator
|
1884
|
-
#
|
1885
|
-
# Semantics
|
1886
|
-
#
|
1887
|
-
# 4 Unlike the bitwise | operator, the || operator guarantees
|
1888
|
-
# left-to-right evaluation; there is a sequence point after the
|
1889
|
-
# evaluation of the first operand. If the first operand compares
|
1890
|
-
# unequal to 0, the second operand is not evaluated.
|
1891
|
-
notify_sequence_point_reached(SequencePoint.new(node.lhs_operand))
|
1437
|
+
_do_assign(node, lhs_var, result_var)
|
1438
|
+
end
|
1892
1439
|
|
1893
|
-
|
1894
|
-
|
1895
|
-
|
1896
|
-
|
1440
|
+
def _do_xor_then_assign(node, lhs_var, rhs_var)
|
1441
|
+
lhs_conved, rhs_conved = _do_uarith_conversion(node, lhs_var, rhs_var)
|
1442
|
+
|
1443
|
+
lhs_val = lhs_conved.value
|
1444
|
+
rhs_val = rhs_conved.value
|
1445
|
+
result_var = create_tempvar(lhs_conved.type, lhs_val ^ rhs_val)
|
1446
|
+
|
1447
|
+
# NOTE: Value of the lhs_var is referred at this point. But value
|
1448
|
+
# reference should not be notified not to confuse sequence-point
|
1449
|
+
# warning detections.
|
1450
|
+
# _notify_variable_value_referred(node, lhs_var)
|
1451
|
+
_notify_variable_value_referred(node, rhs_var)
|
1452
|
+
|
1453
|
+
notify_exclusive_or_expr_evaled(node, lhs_var, rhs_var, result_var)
|
1454
|
+
|
1455
|
+
_do_assign(node, lhs_var, result_var)
|
1897
1456
|
end
|
1898
1457
|
|
1899
|
-
|
1900
|
-
|
1458
|
+
def _do_ior_then_assign(node, lhs_var, rhs_var)
|
1459
|
+
lhs_conved, rhs_conved = _do_uarith_conversion(node, lhs_var, rhs_var)
|
1901
1460
|
|
1902
|
-
|
1903
|
-
|
1904
|
-
|
1905
|
-
notify_variable_value_referred(node, rhs_variable)
|
1461
|
+
lhs_val = lhs_conved.value
|
1462
|
+
rhs_val = rhs_conved.value
|
1463
|
+
result_var = create_tempvar(lhs_conved.type, lhs_val | rhs_val)
|
1906
1464
|
|
1907
|
-
|
1908
|
-
#
|
1909
|
-
|
1910
|
-
|
1911
|
-
|
1912
|
-
|
1465
|
+
# NOTE: Value of the lhs_var is referred at this point. But value
|
1466
|
+
# reference should not be notified not to confuse sequence-point
|
1467
|
+
# warning detections.
|
1468
|
+
# _notify_variable_value_referred(node, lhs_var)
|
1469
|
+
_notify_variable_value_referred(node, rhs_var)
|
1470
|
+
|
1471
|
+
notify_inclusive_or_expr_evaled(node, lhs_var, rhs_var, result_var)
|
1472
|
+
|
1473
|
+
_do_assign(node, lhs_var, result_var)
|
1913
1474
|
end
|
1914
1475
|
|
1915
|
-
|
1916
|
-
|
1917
|
-
|
1476
|
+
def _do_uarith_conversion(node, lhs_var, rhs_var)
|
1477
|
+
lhs_conved, rhs_conved =
|
1478
|
+
do_usual_arithmetic_conversion(lhs_var, rhs_var)
|
1918
1479
|
|
1919
|
-
|
1920
|
-
|
1480
|
+
unless lhs_conved == lhs_var
|
1481
|
+
notify_implicit_conv_performed(node.lhs_operand, lhs_var, lhs_conved)
|
1482
|
+
end
|
1483
|
+
unless rhs_conved == rhs_var
|
1484
|
+
notify_implicit_conv_performed(node.rhs_operand, rhs_var, rhs_conved)
|
1485
|
+
end
|
1921
1486
|
|
1922
|
-
|
1923
|
-
|
1487
|
+
return lhs_conved, rhs_conved
|
1488
|
+
end
|
1924
1489
|
|
1925
|
-
|
1926
|
-
|
1490
|
+
def _do_integer_promotions(node, lhs_var, rhs_var)
|
1491
|
+
lhs_conved = do_integer_promotion(lhs_var)
|
1492
|
+
unless lhs_conved == lhs_var
|
1493
|
+
notify_implicit_conv_performed(node.lhs_operand, lhs_var, lhs_conved)
|
1494
|
+
end
|
1927
1495
|
|
1928
|
-
|
1929
|
-
|
1496
|
+
rhs_conved = do_integer_promotion(rhs_var)
|
1497
|
+
unless rhs_conved == rhs_var
|
1498
|
+
notify_implicit_conv_performed(node.rhs_operand, rhs_var, rhs_conved)
|
1499
|
+
end
|
1500
|
+
|
1501
|
+
return lhs_conved, rhs_conved
|
1502
|
+
end
|
1930
1503
|
|
1931
|
-
|
1932
|
-
|
1504
|
+
def _do_assign(node, lhs_var, result_var)
|
1505
|
+
if result_var.type.same_as?(lhs_var.type)
|
1506
|
+
result_conved = result_var
|
1507
|
+
else
|
1508
|
+
result_conved = do_conversion(result_var, lhs_var.type) ||
|
1509
|
+
create_tempvar(lhs_var.type)
|
1510
|
+
notify_implicit_conv_performed(node.lhs_operand,
|
1511
|
+
result_var, result_conved)
|
1512
|
+
end
|
1933
1513
|
|
1934
|
-
|
1935
|
-
|
1514
|
+
# NOTE: Domain of the arithmetic result value will be restricted by
|
1515
|
+
# min-max of the variable type.
|
1516
|
+
lhs_var.assign!(result_conved.value.to_defined_value)
|
1517
|
+
_notify_variable_value_updated(node, lhs_var)
|
1936
1518
|
|
1937
|
-
|
1938
|
-
|
1519
|
+
notify_assignment_expr_evaled(node, lhs_var, result_conved)
|
1520
|
+
end
|
1939
1521
|
|
1940
|
-
node
|
1941
|
-
|
1522
|
+
def _notify_object_referred(node, obj)
|
1523
|
+
case obj
|
1524
|
+
when Variable
|
1525
|
+
interpreter.notify_variable_referred(node, obj)
|
1526
|
+
when Function
|
1527
|
+
interpreter.notify_function_referred(node, obj)
|
1528
|
+
end
|
1529
|
+
end
|
1942
1530
|
|
1943
|
-
|
1944
|
-
|
1945
|
-
|
1946
|
-
|
1947
|
-
|
1531
|
+
def _notify_variable_value_referred(node, obj)
|
1532
|
+
if obj.variable?
|
1533
|
+
interpreter.notify_variable_value_referred(node, obj)
|
1534
|
+
end
|
1535
|
+
|
1536
|
+
# NOTE: When a value of the inner-variable of array or composite object
|
1537
|
+
# is referred, notification of the outer variable's value has
|
1538
|
+
# already been done in sub expressions.
|
1948
1539
|
end
|
1949
|
-
|
1950
|
-
|
1951
|
-
|
1952
|
-
|
1953
|
-
|
1954
|
-
|
1955
|
-
|
1956
|
-
|
1957
|
-
|
1540
|
+
|
1541
|
+
def _notify_variable_value_updated(node, obj)
|
1542
|
+
if obj.variable?
|
1543
|
+
interpreter.notify_variable_value_updated(node, obj)
|
1544
|
+
if obj.inner?
|
1545
|
+
# NOTE: When a value of the inner-variable of array or composite
|
1546
|
+
# object is updated, the outer variable's value should also
|
1547
|
+
# be notified to be updated.
|
1548
|
+
_notify_variable_value_updated(node, obj.owner)
|
1549
|
+
end
|
1550
|
+
end
|
1958
1551
|
end
|
1959
1552
|
end
|
1553
|
+
|
1554
|
+
include Impl
|
1960
1555
|
end
|
1961
1556
|
|
1962
1557
|
end
|