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/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 ExpressionUtil
41
- # NOTE: Host class of this module must include InterpreterMediator,
42
- # NotifierMediator and Conversion.
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
- notify_unary_arithmetic_expr_evaled(node, variable, result)
44
+ include NotifierMediator
45
+ include ConstantEvaluator
46
+ include Conversion
388
47
 
389
- result
48
+ def visit_error_expression(node)
49
+ checkpoint(node.location)
50
+ create_tempvar
390
51
  end
391
52
 
392
- def execute_cast_expression(node, object)
393
- resolve_unresolved_type(node.type_name)
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 execute_multiplicative_expression(node, lhs_object, rhs_object)
412
- lhs_variable = object_to_variable(lhs_object)
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
- case node.operator.type
448
- when "*"
449
- # NOTE: Domain of the arithmetic result value will be restricted by
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
- __NOTREACHED__
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 execute_additive_expression(node, lhs_object, rhs_object)
477
- lhs_variable = object_to_variable(lhs_object)
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.operator.type
513
- when "+"
514
- # NOTE: Domain of the arithmetic result value will be restricted by
515
- # min-max of the variable type.
516
- result = temporary_variable(lhs_converted.type,
517
- lhs_converted.value + rhs_converted.value)
518
- when "-"
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
- __NOTREACHED__
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 execute_shift_expression(node, lhs_object, rhs_object)
535
- lhs_variable = object_to_variable(lhs_object)
536
- unless lhs_variable.type.scalar? || lhs_variable.type.void?
537
- # NOTE: To detect bad value reference of `void' expressions.
538
- return temporary_variable
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 execute_relational_expression(node, lhs_object, rhs_object)
601
- lhs_variable = object_to_variable(lhs_object)
602
- unless lhs_variable.type.scalar? || lhs_variable.type.void?
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 execute_equality_expression(node, lhs_object, rhs_object)
661
- lhs_variable = object_to_variable(lhs_object)
662
- unless lhs_variable.type.scalar? || lhs_variable.type.void?
663
- # NOTE: To detect bad value reference of `void' expressions.
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 execute_and_expression(node, lhs_object, rhs_object)
715
- lhs_variable = object_to_variable(lhs_object)
716
- unless lhs_variable.type.scalar? || lhs_variable.type.void?
717
- # NOTE: To detect bad value reference of `void' expressions.
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 execute_exclusive_or_expression(node, lhs_object, rhs_object)
763
- lhs_variable = object_to_variable(lhs_object)
764
- unless lhs_variable.type.scalar? || lhs_variable.type.void?
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 execute_inclusive_or_expression(node, lhs_object, rhs_object)
811
- lhs_variable = object_to_variable(lhs_object)
812
- unless lhs_variable.type.scalar? || lhs_variable.type.void?
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 execute_simple_assignment_expression(node, lhs_object, rhs_object)
859
- return lhs_object unless lhs_object.variable?
860
- lhs_variable = lhs_object
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 execute_compound_assignment_expression(node, lhs_object, rhs_object)
893
- unless lhs_object.variable? && lhs_object.type.scalar?
894
- return temporary_variable
895
- end
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 execute_mul_then_assign_expression(node, lhs_variable, rhs_variable)
936
- lhs_converted, rhs_converted =
937
- do_usual_arithmetic_conversion(lhs_variable, rhs_variable)
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 execute_div_then_assign_expression(node, lhs_variable, rhs_variable)
986
- lhs_converted, rhs_converted =
987
- do_usual_arithmetic_conversion(lhs_variable, rhs_variable)
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 execute_mod_then_assign_expression(node, lhs_variable, rhs_variable)
1037
- lhs_converted, rhs_converted =
1038
- do_usual_arithmetic_conversion(lhs_variable, rhs_variable)
1039
-
1040
- unless lhs_variable == lhs_converted
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
- result_variable = temporary_variable(lhs_converted.type, result_value)
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
- notify_multiplicative_expr_evaled(node, lhs_variable, rhs_variable,
1067
- result_variable)
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
- if result_variable.type.same_as?(lhs_variable.type)
1070
- result_converted = result_variable
1071
- else
1072
- result_converted =
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
- # NOTE: Domain of the arithmetic result value will be restricted by
1080
- # min-max of the variable type.
1081
- lhs_variable.assign!(result_converted.value)
1082
- _notify_variable_value_updated(node, lhs_variable)
161
+ def visit_indirection_expression(node)
162
+ checkpoint(node.location)
163
+ eval_indirection_expr(node, node.operand.accept(self))
164
+ end
1083
165
 
1084
- notify_assignment_expr_evaled(node, lhs_variable, result_converted)
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 execute_add_then_assign_expression(node, lhs_variable, rhs_variable)
1088
- lhs_converted, rhs_converted =
1089
- do_usual_arithmetic_conversion(lhs_variable, rhs_variable)
171
+ def visit_sizeof_expression(node)
172
+ checkpoint(node.location)
1090
173
 
1091
- unless lhs_variable == lhs_converted
1092
- notify_implicit_conv_performed(node.lhs_operand,
1093
- lhs_variable, lhs_converted)
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
- unless rhs_variable == rhs_converted
1097
- notify_implicit_conv_performed(node.rhs_operand,
1098
- rhs_variable, rhs_converted)
1099
- end
186
+ notify_sizeof_expr_evaled(node, operand_obj, result_var)
187
+ result_var
188
+ end
1100
189
 
1101
- if lhs_converted.value.scalar? && rhs_converted.value.scalar?
1102
- result_value = lhs_converted.value + rhs_converted.value
1103
- else
1104
- result_value = lhs_converted.value
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
- # NOTE: Value of the lhs_variable is referred at this point. But value
1108
- # reference should not be notified not to confuse sequence-point
1109
- # warning detections.
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
- _notify_variable_value_referred(node, rhs_variable)
205
+ def visit_alignof_expression(node)
206
+ checkpoint(node.location)
1113
207
 
1114
- result_variable = temporary_variable(lhs_converted.type, result_value)
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
- notify_additive_expr_evaled(node, lhs_variable, rhs_variable,
1117
- result_variable)
220
+ def visit_alignof_type_expression(node)
221
+ checkpoint(node.location)
222
+ resolve_unresolved_type(node.operand)
1118
223
 
1119
- if result_variable.type.same_as?(lhs_variable.type)
1120
- result_converted = result_variable
1121
- else
1122
- result_converted =
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
- # NOTE: Domain of the arithmetic result value will be restricted by
1130
- # min-max of the variable type.
1131
- lhs_variable.assign!(result_converted.value)
1132
- _notify_variable_value_updated(node, lhs_variable)
231
+ def visit_cast_expression(node)
232
+ checkpoint(node.location)
233
+ eval_cast_expr(node, node.operand.accept(self))
234
+ end
1133
235
 
1134
- notify_assignment_expr_evaled(node, lhs_variable, result_converted)
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 execute_sub_then_assign_expression(node, lhs_variable, rhs_variable)
1138
- lhs_converted, rhs_converted =
1139
- do_usual_arithmetic_conversion(lhs_variable, rhs_variable)
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
- unless lhs_variable == lhs_converted
1142
- notify_implicit_conv_performed(node.lhs_operand,
1143
- lhs_variable, lhs_converted)
1144
- end
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
- unless rhs_variable == rhs_converted
1147
- notify_implicit_conv_performed(node.rhs_operand,
1148
- rhs_variable, rhs_converted)
1149
- end
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
- if lhs_converted.value.scalar? && rhs_converted.value.scalar?
1152
- result_value = lhs_converted.value - rhs_converted.value
1153
- else
1154
- result_value = lhs_converted.value
1155
- end
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
- # NOTE: Value of the lhs_variable is referred at this point. But value
1158
- # reference should not be notified not to confuse sequence-point
1159
- # warning detections.
1160
- # _notify_variable_value_referred(node, lhs_variable)
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
- _notify_variable_value_referred(node, rhs_variable)
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
- result_variable = temporary_variable(lhs_converted.type, result_value)
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
- notify_additive_expr_evaled(node, lhs_variable, rhs_variable,
1167
- result_variable)
284
+ def visit_logical_and_expression(node)
285
+ checkpoint(node.location)
1168
286
 
1169
- if result_variable.type.same_as?(lhs_variable.type)
1170
- result_converted = result_variable
287
+ lhs_obj = node.lhs_operand.accept(self)
288
+ if lhs_obj.variable?
289
+ lhs_var = lhs_obj
1171
290
  else
1172
- result_converted =
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: Domain of the arithmetic result value will be restricted by
1180
- # min-max of the variable type.
1181
- lhs_variable.assign!(result_converted.value)
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
- # 6.5.7 Bitwise shift operators
298
+ # Semantics
1191
299
  #
1192
- # 3 The integer promotions are performed on each of the operands. The
1193
- # type of the result is that of the promoted left operand. If the
1194
- # value of the right operand is negative or is greater than or equal to
1195
- # the width of the promoted left operand, the behavior is undefined.
1196
-
1197
- lhs_converted = do_integer_promotion(lhs_variable)
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
- rhs_converted = do_integer_promotion(rhs_variable)
1204
- unless rhs_variable == rhs_converted
1205
- notify_implicit_conv_performed(node.rhs_operand,
1206
- rhs_variable, rhs_converted)
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
- if lhs_converted.value.scalar? && rhs_converted.value.scalar?
1210
- result_value = lhs_converted.value << rhs_converted.value
313
+ rhs_obj = node.rhs_operand.accept(self)
314
+ if rhs_obj.variable?
315
+ rhs_var = rhs_obj
1211
316
  else
1212
- result_value = lhs_converted.value
317
+ return create_tempvar(int_type)
1213
318
  end
1214
319
 
1215
- # NOTE: Value of the lhs_variable is referred at this point. But value
1216
- # reference should not be notified not to confuse sequence-point
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
- _notify_variable_value_referred(node, rhs_variable)
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
- result_variable = temporary_variable(lhs_converted.type, result_value)
332
+ notify_logical_and_expr_evaled(node, lhs_var, rhs_var, result_var)
333
+ result_var
334
+ end
1223
335
 
1224
- notify_shift_expr_evaled(node, lhs_variable, rhs_variable,
1225
- result_variable)
336
+ def visit_logical_or_expression(node)
337
+ checkpoint(node.location)
1226
338
 
1227
- if result_variable.type.same_as?(lhs_variable.type)
1228
- result_converted = result_variable
339
+ lhs_obj = node.lhs_operand.accept(self)
340
+ if lhs_obj.variable?
341
+ lhs_var = lhs_obj
1229
342
  else
1230
- result_converted =
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: Domain of the arithmetic result value will be restricted by
1238
- # min-max of the variable type.
1239
- lhs_variable.assign!(result_converted.value)
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
- # 6.5.7 Bitwise shift operators
350
+ # Semantics
1249
351
  #
1250
- # 3 The integer promotions are performed on each of the operands. The
1251
- # type of the result is that of the promoted left operand. If the
1252
- # value of the right operand is negative or is greater than or equal to
1253
- # the width of the promoted left operand, the behavior is undefined.
1254
-
1255
- lhs_converted = do_integer_promotion(lhs_variable)
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
- rhs_converted = do_integer_promotion(rhs_variable)
1262
- unless rhs_variable == rhs_converted
1263
- notify_implicit_conv_performed(node.rhs_operand,
1264
- rhs_variable, rhs_converted)
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
- if lhs_converted.value.scalar? && rhs_converted.value.scalar?
1268
- result_value = lhs_converted.value >> rhs_converted.value
365
+ rhs_obj = node.rhs_operand.accept(self)
366
+ if rhs_obj.variable?
367
+ rhs_var = rhs_obj
1269
368
  else
1270
- result_value = lhs_converted.value
369
+ return create_tempvar(int_type)
1271
370
  end
1272
371
 
1273
- # NOTE: Value of the lhs_variable is referred at this point. But value
1274
- # reference should not be notified not to confuse sequence-point
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 result_variable.type.same_as?(lhs_variable.type)
1286
- result_converted = result_variable
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
- result_converted =
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
- # NOTE: Domain of the arithmetic result value will be restricted by
1296
- # min-max of the variable type.
1297
- lhs_variable.assign!(result_converted.value)
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
- notify_assignment_expr_evaled(node, lhs_variable, result_converted)
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 execute_and_then_assign_expression(node, lhs_variable, rhs_variable)
1304
- lhs_converted, rhs_converted =
1305
- do_usual_arithmetic_conversion(lhs_variable, rhs_variable)
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
- unless lhs_variable == lhs_converted
1308
- notify_implicit_conv_performed(node.lhs_operand,
1309
- lhs_variable, lhs_converted)
1310
- end
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
- unless rhs_variable == rhs_converted
1313
- notify_implicit_conv_performed(node.rhs_operand,
1314
- rhs_variable, rhs_converted)
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
- if lhs_converted.value.scalar? && rhs_converted.value.scalar?
1318
- result_value = lhs_converted.value & rhs_converted.value
1319
- else
1320
- result_value = lhs_converted.value
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
- # NOTE: Value of the lhs_variable is referred at this point. But value
1324
- # reference should not be notified not to confuse sequence-point
1325
- # warning detections.
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
- _notify_variable_value_referred(node, rhs_variable)
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
- result_variable = temporary_variable(lhs_converted.type, result_value)
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
- notify_and_expr_evaled(node, lhs_variable, rhs_variable, result_variable)
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
- if result_variable.type.same_as?(lhs_variable.type)
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
- # NOTE: Domain of the arithmetic result value will be restricted by
1345
- # min-max of the variable type.
1346
- lhs_variable.assign!(result_converted.value)
1347
- _notify_variable_value_updated(node, lhs_variable)
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
- notify_assignment_expr_evaled(node, lhs_variable, result_converted)
1350
- end
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
- def execute_xor_then_assign_expression(node, lhs_variable, rhs_variable)
1353
- lhs_converted, rhs_converted =
1354
- do_usual_arithmetic_conversion(lhs_variable, rhs_variable)
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
- unless lhs_variable == lhs_converted
1357
- notify_implicit_conv_performed(node.lhs_operand,
1358
- lhs_variable, lhs_converted)
1359
- end
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
- unless rhs_variable == rhs_converted
1362
- notify_implicit_conv_performed(node.rhs_operand,
1363
- rhs_variable, rhs_converted)
512
+ notify_array_subscript_expr_evaled(node, ary_or_ptr, subs, ary,
513
+ result_var)
514
+ result_var
1364
515
  end
1365
516
 
1366
- if lhs_converted.value.scalar? && rhs_converted.value.scalar?
1367
- result_value = lhs_converted.value ^ rhs_converted.value
1368
- else
1369
- result_value = lhs_converted.value
1370
- end
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
- # NOTE: Value of the lhs_variable is referred at this point. But value
1373
- # reference should not be notified not to confuse sequence-point
1374
- # warning detections.
1375
- # _notify_variable_value_referred(node, lhs_variable)
552
+ result_var
553
+ end
1376
554
 
1377
- _notify_variable_value_referred(node, rhs_variable)
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
- result_variable = temporary_variable(lhs_converted.type, result_value)
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
- notify_exclusive_or_expr_evaled(node, lhs_variable, rhs_variable,
1382
- result_variable)
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
- if result_variable.type.same_as?(lhs_variable.type)
1385
- result_converted = result_variable
1386
- else
1387
- result_converted =
1388
- do_conversion(result_variable, lhs_variable.type) ||
1389
- temporary_variable(lhs_variable.type)
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
- # NOTE: Domain of the arithmetic result value will be restricted by
1395
- # min-max of the variable type.
1396
- lhs_variable.assign!(result_converted.value)
1397
- _notify_variable_value_updated(node, lhs_variable)
1398
-
1399
- notify_assignment_expr_evaled(node, lhs_variable, result_converted)
1400
- end
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
- def execute_ior_then_assign_expression(node, lhs_variable, rhs_variable)
1403
- lhs_converted, rhs_converted =
1404
- do_usual_arithmetic_conversion(lhs_variable, rhs_variable)
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
- unless lhs_variable == lhs_converted
1407
- notify_implicit_conv_performed(node.lhs_operand,
1408
- lhs_variable, lhs_converted)
1409
- end
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
- unless rhs_variable == rhs_converted
1412
- notify_implicit_conv_performed(node.rhs_operand,
1413
- rhs_variable, rhs_converted)
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
- if lhs_converted.value.scalar? && rhs_converted.value.scalar?
1417
- result_value = lhs_converted.value | rhs_converted.value
1418
- else
1419
- result_value = lhs_converted.value
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
- # NOTE: Value of the lhs_variable is referred at this point. But value
1423
- # reference should not be notified not to confuse sequence-point
1424
- # warning detections.
1425
- # _notify_variable_value_referred(node, lhs_variable)
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
- _notify_variable_value_referred(node, rhs_variable)
627
+ result_var = create_tempvar(var.type, var.value.dup)
1428
628
 
1429
- result_variable = temporary_variable(lhs_converted.type, result_value)
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
- notify_inclusive_or_expr_evaled(node, lhs_variable, rhs_variable,
1432
- result_variable)
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
- if result_variable.type.same_as?(lhs_variable.type)
1435
- result_converted = result_variable
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
- # NOTE: Domain of the arithmetic result value will be restricted by
1445
- # min-max of the variable type.
1446
- lhs_variable.assign!(result_converted.value)
1447
- _notify_variable_value_updated(node, lhs_variable)
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
- notify_assignment_expr_evaled(node, lhs_variable, result_converted)
1450
- end
650
+ result_var = create_tempvar(var.type, var.value.dup)
1451
651
 
1452
- def _notify_object_referred(node, object)
1453
- case object
1454
- when Variable
1455
- interpreter.notify_variable_referred(node, object)
1456
- when Function
1457
- interpreter.notify_function_referred(node, object)
1458
- end
1459
- end
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
- def _notify_variable_value_referred(node, object)
1462
- if object.variable?
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
- # NOTE: When a value of the inner-variable of array or composite object
1467
- # is referred, notification of the outer variable's value has
1468
- # already been done in sub expressions.
1469
- end
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
- def _notify_variable_value_updated(node, object)
1472
- if object.variable?
1473
- interpreter.notify_variable_value_updated(node, object)
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
- def _char_array_value(string_literal)
1484
- chars = string_literal.chars.map { |ch| ScalarValue.of(ch.ord) }
1485
- ArrayValue.new(chars + [ScalarValue.of("\0".ord)])
1486
- end
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
- def _wchar_array_value(string_literal)
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
- module ExpressionEvaluator
1495
- # NOTE: Host class of this module must include InterpreterMediator and
1496
- # MonitorUtil.
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
- include NotifierMediator
1499
- include ConstantEvaluator
1500
- include Conversion
1501
- include ExpressionUtil
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
- def visit_error_expression(node)
1504
- checkpoint(node.location)
708
+ notify_prefix_decrement_expr_evaled(node, var, orig_val)
709
+ create_tempvar(var.type, var.value)
710
+ end
1505
711
 
1506
- temporary_variable
1507
- end
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
- def visit_object_specifier(node)
1510
- checkpoint(node.location)
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
- execute_object_specifier(node)
1513
- end
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
- def visit_constant_specifier(node)
1516
- checkpoint(node.location)
730
+ pointee = pointee_of(ptr)
731
+ _notify_variable_value_referred(node, ptr)
1517
732
 
1518
- if variable = eval_constant(node)
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
- def visit_string_literal_specifier(node)
1527
- checkpoint(node.location)
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
- case node.literal.value
1530
- when /\A"(.*)"\z/
1531
- temporary_variable(array_type(char_type, $1.length + 1),
1532
- _char_array_value($1))
1533
- when /\AL"(.*)"\z/i
1534
- temporary_variable(array_type(wchar_type, $1.length + 1),
1535
- _wchar_array_value($1))
1536
- else
1537
- temporary_variable(array_type(char_type))
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
- def visit_null_constant_specifier(node)
1542
- checkpoint(node.location)
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
- # TODO: NULL may not be 0 on some environments.
1545
- # Representation of NULL should be configurable?
1546
- temporary_variable(pointer_type(void_type), ScalarValue.of(0))
1547
- end
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
- def visit_grouped_expression(node)
1550
- checkpoint(node.location)
784
+ notify_unary_arithmetic_expr_evaled(node, var, result_var)
785
+ result_var
786
+ end
1551
787
 
1552
- node.expression.accept(self)
1553
- end
788
+ def eval_cast_expr(node, obj)
789
+ resolve_unresolved_type(node.type_name)
1554
790
 
1555
- def visit_array_subscript_expression(node)
1556
- checkpoint(node.location)
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
- execute_array_subscript_expression(
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
- def visit_function_call_expression(node)
1563
- checkpoint(node.location)
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
- object = node.expression.accept(self)
1566
- args = node.argument_expressions.map { |expr| [expr.accept(self), expr] }
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
- execute_function_call_expression(node, object, args)
1569
- end
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
- def visit_member_access_by_value_expression(node)
1572
- checkpoint(node.location)
824
+ lhs_conved, rhs_conved =
825
+ do_usual_arithmetic_conversion(lhs_var, rhs_var)
1573
826
 
1574
- object = node.expression.accept(self)
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
- execute_member_access_by_value_expression(node, object)
1577
- end
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
- def visit_member_access_by_pointer_expression(node)
1580
- checkpoint(node.location)
860
+ notify_multiplicative_expr_evaled(node, lhs_var, rhs_var, result_var)
861
+ result_var
862
+ end
1581
863
 
1582
- object = node.expression.accept(self)
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
- execute_member_access_by_pointer_expression(node, object)
1585
- end
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
- def visit_bit_access_by_value_expression(node)
1588
- checkpoint(node.location)
883
+ lhs_conved, rhs_conved =
884
+ do_usual_arithmetic_conversion(lhs_var, rhs_var)
1589
885
 
1590
- # TODO: Should support the GCC extension.
1591
- temporary_variable
1592
- end
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
- def visit_bit_access_by_pointer_expression(node)
1595
- checkpoint(node.location)
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
- # TODO: Should support the GCC extension.
1598
- temporary_variable
1599
- end
911
+ notify_additive_expr_evaled(node, lhs_var, rhs_var, result_var)
912
+ result_var
913
+ end
1600
914
 
1601
- def visit_postfix_increment_expression(node)
1602
- checkpoint(node.location)
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
- object = node.operand.accept(self)
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
- execute_postfix_increment_expression(node, object)
1607
- end
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
- def visit_postfix_decrement_expression(node)
1610
- checkpoint(node.location)
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
- object = node.operand.accept(self)
972
+ notify_shift_expr_evaled(node, lhs_var, rhs_var, result_var)
973
+ result_var
974
+ end
1613
975
 
1614
- execute_postfix_decrement_expression(node, object)
1615
- end
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
- def visit_compound_literal_expression(node)
1618
- checkpoint(node.location)
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
- # TODO: Should support C99 features.
1621
- temporary_variable(node.type_name.type)
1622
- end
995
+ lhs_conved, rhs_conved =
996
+ do_usual_arithmetic_conversion(lhs_var, rhs_var)
1623
997
 
1624
- def visit_prefix_increment_expression(node)
1625
- checkpoint(node.location)
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
- object = node.operand.accept(self)
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
- execute_prefix_increment_expression(node, object)
1630
- end
1023
+ notify_relational_expr_evaled(node, lhs_var, rhs_var, result_var)
1024
+ result_var
1025
+ end
1631
1026
 
1632
- def visit_prefix_decrement_expression(node)
1633
- checkpoint(node.location)
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
- object = node.operand.accept(self)
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
- execute_prefix_decrement_expression(node, object)
1638
- end
1046
+ lhs_conved, rhs_conved =
1047
+ do_usual_arithmetic_conversion(lhs_var, rhs_var)
1639
1048
 
1640
- def visit_address_expression(node)
1641
- checkpoint(node.location)
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
- object = node.operand.accept(self)
1056
+ lhs_val = lhs_conved.value
1057
+ rhs_val = rhs_conved.value
1644
1058
 
1645
- execute_address_expression(node, object)
1646
- end
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
- def visit_indirection_expression(node)
1649
- checkpoint(node.location)
1070
+ notify_equality_expr_evaled(node, lhs_var, rhs_var, result_var)
1071
+ result_var
1072
+ end
1650
1073
 
1651
- object = node.operand.accept(self)
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
- execute_indirection_expression(node, object)
1654
- end
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
- def visit_unary_arithmetic_expression(node)
1657
- checkpoint(node.location)
1093
+ lhs_conved, rhs_conved =
1094
+ do_usual_arithmetic_conversion(lhs_var, rhs_var)
1658
1095
 
1659
- object = node.operand.accept(self)
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
- execute_unary_arithmetic_expression(node, object)
1662
- end
1103
+ lhs_val = lhs_conved.value
1104
+ rhs_val = rhs_conved.value
1663
1105
 
1664
- def visit_sizeof_expression(node)
1665
- checkpoint(node.location)
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
- variable = result = nil
1668
- eval_without_side_effect do
1669
- if size_t_type = type_of(UserTypeId.new("size_t"))
1670
- result_type = size_t_type
1671
- else
1672
- result_type = unsigned_long_type
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
- object = node.operand.accept(self)
1676
- if object.variable?
1677
- variable = object
1678
- result = temporary_variable(
1679
- result_type, ScalarValue.of(variable.type.aligned_byte_size))
1680
- else
1681
- return temporary_variable(result_type)
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
- notify_sizeof_expr_evaled(node, variable, result)
1686
- result
1687
- end
1145
+ lhs_val = lhs_conved.value
1146
+ rhs_val = rhs_conved.value
1688
1147
 
1689
- def visit_sizeof_type_expression(node)
1690
- checkpoint(node.location)
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
- resolve_unresolved_type(node.operand)
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
- result = nil
1695
- eval_without_side_effect do
1696
- if size_t_type = type_of(UserTypeId.new("size_t"))
1697
- result_type = size_t_type
1698
- else
1699
- result_type = unsigned_long_type
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
- result = temporary_variable(
1703
- result_type, ScalarValue.of(node.operand.type.aligned_byte_size))
1704
- end
1187
+ lhs_val = lhs_conved.value
1188
+ rhs_val = rhs_conved.value
1705
1189
 
1706
- notify_sizeof_type_expr_evaled(node, node.operand.type, result)
1707
- result
1708
- end
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
- def visit_alignof_expression(node)
1711
- checkpoint(node.location)
1196
+ notify_inclusive_or_expr_evaled(node, lhs_var, rhs_var, result_var)
1197
+ result_var
1198
+ end
1712
1199
 
1713
- eval_without_side_effect do
1714
- if size_t_type = type_of(UserTypeId.new("size_t"))
1715
- result_type = size_t_type
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
- result_type = unsigned_long_type
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
- object = node.operand.accept(self)
1721
- if object.variable?
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
- temporary_variable(result_type)
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
- def visit_alignof_type_expression(node)
1732
- checkpoint(node.location)
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
- resolve_unresolved_type(node.operand)
1229
+ notify_assignment_expr_evaled(node, lhs_var, rhs_var)
1230
+ lhs_var
1231
+ end
1735
1232
 
1736
- eval_without_side_effect do
1737
- if size_t_type = type_of(UserTypeId.new("size_t"))
1738
- result_type = size_t_type
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
- result_type = unsigned_long_type
1237
+ return lhs_obj
1741
1238
  end
1742
1239
 
1743
- temporary_variable(result_type,
1744
- ScalarValue.of(node.operand.type.aligned_byte_size))
1745
- end
1746
- end
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
- def visit_cast_expression(node)
1749
- checkpoint(node.location)
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
- object = node.operand.accept(self)
1752
- execute_cast_expression(node, object)
1753
- end
1272
+ lhs_var
1273
+ end
1754
1274
 
1755
- def visit_multiplicative_expression(node)
1756
- checkpoint(node.location)
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
- lhs_object = node.lhs_operand.accept(self)
1759
- rhs_object = node.rhs_operand.accept(self)
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
- execute_multiplicative_expression(node, lhs_object, rhs_object)
1762
- end
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
- def visit_additive_expression(node)
1765
- checkpoint(node.location)
1289
+ notify_multiplicative_expr_evaled(node, lhs_var, rhs_var, result_var)
1766
1290
 
1767
- lhs_object = node.lhs_operand.accept(self)
1768
- rhs_object = node.rhs_operand.accept(self)
1291
+ _do_assign(node, lhs_var, result_var)
1292
+ end
1769
1293
 
1770
- execute_additive_expression(node, lhs_object, rhs_object)
1771
- end
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
- def visit_shift_expression(node)
1774
- checkpoint(node.location)
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
- lhs_object = node.lhs_operand.accept(self)
1777
- rhs_object = node.rhs_operand.accept(self)
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
- execute_shift_expression(node, lhs_object, rhs_object)
1780
- end
1308
+ notify_multiplicative_expr_evaled(node, lhs_var, rhs_var, result_var)
1781
1309
 
1782
- def visit_relational_expression(node)
1783
- checkpoint(node.location)
1310
+ _do_assign(node, lhs_var, result_var)
1311
+ end
1784
1312
 
1785
- lhs_object = node.lhs_operand.accept(self)
1786
- rhs_object = node.rhs_operand.accept(self)
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
- execute_relational_expression(node, lhs_object, rhs_object)
1789
- end
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
- def visit_equality_expression(node)
1792
- checkpoint(node.location)
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
- lhs_object = node.lhs_operand.accept(self)
1795
- rhs_object = node.rhs_operand.accept(self)
1327
+ notify_multiplicative_expr_evaled(node, lhs_var, rhs_var, result_var)
1796
1328
 
1797
- execute_equality_expression(node, lhs_object, rhs_object)
1798
- end
1329
+ _do_assign(node, lhs_var, result_var)
1330
+ end
1799
1331
 
1800
- def visit_and_expression(node)
1801
- checkpoint(node.location)
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
- lhs_object = node.lhs_operand.accept(self)
1804
- rhs_object = node.rhs_operand.accept(self)
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
- execute_and_expression(node, lhs_object, rhs_object)
1807
- end
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
- def visit_exclusive_or_expression(node)
1810
- checkpoint(node.location)
1345
+ notify_additive_expr_evaled(node, lhs_var, rhs_var, result_var)
1811
1346
 
1812
- lhs_object = node.lhs_operand.accept(self)
1813
- rhs_object = node.rhs_operand.accept(self)
1347
+ _do_assign(node, lhs_var, result_var)
1348
+ end
1814
1349
 
1815
- execute_exclusive_or_expression(node, lhs_object, rhs_object)
1816
- end
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
- def visit_inclusive_or_expression(node)
1819
- checkpoint(node.location)
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
- lhs_object = node.lhs_operand.accept(self)
1822
- rhs_object = node.rhs_operand.accept(self)
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
- execute_inclusive_or_expression(node, lhs_object, rhs_object)
1825
- end
1363
+ notify_additive_expr_evaled(node, lhs_var, rhs_var, result_var)
1826
1364
 
1827
- def visit_logical_and_expression(node)
1828
- checkpoint(node.location)
1365
+ _do_assign(node, lhs_var, result_var)
1366
+ end
1829
1367
 
1830
- lhs_object = node.lhs_operand.accept(self)
1831
- return temporary_variable(int_type) unless lhs_object.variable?
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
- lhs_variable = lhs_object
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
- # NOTE: The ISO C99 standard saids;
1836
- #
1837
- # 6.5.13 Logical AND operator
1838
- #
1839
- # Semantics
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
- if lhs_variable.value.scalar? && lhs_variable.value.must_be_false?
1848
- # NOTE: Doing the short-circuit evaluation.
1849
- notify_variable_value_referred(node, lhs_variable)
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
- rhs_object = node.rhs_operand.accept(self)
1854
- return temporary_variable(int_type) unless rhs_object.variable?
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
- rhs_variable = rhs_object
1857
- notify_sequence_point_reached(SequencePoint.new(node.rhs_operand))
1858
- notify_variable_value_referred(node, lhs_variable)
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
- if lhs_variable.value.scalar? && rhs_variable.value.scalar?
1862
- # NOTE: No usual-arithmetic-conversion.
1863
- result = temporary_variable(
1864
- int_type, lhs_variable.value.logical_and(rhs_variable.value))
1865
- else
1866
- result = temporary_variable(int_type)
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
- notify_logical_and_expr_evaled(node, lhs_variable, rhs_variable, result)
1870
- result
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
- def visit_logical_or_expression(node)
1874
- checkpoint(node.location)
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
- lhs_object = node.lhs_operand.accept(self)
1877
- return temporary_variable(int_type) unless lhs_object.variable?
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
- lhs_variable = lhs_object
1435
+ notify_and_expr_evaled(node, lhs_var, rhs_var, result_var)
1880
1436
 
1881
- # NOTE: The ISO C99 standard saids;
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
- if lhs_variable.value.scalar? && lhs_variable.value.must_be_true?
1894
- # NOTE: Doing the short-circuit evaluation.
1895
- notify_variable_value_referred(node, lhs_variable)
1896
- return temporary_variable(int_type, ScalarValue.of_true)
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
- rhs_object = node.rhs_operand.accept(self)
1900
- return temporary_variable(int_type) unless rhs_object.variable?
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
- rhs_variable = rhs_object
1903
- notify_sequence_point_reached(SequencePoint.new(node.rhs_operand))
1904
- notify_variable_value_referred(node, lhs_variable)
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
- if lhs_variable.value.scalar? && rhs_variable.value.scalar?
1908
- # NOTE: No usual-arithmetic-conversion.
1909
- result = temporary_variable(
1910
- int_type, lhs_variable.value.logical_or(rhs_variable.value))
1911
- else
1912
- result = temporary_variable(int_type)
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
- notify_logical_or_expr_evaled(node, lhs_variable, rhs_variable, result)
1916
- result
1917
- end
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
- def visit_simple_assignment_expression(node)
1920
- checkpoint(node.location)
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
- lhs_object = node.lhs_operand.accept(self)
1923
- rhs_object = node.rhs_operand.accept(self)
1487
+ return lhs_conved, rhs_conved
1488
+ end
1924
1489
 
1925
- execute_simple_assignment_expression(node, lhs_object, rhs_object)
1926
- end
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
- def visit_compound_assignment_expression(node)
1929
- checkpoint(node.location)
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
- lhs_object = node.lhs_operand.accept(self)
1932
- rhs_object = node.rhs_operand.accept(self)
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
- execute_compound_assignment_expression(node, lhs_object, rhs_object)
1935
- end
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
- def visit_comma_separated_expression(node)
1938
- checkpoint(node.location)
1519
+ notify_assignment_expr_evaled(node, lhs_var, result_conved)
1520
+ end
1939
1521
 
1940
- node.expressions.map { |expression| expression.accept(self) }.last
1941
- end
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
- private
1944
- def eval_without_side_effect(&block)
1945
- originally_quiet = interpreter.quiet_without_side_effect?
1946
- unless originally_quiet
1947
- interpreter._quiet_without_side_effect = true
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
- yield
1950
- ensure
1951
- unless originally_quiet
1952
- interpreter._quiet_without_side_effect = false
1953
- # FIXME: Evaluation of an object-specifier doesn't refer to value
1954
- # of a variable. Thus, no cross-reference record on a
1955
- # sizeof-expression because cross-reference extraction
1956
- # watches variable value reference not variable reference.
1957
- # collect_object_specifiers(node).each { |os| os.accept(self) }
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