Module: AdLint::Cc1::ExpressionEvaluator

Includes:
ConstantEvaluator, Conversion, Impl, NotifierMediator
Included in:
ExpressionInterpreter
Defined in:
lib/adlint/cc1/expr.rb

Defined Under Namespace

Modules: Impl

Instance Method Summary collapse

Methods included from Impl

#eval_additive_expr, #eval_address_expr, #eval_and_expr, #eval_array_subscript_expr, #eval_bit_access_by_pointer_expr, #eval_bit_access_by_value_expr, #eval_cast_expr, #eval_compound_assignment_expr, #eval_compound_literal_expr, #eval_equality_expr, #eval_exclusive_or_expr, #eval_function_call_expr, #eval_inclusive_or_expr, #eval_indirection_expr, #eval_member_access_by_pointer_expr, #eval_member_access_by_value_expr, #eval_multiplicative_expr, #eval_object_specifier, #eval_postfix_decrement_expr, #eval_postfix_increment_expr, #eval_prefix_decrement_expr, #eval_prefix_increment_expr, #eval_relational_expr, #eval_shift_expr, #eval_simple_assignment_expr, #eval_unary_arithmetic_expr

Methods included from Conversion

#do_conversion, #do_default_argument_promotion, #do_integer_promotion, #do_usual_arithmetic_conversion, #untyped_pointer_conversion?

Methods included from ConstantEvaluator

#eval_constant

Instance Method Details

#visit_additive_expression(node) ⇒ Object



253
254
255
256
257
# File 'lib/adlint/cc1/expr.rb', line 253

def visit_additive_expression(node)
  checkpoint(node.location)
  eval_additive_expr(node, node.lhs_operand.accept(self),
                     node.rhs_operand.accept(self))
end

#visit_address_expression(node) ⇒ Object



159
160
161
162
# File 'lib/adlint/cc1/expr.rb', line 159

def visit_address_expression(node)
  checkpoint(node.location)
  eval_address_expr(node, node.operand.accept(self))
end

#visit_alignof_expression(node) ⇒ Object



208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
# File 'lib/adlint/cc1/expr.rb', line 208

def visit_alignof_expression(node)
  checkpoint(node.location)

  ope_obj = rslt_var = nil
  eval_quietly_without_side_effects do
    rslt_type = type_of(UserTypeId.new("size_t")) || unsigned_long_t
    ope_obj = node.operand.accept(self)
    if ope_obj.variable?
      align = ope_obj.type.byte_alignment
      rslt_var = create_tmpvar(rslt_type, scalar_value_of(align))
    else
      rslt_var = create_tmpvar(rslt_type)
    end
  end

  notify_alignof_expr_evaled(node, ope_obj, rslt_var)
  rslt_var
end

#visit_alignof_type_expression(node) ⇒ Object



227
228
229
230
231
232
233
234
235
236
237
238
239
240
# File 'lib/adlint/cc1/expr.rb', line 227

def visit_alignof_type_expression(node)
  checkpoint(node.location)
  resolve_unresolved_type(node.operand)

  rslt_var = nil
  eval_quietly_without_side_effects do
    rslt_type = type_of(UserTypeId.new("size_t")) || unsigned_long_t
    align = node.operand.type.aligned_byte_size
    rslt_var = create_tmpvar(rslt_type, scalar_value_of(align))
  end

  notify_alignof_type_expr_evaled(node, node.operand.type, rslt_var)
  rslt_var
end

#visit_and_expression(node) ⇒ Object



277
278
279
280
281
# File 'lib/adlint/cc1/expr.rb', line 277

def visit_and_expression(node)
  checkpoint(node.location)
  eval_and_expr(node, node.lhs_operand.accept(self),
                node.rhs_operand.accept(self))
end

#visit_array_subscript_expression(node) ⇒ Object



102
103
104
105
106
# File 'lib/adlint/cc1/expr.rb', line 102

def visit_array_subscript_expression(node)
  checkpoint(node.location)
  eval_array_subscript_expr(node, node.expression.accept(self),
                            node.array_subscript.accept(self))
end

#visit_bit_access_by_pointer_expression(node) ⇒ Object



129
130
131
132
# File 'lib/adlint/cc1/expr.rb', line 129

def visit_bit_access_by_pointer_expression(node)
  checkpoint(node.location)
  eval_bit_access_by_pointer_expr(node, node.expression.accept(self))
end

#visit_bit_access_by_value_expression(node) ⇒ Object



124
125
126
127
# File 'lib/adlint/cc1/expr.rb', line 124

def visit_bit_access_by_value_expression(node)
  checkpoint(node.location)
  eval_bit_access_by_value_expr(node, node.expression.accept(self))
end

#visit_cast_expression(node) ⇒ Object



242
243
244
245
# File 'lib/adlint/cc1/expr.rb', line 242

def visit_cast_expression(node)
  checkpoint(node.location)
  eval_cast_expr(node, node.operand.accept(self))
end

#visit_comma_separated_expression(node) ⇒ Object



411
412
413
414
# File 'lib/adlint/cc1/expr.rb', line 411

def visit_comma_separated_expression(node)
  checkpoint(node.location)
  node.expressions.map { |expr| expr.accept(self) }.last
end

#visit_compound_assignment_expression(node) ⇒ Object



405
406
407
408
409
# File 'lib/adlint/cc1/expr.rb', line 405

def visit_compound_assignment_expression(node)
  checkpoint(node.location)
  eval_compound_assignment_expr(node, node.lhs_operand.accept(self),
                                node.rhs_operand.accept(self))
end

#visit_compound_literal_expression(node) ⇒ Object



144
145
146
147
# File 'lib/adlint/cc1/expr.rb', line 144

def visit_compound_literal_expression(node)
  checkpoint(node.location)
  eval_compound_literal_expr(node)
end

#visit_constant_specifier(node) ⇒ Object



58
59
60
61
62
63
64
65
66
67
68
69
70
# File 'lib/adlint/cc1/expr.rb', line 58

def visit_constant_specifier(node)
  checkpoint(node.location)

  if const_var = eval_constant(node)
    notify_constant_referred(node, const_var)
    rslt_var = const_var
  else
    rslt_var = create_tmpvar
  end

  notify_constant_specifier_evaled(node, rslt_var)
  rslt_var
end

#visit_equality_expression(node) ⇒ Object



271
272
273
274
275
# File 'lib/adlint/cc1/expr.rb', line 271

def visit_equality_expression(node)
  checkpoint(node.location)
  eval_equality_expr(node, node.lhs_operand.accept(self),
                     node.rhs_operand.accept(self))
end

#visit_error_expression(node) ⇒ Object



48
49
50
51
# File 'lib/adlint/cc1/expr.rb', line 48

def visit_error_expression(node)
  checkpoint(node.location)
  create_tmpvar.tap { |rslt_var| notify_error_expr_evaled(node, rslt_var) }
end

#visit_exclusive_or_expression(node) ⇒ Object



283
284
285
286
287
# File 'lib/adlint/cc1/expr.rb', line 283

def visit_exclusive_or_expression(node)
  checkpoint(node.location)
  eval_exclusive_or_expr(node, node.lhs_operand.accept(self),
                         node.rhs_operand.accept(self))
end

#visit_function_call_expression(node) ⇒ Object



108
109
110
111
112
# File 'lib/adlint/cc1/expr.rb', line 108

def visit_function_call_expression(node)
  checkpoint(node.location)
  args = node.argument_expressions.map { |expr| [expr.accept(self), expr] }
  eval_function_call_expr(node, node.expression.accept(self), args)
end

#visit_grouped_expression(node) ⇒ Object



97
98
99
100
# File 'lib/adlint/cc1/expr.rb', line 97

def visit_grouped_expression(node)
  checkpoint(node.location)
  node.expression.accept(self)
end

#visit_inclusive_or_expression(node) ⇒ Object



289
290
291
292
293
# File 'lib/adlint/cc1/expr.rb', line 289

def visit_inclusive_or_expression(node)
  checkpoint(node.location)
  eval_inclusive_or_expr(node, node.lhs_operand.accept(self),
                         node.rhs_operand.accept(self))
end

#visit_indirection_expression(node) ⇒ Object



164
165
166
167
# File 'lib/adlint/cc1/expr.rb', line 164

def visit_indirection_expression(node)
  checkpoint(node.location)
  eval_indirection_expr(node, node.operand.accept(self))
end

#visit_logical_and_expression(node) ⇒ Object



295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
# File 'lib/adlint/cc1/expr.rb', line 295

def visit_logical_and_expression(node)
  checkpoint(node.location)

  lhs_obj = node.lhs_operand.accept(self)
  if lhs_obj.variable?
    lhs_var = lhs_obj
  else
    return create_tmpvar(int_t)
  end

  # NOTE: The ISO C99 standard says;
  #
  # 6.5.13 Logical AND operator
  #
  # Semantics
  #
  # 4 Unlike the bitwise binary & operator, the && operator guarantees
  #   left-to-right evaluation; there is a sequence point after the
  #   evaluation of the first operand.  If the first operand compares equal
  #   to 0, the second operand is not evaluated.
  notify_sequence_point_reached(SequencePoint.new(node.lhs_operand))
  lhs_val = lhs_var.value

  if lhs_val.scalar? && lhs_val.test_must_be_false.true?
    # NOTE: Doing the short-circuit evaluation.
    notify_variable_value_referred(node, lhs_var)
    return create_tmpvar(int_t, scalar_value_of_false)
  end

  rhs_obj = node.rhs_operand.accept(self)
  if rhs_obj.variable?
    rhs_var = rhs_obj
  else
    return create_tmpvar(int_t)
  end

  notify_sequence_point_reached(SequencePoint.new(node.rhs_operand))
  rhs_val = rhs_var.value

  if lhs_val.scalar? && rhs_val.scalar?
    # NOTE: No usual-arithmetic-conversion.
    rslt_var = create_tmpvar(int_t, lhs_val.logical_and(rhs_val))
  else
    rslt_var = create_tmpvar(int_t)
  end
  notify_variable_value_referred(node, lhs_var)
  notify_variable_value_referred(node, rhs_var)

  notify_logical_and_expr_evaled(node, lhs_var, rhs_var, rslt_var)
  rslt_var
end

#visit_logical_or_expression(node) ⇒ Object



347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
# File 'lib/adlint/cc1/expr.rb', line 347

def visit_logical_or_expression(node)
  checkpoint(node.location)

  lhs_obj = node.lhs_operand.accept(self)
  if lhs_obj.variable?
    lhs_var = lhs_obj
  else
    return create_tmpvar(int_t)
  end

  # NOTE: The ISO C99 standard says;
  #
  # 6.5.14 Logical OR operator
  #
  # Semantics
  #
  # 4 Unlike the bitwise | operator, the || operator guarantees
  #   left-to-right evaluation; there is a sequence point after the
  #   evaluation of the first operand.  If the first operand compares
  #   unequal to 0, the second operand is not evaluated.
  notify_sequence_point_reached(SequencePoint.new(node.lhs_operand))
  lhs_val = lhs_var.value

  if lhs_val.scalar? && lhs_val.test_must_be_true.true?
    # NOTE: Doing the short-circuit evaluation.
    notify_variable_value_referred(node, lhs_var)
    return create_tmpvar(int_t, scalar_value_of_true)
  end

  rhs_obj = node.rhs_operand.accept(self)
  if rhs_obj.variable?
    rhs_var = rhs_obj
  else
    return create_tmpvar(int_t)
  end

  notify_sequence_point_reached(SequencePoint.new(node.rhs_operand))
  rhs_val = rhs_var.value

  if lhs_val.scalar? && rhs_val.scalar?
    # NOTE: No usual-arithmetic-conversion.
    rslt_var = create_tmpvar(int_t, lhs_val.logical_or(rhs_val))
  else
    rslt_var = create_tmpvar(int_t)
  end
  notify_variable_value_referred(node, lhs_var)
  notify_variable_value_referred(node, rhs_var)

  notify_logical_or_expr_evaled(node, lhs_var, rhs_var, rslt_var)
  rslt_var
end

#visit_member_access_by_pointer_expression(node) ⇒ Object



119
120
121
122
# File 'lib/adlint/cc1/expr.rb', line 119

def visit_member_access_by_pointer_expression(node)
  checkpoint(node.location)
  eval_member_access_by_pointer_expr(node,node.expression.accept(self))
end

#visit_member_access_by_value_expression(node) ⇒ Object



114
115
116
117
# File 'lib/adlint/cc1/expr.rb', line 114

def visit_member_access_by_value_expression(node)
  checkpoint(node.location)
  eval_member_access_by_value_expr(node, node.expression.accept(self))
end

#visit_multiplicative_expression(node) ⇒ Object



247
248
249
250
251
# File 'lib/adlint/cc1/expr.rb', line 247

def visit_multiplicative_expression(node)
  checkpoint(node.location)
  eval_multiplicative_expr(node, node.lhs_operand.accept(self),
                           node.rhs_operand.accept(self))
end

#visit_null_constant_specifier(node) ⇒ Object



90
91
92
93
94
95
# File 'lib/adlint/cc1/expr.rb', line 90

def visit_null_constant_specifier(node)
  checkpoint(node.location)
  rslt_var = create_tmpvar(pointer_type(void_t), scalar_value_of_null)
  notify_null_constant_specifier_evaled(node, rslt_var)
  rslt_var
end

#visit_object_specifier(node) ⇒ Object



53
54
55
56
# File 'lib/adlint/cc1/expr.rb', line 53

def visit_object_specifier(node)
  checkpoint(node.location)
  eval_object_specifier(node)
end

#visit_postfix_decrement_expression(node) ⇒ Object



139
140
141
142
# File 'lib/adlint/cc1/expr.rb', line 139

def visit_postfix_decrement_expression(node)
  checkpoint(node.location)
  eval_postfix_decrement_expr(node, node.operand.accept(self))
end

#visit_postfix_increment_expression(node) ⇒ Object



134
135
136
137
# File 'lib/adlint/cc1/expr.rb', line 134

def visit_postfix_increment_expression(node)
  checkpoint(node.location)
  eval_postfix_increment_expr(node, node.operand.accept(self))
end

#visit_prefix_decrement_expression(node) ⇒ Object



154
155
156
157
# File 'lib/adlint/cc1/expr.rb', line 154

def visit_prefix_decrement_expression(node)
  checkpoint(node.location)
  eval_prefix_decrement_expr(node, node.operand.accept(self))
end

#visit_prefix_increment_expression(node) ⇒ Object



149
150
151
152
# File 'lib/adlint/cc1/expr.rb', line 149

def visit_prefix_increment_expression(node)
  checkpoint(node.location)
  eval_prefix_increment_expr(node, node.operand.accept(self))
end

#visit_relational_expression(node) ⇒ Object



265
266
267
268
269
# File 'lib/adlint/cc1/expr.rb', line 265

def visit_relational_expression(node)
  checkpoint(node.location)
  eval_relational_expr(node, node.lhs_operand.accept(self),
                       node.rhs_operand.accept(self))
end

#visit_shift_expression(node) ⇒ Object



259
260
261
262
263
# File 'lib/adlint/cc1/expr.rb', line 259

def visit_shift_expression(node)
  checkpoint(node.location)
  eval_shift_expr(node, node.lhs_operand.accept(self),
                  node.rhs_operand.accept(self))
end

#visit_simple_assignment_expression(node) ⇒ Object



399
400
401
402
403
# File 'lib/adlint/cc1/expr.rb', line 399

def visit_simple_assignment_expression(node)
  checkpoint(node.location)
  eval_simple_assignment_expr(node, node.lhs_operand.accept(self),
                              node.rhs_operand.accept(self))
end

#visit_sizeof_expression(node) ⇒ Object



174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
# File 'lib/adlint/cc1/expr.rb', line 174

def visit_sizeof_expression(node)
  checkpoint(node.location)

  ope_obj = rslt_var = nil
  eval_quietly_without_side_effects do
    rslt_type = type_of(UserTypeId.new("size_t")) || unsigned_long_t
    ope_obj = node.operand.accept(self)
    if ope_obj.variable?
      size = ope_obj.type.aligned_byte_size
      rslt_var = create_tmpvar(rslt_type, scalar_value_of(size))
    else
      rslt_var = create_tmpvar(rslt_type)
    end
  end

  notify_sizeof_expr_evaled(node, ope_obj, rslt_var)
  rslt_var
end

#visit_sizeof_type_expression(node) ⇒ Object



193
194
195
196
197
198
199
200
201
202
203
204
205
206
# File 'lib/adlint/cc1/expr.rb', line 193

def visit_sizeof_type_expression(node)
  checkpoint(node.location)
  resolve_unresolved_type(node.operand)

  rslt_var = nil
  eval_quietly_without_side_effects do
    rslt_type = type_of(UserTypeId.new("size_t")) || unsigned_long_t
    size = node.operand.type.aligned_byte_size
    rslt_var = create_tmpvar(rslt_type, scalar_value_of(size))
  end

  notify_sizeof_type_expr_evaled(node, node.operand.type, rslt_var)
  rslt_var
end

#visit_string_literal_specifier(node) ⇒ Object



72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
# File 'lib/adlint/cc1/expr.rb', line 72

def visit_string_literal_specifier(node)
  checkpoint(node.location)

  case node.literal.value
  when /\A"(.*)"\z/
    rslt_var = create_tmpvar(array_type(char_t, $1.length + 1),
                             create_array_value_of_string($1))
  when /\AL"(.*)"\z/i
    rslt_var = create_tmpvar(array_type(wchar_t, $1.length + 1),
                             create_array_value_of_string($1))
  else
    rslt_var = create_tmpvar(array_type(char_t))
  end

  notify_string_literal_specifier_evaled(node, rslt_var)
  rslt_var
end

#visit_unary_arithmetic_expression(node) ⇒ Object



169
170
171
172
# File 'lib/adlint/cc1/expr.rb', line 169

def visit_unary_arithmetic_expression(node)
  checkpoint(node.location)
  eval_unary_arithmetic_expr(node, node.operand.accept(self))
end