adlint 2.6.0 → 2.6.2

Sign up to get free protection for your applications and to get access to all the features.
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