adlint 3.0.4 → 3.0.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (73) hide show
  1. data/ChangeLog +374 -13
  2. data/INSTALL +1 -3
  3. data/MANIFEST +12 -0
  4. data/NEWS +30 -4
  5. data/README +0 -4
  6. data/TODO +2 -1
  7. data/etc/mesg.d/c_builtin/en_US/messages.yml +2 -2
  8. data/etc/mesg.d/c_builtin/ja_JP/messages.yml +2 -2
  9. data/etc/mesg.d/core/en_US/messages.yml +5 -1
  10. data/etc/mesg.d/core/ja_JP/messages.yml +5 -1
  11. data/features/code_check/W0422.feature +128 -0
  12. data/features/code_check/W0491.feature +57 -0
  13. data/features/code_check/W0492.feature +80 -0
  14. data/features/code_check/W0542.feature +20 -0
  15. data/features/code_check/W0580.feature +25 -0
  16. data/features/code_check/W0610.feature +36 -0
  17. data/features/code_check/W0642.feature +67 -0
  18. data/features/code_check/W0786.feature +39 -0
  19. data/features/code_check/W0830.feature +27 -0
  20. data/features/code_check/W1047.feature +72 -0
  21. data/features/code_check/W9003.feature +22 -0
  22. data/features/code_extraction/TODO +1 -0
  23. data/features/metric_measurement/TODO +1 -0
  24. data/lib/adlint/analyzer.rb +2 -2
  25. data/lib/adlint/cc1/ctrlexpr.rb +27 -6
  26. data/lib/adlint/cc1/domain.rb +72 -12
  27. data/lib/adlint/cc1/enum.rb +4 -0
  28. data/lib/adlint/cc1/expr.rb +31 -29
  29. data/lib/adlint/cc1/interp.rb +45 -56
  30. data/lib/adlint/cc1/lexer.rb +26 -5
  31. data/lib/adlint/cc1/mediator.rb +35 -6
  32. data/lib/adlint/cc1/object.rb +62 -19
  33. data/lib/adlint/cc1/parser.rb +948 -904
  34. data/lib/adlint/cc1/parser.y +59 -29
  35. data/lib/adlint/cc1/phase.rb +6 -8
  36. data/lib/adlint/cc1/syntax.rb +70 -17
  37. data/lib/adlint/cc1/util.rb +4 -4
  38. data/lib/adlint/code.rb +16 -6
  39. data/lib/adlint/cpp/eval.rb +31 -25
  40. data/lib/adlint/cpp/lexer.rb +11 -5
  41. data/lib/adlint/cpp/macro.rb +34 -7
  42. data/lib/adlint/cpp/phase.rb +8 -8
  43. data/lib/adlint/error.rb +6 -0
  44. data/lib/adlint/exam/c_builtin/cc1_check.rb +557 -594
  45. data/lib/adlint/exam/c_builtin/cc1_check_shima.rb +72 -72
  46. data/lib/adlint/exam/c_builtin/cc1_code.rb +72 -52
  47. data/lib/adlint/exam/c_builtin/cc1_metric.rb +131 -131
  48. data/lib/adlint/exam/c_builtin/cpp_check.rb +48 -48
  49. data/lib/adlint/exam/c_builtin/cpp_check_shima.rb +2 -2
  50. data/lib/adlint/exam/c_builtin/cpp_code.rb +21 -21
  51. data/lib/adlint/exam/c_builtin/ld_check.rb +88 -87
  52. data/lib/adlint/exam/c_builtin/ld_metric.rb +4 -5
  53. data/lib/adlint/exam/c_builtin.rb +6 -6
  54. data/lib/adlint/ld/object.rb +269 -186
  55. data/lib/adlint/ld/phase.rb +19 -19
  56. data/lib/adlint/ld/typedef.rb +7 -7
  57. data/lib/adlint/ld/util.rb +25 -17
  58. data/lib/adlint/location.rb +6 -1
  59. data/lib/adlint/memo.rb +66 -13
  60. data/lib/adlint/prelude.rb +2 -2
  61. data/lib/adlint/report.rb +13 -14
  62. data/lib/adlint/util.rb +1 -1
  63. data/lib/adlint/version.rb +2 -2
  64. data/share/doc/Makefile +6 -2
  65. data/share/doc/c99gram.dot +502 -0
  66. data/share/doc/c99gram.pdf +0 -0
  67. data/share/doc/developers_guide_ja.html +4 -3
  68. data/share/doc/developers_guide_ja.texi +2 -1
  69. data/share/doc/users_guide_en.html +9 -9
  70. data/share/doc/users_guide_en.texi +7 -7
  71. data/share/doc/users_guide_ja.html +9 -9
  72. data/share/doc/users_guide_ja.texi +7 -7
  73. metadata +14 -2
@@ -42,57 +42,112 @@ module Cc1 #:nodoc:
42
42
  def equal_to(numeric, logical_shr)
43
43
  EqualToValueDomain.new(numeric, logical_shr)
44
44
  end
45
- memoize :equal_to
45
+ # NOTE: Value of #equal_to depends on the `logical_shr' parameter derived
46
+ # from the traits object.
47
+ # But the traits object is unique in an AdLint instance.
48
+ # So, it is safe to treat this method as unary method for improving
49
+ # the performance.
50
+ memoize :equal_to, key_indices: [0]
46
51
 
47
52
  def not_equal_to(numeric, logical_shr)
48
53
  equal_to(numeric, logical_shr).inversion
49
54
  end
50
- memoize :not_equal_to
55
+ # NOTE: Value of #not_equal_to depends on the `logical_shr' parameter
56
+ # derived from the traits object.
57
+ # But the traits object is unique in an AdLint instance.
58
+ # So, it is safe to treat this method as unary method for improving
59
+ # the performance.
60
+ memoize :not_equal_to, key_indices: [0]
51
61
 
52
62
  def less_than(numeric, logical_shr)
53
63
  LessThanValueDomain.new(numeric, logical_shr)
54
64
  end
55
- memoize :less_than
65
+ # NOTE: Value of #less_than depends on the `logical_shr' parameter derived
66
+ # from the traits object.
67
+ # But the traits object is unique in an AdLint instance.
68
+ # So, it is safe to treat this method as unary method for improving
69
+ # the performance.
70
+ memoize :less_than, key_indices: [0]
56
71
 
57
72
  def greater_than(numeric, logical_shr)
58
73
  GreaterThanValueDomain.new(numeric, logical_shr)
59
74
  end
60
- memoize :greater_than
75
+ # NOTE: Value of #greater_than depends on the `logical_shr' parameter
76
+ # derived from the traits object.
77
+ # But the traits object is unique in an AdLint instance.
78
+ # So, it is safe to treat this method as unary method for improving
79
+ # the performance.
80
+ memoize :greater_than, key_indices: [0]
61
81
 
62
82
  def less_than_or_equal_to(numeric, logical_shr)
63
83
  less_than(numeric, logical_shr).union(equal_to(numeric, logical_shr))
64
84
  end
65
- memoize :less_than_or_equal_to
85
+ # NOTE: Value of #less_than_or_equal_to depends on the `logical_shr'
86
+ # parameter derived from the traits object.
87
+ # But the traits object is unique in an AdLint instance.
88
+ # So, it is safe to treat this method as unary method for improving
89
+ # the performance.
90
+ memoize :less_than_or_equal_to, key_indices: [0]
66
91
 
67
92
  def greater_than_or_equal_to(numeric, logical_shr)
68
93
  greater_than(numeric, logical_shr).union(equal_to(numeric, logical_shr))
69
94
  end
70
- memoize :greater_than_or_equal_to
95
+ # NOTE: Value of #greater_than_or_equal_to depends on the `logical_shr'
96
+ # parameter derived from the traits object.
97
+ # But the traits object is unique in an AdLint instance.
98
+ # So, it is safe to treat this method as unary method for improving
99
+ # the performance.
100
+ memoize :greater_than_or_equal_to, key_indices: [0]
71
101
 
72
102
  def of_true(logical_shr)
73
103
  not_equal_to(0, logical_shr)
74
104
  end
75
- memoize :of_true
105
+ # NOTE: Value of #of_true depends on the `logical_shr' parameter derived
106
+ # from the traits object.
107
+ # But the traits object is unique in an AdLint instance.
108
+ # So, it is safe to treat this method as nullary method for improving
109
+ # the performance.
110
+ memoize :of_true, force_nullary: true
76
111
 
77
112
  def of_false(logical_shr)
78
113
  equal_to(0, logical_shr)
79
114
  end
80
- memoize :of_false
115
+ # NOTE: Value of #of_false depends on the `logical_shr' parameter derived
116
+ # from the traits object.
117
+ # But the traits object is unique in an AdLint instance.
118
+ # So, it is safe to treat this method as nullary method for improving
119
+ # the performance.
120
+ memoize :of_false, force_nullary: true
81
121
 
82
122
  def of_unlimited(logical_shr)
83
123
  UnlimitedValueDomain.new(logical_shr)
84
124
  end
85
- memoize :of_unlimited
125
+ # NOTE: Value of #of_unlimited depends on the `logical_shr' parameter
126
+ # derived from the traits object.
127
+ # But the traits object is unique in an AdLint instance.
128
+ # So, it is safe to treat this method as nullary method for improving
129
+ # the performance.
130
+ memoize :of_unlimited, force_nullary: true
86
131
 
87
132
  def of_nil(logical_shr)
88
133
  NilValueDomain.new(logical_shr)
89
134
  end
90
- memoize :of_nil
135
+ # NOTE: Value of #of_nil depends on the `logical_shr' parameter derived
136
+ # from the traits object.
137
+ # But the traits object is unique in an AdLint instance.
138
+ # So, it is safe to treat this method as nullary method for improving
139
+ # the performance.
140
+ memoize :of_nil, force_nullary: true
91
141
 
92
142
  def of_nan(logical_shr)
93
143
  NaN.new(logical_shr)
94
144
  end
95
- memoize :of_nan
145
+ # NOTE: Value of #of_nan depends on the `logical_shr' parameter derived
146
+ # from the traits object.
147
+ # But the traits object is unique in an AdLint instance.
148
+ # So, it is safe to treat this method as nullary method for improving
149
+ # the performance.
150
+ memoize :of_nan, force_nullary: true
96
151
 
97
152
  def of_intersection(lhs_dom, rhs_dom)
98
153
  case lhs_dom
@@ -168,7 +223,12 @@ module Cc1 #:nodoc:
168
223
  def of_ambiguous(undefined, logical_shr)
169
224
  AmbiguousValueDomain.new(undefined, logical_shr)
170
225
  end
171
- memoize :of_ambiguous
226
+ # NOTE: Value of #of_ambiguous depends on the `logical_shr' parameter
227
+ # derived from the traits object.
228
+ # But the traits object is unique in an AdLint instance.
229
+ # So, it is safe to treat this method as unary method for improving
230
+ # the performance.
231
+ memoize :of_ambiguous, key_indices: [0]
172
232
 
173
233
  def _create_intersection(lhs_dom, rhs_dom)
174
234
  expected = lhs_dom.complexity + rhs_dom.complexity
@@ -44,6 +44,10 @@ module Cc1 #:nodoc:
44
44
  def lookup(name_str)
45
45
  @enumerators[name_str]
46
46
  end
47
+
48
+ def designators
49
+ @enumerators.keys.to_set
50
+ end
47
51
  end
48
52
 
49
53
  end
@@ -550,7 +550,9 @@ module Cc1 #:nodoc:
550
550
  }
551
551
 
552
552
  unless fun.builtin?
553
- arg_vars = args.map { |arg_obj, *| object_to_variable(arg_obj) }
553
+ arg_vars = args.map { |arg_obj, arg_expr|
554
+ object_to_variable(arg_obj, arg_expr)
555
+ }
554
556
  notify_function_call_expr_evaled(node, fun, arg_vars, res_var)
555
557
  end
556
558
 
@@ -627,7 +629,7 @@ module Cc1 #:nodoc:
627
629
  end
628
630
 
629
631
  def eval_postfix_increment_expr(node, obj)
630
- var = object_to_variable(obj)
632
+ var = object_to_variable(obj, node)
631
633
  if !var.type.scalar? && !var.type.void?
632
634
  # NOTE: To detect bad value reference of `void' expressions.
633
635
  return create_tmpvar
@@ -650,7 +652,7 @@ module Cc1 #:nodoc:
650
652
  end
651
653
 
652
654
  def eval_postfix_decrement_expr(node, obj)
653
- var = object_to_variable(obj)
655
+ var = object_to_variable(obj, node)
654
656
  if !var.type.scalar? && !var.type.void?
655
657
  # NOTE: To detect bad value reference of `void' expressions.
656
658
  return create_tmpvar
@@ -673,7 +675,7 @@ module Cc1 #:nodoc:
673
675
  end
674
676
 
675
677
  def eval_prefix_increment_expr(node, obj)
676
- var = object_to_variable(obj)
678
+ var = object_to_variable(obj, node)
677
679
  if !var.type.scalar? && !var.type.void?
678
680
  # NOTE: To detect bad value reference of `void' expressions.
679
681
  return create_tmpvar
@@ -696,7 +698,7 @@ module Cc1 #:nodoc:
696
698
  end
697
699
 
698
700
  def eval_prefix_decrement_expr(node, obj)
699
- var = object_to_variable(obj)
701
+ var = object_to_variable(obj, node)
700
702
  if !var.type.scalar? && !var.type.void?
701
703
  # NOTE: To detect bad value reference of `void' expressions.
702
704
  return create_tmpvar
@@ -724,13 +726,13 @@ module Cc1 #:nodoc:
724
726
  # variable cross-references.
725
727
  _notify_variable_value_referred(node, obj)
726
728
 
727
- ptr = create_tmpvar(pointer_type(obj.type), pointer_value_of(obj))
729
+ ptr = object_to_pointer(obj, node)
728
730
  notify_address_expr_evaled(node, obj, ptr)
729
731
  ptr
730
732
  end
731
733
 
732
734
  def eval_indirection_expr(node, obj)
733
- var = object_to_variable(obj)
735
+ var = object_to_variable(obj, node)
734
736
  if var.type.pointer?
735
737
  ptr = var
736
738
  else
@@ -768,7 +770,7 @@ module Cc1 #:nodoc:
768
770
  end
769
771
 
770
772
  def eval_unary_arithmetic_expr(node, obj)
771
- var = object_to_variable(obj)
773
+ var = object_to_variable(obj, node)
772
774
  if !var.type.scalar? && !var.type.void?
773
775
  # NOTE: To detect bad value reference of `void' expressions.
774
776
  return create_tmpvar
@@ -795,7 +797,7 @@ module Cc1 #:nodoc:
795
797
  def eval_cast_expr(node, obj)
796
798
  resolve_unresolved_type(node.type_name)
797
799
 
798
- var = object_to_variable(obj)
800
+ var = object_to_variable(obj, node)
799
801
  res_var = do_conversion(var, node.type_name.type) ||
800
802
  create_tmpvar(node.type_name.type)
801
803
 
@@ -810,13 +812,13 @@ module Cc1 #:nodoc:
810
812
  end
811
813
 
812
814
  def eval_multiplicative_expr(node, lhs_obj, rhs_obj)
813
- lhs_var = object_to_variable(lhs_obj)
815
+ lhs_var = object_to_variable(lhs_obj, node.lhs_operand)
814
816
  if !lhs_var.type.scalar? && !lhs_var.type.void?
815
817
  # NOTE: To detect bad value reference of `void' expressions.
816
818
  return create_tmpvar
817
819
  end
818
820
 
819
- rhs_var = object_to_variable(rhs_obj)
821
+ rhs_var = object_to_variable(rhs_obj, node.rhs_operand)
820
822
  if !rhs_var.type.scalar? && !rhs_var.type.void?
821
823
  # NOTE: To detect bad value reference of `void' expressions.
822
824
  return create_tmpvar
@@ -863,13 +865,13 @@ module Cc1 #:nodoc:
863
865
  end
864
866
 
865
867
  def eval_additive_expr(node, lhs_obj, rhs_obj)
866
- lhs_var = object_to_variable(lhs_obj)
868
+ lhs_var = object_to_variable(lhs_obj, node.lhs_operand)
867
869
  if !lhs_var.type.scalar? && !lhs_var.type.void?
868
870
  # NOTE: To detect bad value reference of `void' expressions.
869
871
  return create_tmpvar
870
872
  end
871
873
 
872
- rhs_var = object_to_variable(rhs_obj)
874
+ rhs_var = object_to_variable(rhs_obj, node.rhs_operand)
873
875
  if !rhs_var.type.scalar? && !rhs_var.type.void?
874
876
  # NOTE: To detect bad value reference of `void' expressions.
875
877
  return create_tmpvar
@@ -908,13 +910,13 @@ module Cc1 #:nodoc:
908
910
  end
909
911
 
910
912
  def eval_shift_expr(node, lhs_obj, rhs_obj)
911
- lhs_var = object_to_variable(lhs_obj)
913
+ lhs_var = object_to_variable(lhs_obj, node.lhs_operand)
912
914
  if !lhs_var.type.scalar? && !lhs_var.type.void?
913
915
  # NOTE: To detect bad value reference of `void' expressions.
914
916
  return create_tmpvar
915
917
  end
916
918
 
917
- rhs_var = object_to_variable(rhs_obj)
919
+ rhs_var = object_to_variable(rhs_obj, node.rhs_operand)
918
920
  if !rhs_var.type.scalar? && !rhs_var.type.void?
919
921
  # NOTE: To detect bad value reference of `void' expressions.
920
922
  return create_tmpvar
@@ -963,13 +965,13 @@ module Cc1 #:nodoc:
963
965
  end
964
966
 
965
967
  def eval_relational_expr(node, lhs_obj, rhs_obj)
966
- lhs_var = object_to_variable(lhs_obj)
968
+ lhs_var = object_to_variable(lhs_obj, node.lhs_operand)
967
969
  if !lhs_var.type.scalar? && !lhs_var.type.void?
968
970
  # NOTE: To detect bad value reference of `void' expressions.
969
971
  return create_tmpvar(int_t, scalar_value_of_arbitrary)
970
972
  end
971
973
 
972
- rhs_var = object_to_variable(rhs_obj)
974
+ rhs_var = object_to_variable(rhs_obj, node.rhs_operand)
973
975
  if !rhs_var.type.scalar? && !rhs_var.type.void?
974
976
  # NOTE: To detect bad value reference of `void' expressions.
975
977
  return create_tmpvar(int_t, scalar_value_of_arbitrary)
@@ -1008,13 +1010,13 @@ module Cc1 #:nodoc:
1008
1010
  end
1009
1011
 
1010
1012
  def eval_equality_expr(node, lhs_obj, rhs_obj)
1011
- lhs_var = object_to_variable(lhs_obj)
1013
+ lhs_var = object_to_variable(lhs_obj, node.lhs_operand)
1012
1014
  if !lhs_var.type.scalar? && !lhs_var.type.void?
1013
1015
  # NOTE: To detect bad value reference of `void' expressions.
1014
1016
  return create_tmpvar(int_t, scalar_value_of_arbitrary)
1015
1017
  end
1016
1018
 
1017
- rhs_var = object_to_variable(rhs_obj)
1019
+ rhs_var = object_to_variable(rhs_obj, node.rhs_operand)
1018
1020
  if !rhs_var.type.scalar? && !rhs_var.type.void?
1019
1021
  # NOTE: To detect bad value reference of `void' expressions.
1020
1022
  return create_tmpvar(int_t, scalar_value_of_arbitrary)
@@ -1049,13 +1051,13 @@ module Cc1 #:nodoc:
1049
1051
  end
1050
1052
 
1051
1053
  def eval_and_expr(node, lhs_obj, rhs_obj)
1052
- lhs_var = object_to_variable(lhs_obj)
1054
+ lhs_var = object_to_variable(lhs_obj, node.lhs_operand)
1053
1055
  if !lhs_var.type.scalar? && !lhs_var.type.void?
1054
1056
  # NOTE: To detect bad value reference of `void' expressions.
1055
1057
  return create_tmpvar
1056
1058
  end
1057
1059
 
1058
- rhs_var = object_to_variable(rhs_obj)
1060
+ rhs_var = object_to_variable(rhs_obj, node.rhs_operand)
1059
1061
  if !rhs_var.type.scalar? && !rhs_var.type.void?
1060
1062
  # NOTE: To detect bad value reference of `void' expressions.
1061
1063
  return create_tmpvar
@@ -1085,13 +1087,13 @@ module Cc1 #:nodoc:
1085
1087
  end
1086
1088
 
1087
1089
  def eval_exclusive_or_expr(node, lhs_obj, rhs_obj)
1088
- lhs_var = object_to_variable(lhs_obj)
1090
+ lhs_var = object_to_variable(lhs_obj, node.lhs_operand)
1089
1091
  if !lhs_var.type.scalar? && !lhs_var.type.void?
1090
1092
  # NOTE: To detect bad value reference of `void' expressions.
1091
1093
  return create_tmpvar
1092
1094
  end
1093
1095
 
1094
- rhs_var = object_to_variable(rhs_obj)
1096
+ rhs_var = object_to_variable(rhs_obj, node.rhs_operand)
1095
1097
  if !rhs_var.type.scalar? && !rhs_var.type.void?
1096
1098
  # NOTE: To detect bad value reference of `void' expressions.
1097
1099
  return create_tmpvar
@@ -1121,13 +1123,13 @@ module Cc1 #:nodoc:
1121
1123
  end
1122
1124
 
1123
1125
  def eval_inclusive_or_expr(node, lhs_obj, rhs_obj)
1124
- lhs_var = object_to_variable(lhs_obj)
1126
+ lhs_var = object_to_variable(lhs_obj, node.lhs_operand)
1125
1127
  if !lhs_var.type.scalar? && !lhs_var.type.void?
1126
1128
  # NOTE: To detect bad value reference of `void' expressions.
1127
1129
  return create_tmpvar
1128
1130
  end
1129
1131
 
1130
- rhs_var = object_to_variable(rhs_obj)
1132
+ rhs_var = object_to_variable(rhs_obj, node.rhs_operand)
1131
1133
  if !rhs_var.type.scalar? && !rhs_var.type.void?
1132
1134
  # NOTE: To detect bad value reference of `void' expressions.
1133
1135
  return create_tmpvar
@@ -1157,8 +1159,8 @@ module Cc1 #:nodoc:
1157
1159
  end
1158
1160
 
1159
1161
  def eval_simple_assignment_expr(node, lhs_obj, rhs_obj)
1160
- lhs_var = object_to_variable(lhs_obj)
1161
- rhs_var = object_to_variable(rhs_obj)
1162
+ lhs_var = object_to_variable(lhs_obj, node.lhs_operand)
1163
+ rhs_var = object_to_variable(rhs_obj, node.rhs_operand)
1162
1164
 
1163
1165
  if rhs_var.type.same_as?(lhs_var.type)
1164
1166
  rhs_conved = rhs_var
@@ -1182,13 +1184,13 @@ module Cc1 #:nodoc:
1182
1184
  end
1183
1185
 
1184
1186
  def eval_compound_assignment_expr(node, lhs_obj, rhs_obj)
1185
- lhs_var = object_to_variable(lhs_obj)
1187
+ lhs_var = object_to_variable(lhs_obj, node.lhs_operand)
1186
1188
  if !lhs_var.type.scalar? && !lhs_var.type.void?
1187
1189
  # NOTE: To detect bad value reference of `void' expressions.
1188
1190
  return lhs_obj
1189
1191
  end
1190
1192
 
1191
- rhs_var = object_to_variable(rhs_obj)
1193
+ rhs_var = object_to_variable(rhs_obj, node.rhs_operand)
1192
1194
  if !rhs_var.type.scalar? && !rhs_var.type.void?
1193
1195
  # NOTE: To detect bad value reference of `void' expressions.
1194
1196
  return lhs_var
@@ -191,11 +191,17 @@ module Cc1 #:nodoc:
191
191
  # NOTE: Notified when the interpreter evaluates a cast-expression.
192
192
  def_plugin_and_notifier :explicit_conv_performed, :expr, :org_var, :res_var
193
193
 
194
- # NOTE: Notified when the interpreter performs an implicit type conversion
195
- # while evaluating an expression.
194
+ # NOTE: Notified when the interpreter performs an implicit conversion while
195
+ # evaluating an expression.
196
196
  def_plugin_and_notifier :implicit_conv_performed,
197
197
  :init_or_expr, :org_var, :res_var
198
198
 
199
+ # NOTE: Notified when the interpreter performs an address derivation while
200
+ # address-expression evaluation and array or function address
201
+ # derivation.
202
+ def_plugin_and_notifier :address_derivation_performed,
203
+ :init_or_expr, :obj, :ptr
204
+
199
205
  # NOTE: Notified when the interpreter evaluates an
200
206
  # array-subscript-expression.
201
207
  def_plugin_and_notifier :array_subscript_expr_evaled,
@@ -427,37 +433,6 @@ module Cc1 #:nodoc:
427
433
  @options_stack.pop
428
434
  end
429
435
 
430
- def object_to_variable(obj)
431
- case
432
- when obj.function?
433
- function_to_pointer(obj)
434
- when obj.variable? && obj.type.array?
435
- array_to_pointer(obj)
436
- else
437
- obj
438
- end
439
- end
440
-
441
- def function_to_pointer(fun)
442
- create_tmpvar(pointer_type(fun.type), pointer_value_of(fun))
443
- end
444
-
445
- def array_to_pointer(ary)
446
- create_tmpvar(pointer_type(ary.type.base_type), pointer_value_of(ary))
447
- end
448
-
449
- def value_of(obj)
450
- if obj.type.array? || obj.type.function?
451
- pointer_value_of(obj)
452
- else
453
- obj.value.to_single_value
454
- end
455
- end
456
-
457
- def pointer_value_of(obj)
458
- scalar_value_of(obj.binding.memory.address)
459
- end
460
-
461
436
  def quiet?
462
437
  cur_opts.include?(QUIET) || cur_opts.include?(QUIET_WITHOUT_SIDE_EFFECT)
463
438
  end
@@ -592,8 +567,20 @@ module Cc1 #:nodoc:
592
567
  end
593
568
 
594
569
  if node.initializer
595
- init_var, init_conved = evaluate_initializer(node)
596
- var = define_variable(node, init_conved.value.to_defined_value)
570
+ if node.type.incomplete?
571
+ # NOTE: Unable to define variable of incomplete type such as an array
572
+ # without length.
573
+ init_var, init_conved = evaluate_initializer(node)
574
+ var = define_variable(node, init_conved.value.to_defined_value)
575
+ else
576
+ # NOTE: Define variable first in order to correctly evaluate
577
+ # sizeof-expression that refers to the defining variable in the
578
+ # initializer.
579
+ define_variable(node) unless variable_named(node.identifier.value)
580
+ init_var, init_conved = evaluate_initializer(node)
581
+ var = define_variable(node, init_conved.value.to_defined_value)
582
+ end
583
+
597
584
  notify_variable_value_referred(node, init_var)
598
585
  notify_variable_defined(node, var)
599
586
  notify_variable_initialized(node, var, init_var)
@@ -736,9 +723,7 @@ module Cc1 #:nodoc:
736
723
  def evaluate_expression(expr, type)
737
724
  checkpoint(expr.location)
738
725
 
739
- obj = interpret(expr)
740
- var = object_to_variable(obj)
741
- notify_implicit_conv_performed(expr, obj, var) unless var == obj
726
+ var = object_to_variable(interpret(expr), expr)
742
727
 
743
728
  if var.type.same_as?(type)
744
729
  conved = var
@@ -969,7 +954,7 @@ module Cc1 #:nodoc:
969
954
 
970
955
  node.executed = true
971
956
  ctrlexpr = node.expression
972
- ctrlexpr_var = object_to_variable(interpret(ctrlexpr, QUIET))
957
+ ctrlexpr_var = object_to_variable(interpret(ctrlexpr, QUIET), ctrlexpr)
973
958
  notify_case_ctrlexpr_evaled(node, ctrlexpr_var)
974
959
 
975
960
  interpret(node.statement)
@@ -1017,7 +1002,8 @@ module Cc1 #:nodoc:
1017
1002
  ctrlexpr_val = scalar_value_of_arbitrary
1018
1003
  ctrlexpr = nil
1019
1004
  else
1020
- ctrlexpr_var = object_to_variable(interpret(org_ctrlexpr))
1005
+ ctrlexpr_var = object_to_variable(interpret(org_ctrlexpr),
1006
+ org_ctrlexpr)
1021
1007
  ctrlexpr_val = value_of(ctrlexpr_var)
1022
1008
  notify_variable_value_referred(org_ctrlexpr, ctrlexpr_var)
1023
1009
  notify_sequence_point_reached(SequencePoint.new(org_ctrlexpr))
@@ -1050,7 +1036,8 @@ module Cc1 #:nodoc:
1050
1036
  ctrlexpr_val = scalar_value_of_arbitrary
1051
1037
  ctrlexpr = nil
1052
1038
  else
1053
- ctrlexpr_var = object_to_variable(interpret(org_ctrlexpr))
1039
+ ctrlexpr_var = object_to_variable(interpret(org_ctrlexpr),
1040
+ org_ctrlexpr)
1054
1041
  ctrlexpr_val = value_of(ctrlexpr_var)
1055
1042
  notify_variable_value_referred(org_ctrlexpr, ctrlexpr_var)
1056
1043
  notify_sequence_point_reached(SequencePoint.new(org_ctrlexpr))
@@ -1088,7 +1075,8 @@ module Cc1 #:nodoc:
1088
1075
 
1089
1076
  widen_varying_variable_value_domain(node)
1090
1077
 
1091
- ctrlexpr_var = object_to_variable(interpret(node.expression))
1078
+ ctrlexpr_var = object_to_variable(interpret(node.expression),
1079
+ node.expression)
1092
1080
  ctrlexpr_val = value_of(ctrlexpr_var)
1093
1081
  notify_variable_value_referred(node.expression, ctrlexpr_var)
1094
1082
  notify_sequence_point_reached(SequencePoint.new(node.expression))
@@ -1139,7 +1127,8 @@ module Cc1 #:nodoc:
1139
1127
  leave_iteration_statement(org_ctrlexpr)
1140
1128
  end
1141
1129
 
1142
- ctrlexpr_var = object_to_variable(interpret(node.expression))
1130
+ ctrlexpr_var = object_to_variable(interpret(node.expression),
1131
+ node.expression)
1143
1132
  ctrlexpr_val = value_of(ctrlexpr_var)
1144
1133
  notify_variable_value_referred(node.expression, ctrlexpr_var)
1145
1134
  notify_sequence_point_reached(SequencePoint.new(node.expression))
@@ -1161,7 +1150,8 @@ module Cc1 #:nodoc:
1161
1150
 
1162
1151
  node.condition_statement.executed = true
1163
1152
  if explicit_ctrlexpr = node.condition_statement.expression
1164
- ctrlexpr_var = object_to_variable(interpret(explicit_ctrlexpr))
1153
+ ctrlexpr_var = object_to_variable(interpret(explicit_ctrlexpr),
1154
+ explicit_ctrlexpr)
1165
1155
  ctrlexpr_val = value_of(ctrlexpr_var)
1166
1156
  notify_variable_value_referred(explicit_ctrlexpr, ctrlexpr_var)
1167
1157
  notify_sequence_point_reached(SequencePoint.new(explicit_ctrlexpr))
@@ -1194,7 +1184,8 @@ module Cc1 #:nodoc:
1194
1184
 
1195
1185
  node.condition_statement.executed = true
1196
1186
  if explicit_ctrlexpr = node.condition_statement.expression
1197
- ctrlexpr_var = object_to_variable(interpret(explicit_ctrlexpr))
1187
+ ctrlexpr_var = object_to_variable(interpret(explicit_ctrlexpr),
1188
+ explicit_ctrlexpr)
1198
1189
  ctrlexpr_val = value_of(ctrlexpr_var)
1199
1190
  notify_variable_value_referred(explicit_ctrlexpr, ctrlexpr_var)
1200
1191
  notify_sequence_point_reached(SequencePoint.new(explicit_ctrlexpr))
@@ -1246,12 +1237,7 @@ module Cc1 #:nodoc:
1246
1237
  BreakEvent.of_return.throw
1247
1238
  end
1248
1239
 
1249
- obj = interpret(node.expression)
1250
- var = object_to_variable(obj)
1251
- unless var == obj
1252
- notify_implicit_conv_performed(node.expression, obj, var)
1253
- end
1254
-
1240
+ var = object_to_variable(interpret(node.expression), node.expression)
1255
1241
  notify_variable_value_referred(node.expression, var)
1256
1242
 
1257
1243
  if active_fun = interpreter._active_function and
@@ -1296,7 +1282,8 @@ module Cc1 #:nodoc:
1296
1282
  # causes "logical-expression must be false" warnings about a
1297
1283
  # one-time-for-loop. To avoid this, now, workarounds are in
1298
1284
  # builtin code checks W0609 and W0610.
1299
- var = object_to_variable(interpret(explicit_ctrlexpr))
1285
+ var = object_to_variable(interpret(explicit_ctrlexpr),
1286
+ explicit_ctrlexpr)
1300
1287
  notify_variable_value_referred(explicit_ctrlexpr, var)
1301
1288
  notify_sequence_point_reached(SequencePoint.new(explicit_ctrlexpr))
1302
1289
  end
@@ -1440,7 +1427,7 @@ module Cc1 #:nodoc:
1440
1427
  notify_switch_stmt_started(node)
1441
1428
 
1442
1429
  ctrlexpr = node.expression
1443
- ctrlexpr_var = object_to_variable(interpret(ctrlexpr))
1430
+ ctrlexpr_var = object_to_variable(interpret(ctrlexpr), ctrlexpr)
1444
1431
  notify_switch_ctrlexpr_evaled(node, ctrlexpr_var)
1445
1432
  notify_variable_value_referred(ctrlexpr, ctrlexpr_var)
1446
1433
 
@@ -1693,7 +1680,7 @@ module Cc1 #:nodoc:
1693
1680
  checkpoint(node.location)
1694
1681
 
1695
1682
  ctrlexpr = node.condition
1696
- ctrlexpr_var = object_to_variable(interpret(ctrlexpr))
1683
+ ctrlexpr_var = object_to_variable(interpret(ctrlexpr), ctrlexpr)
1697
1684
  ctrlexpr_val = value_of(ctrlexpr_var)
1698
1685
  notify_variable_value_referred(ctrlexpr, ctrlexpr_var)
1699
1686
  notify_sequence_point_reached(ctrlexpr.subsequent_sequence_point)
@@ -1702,14 +1689,16 @@ module Cc1 #:nodoc:
1702
1689
  then_var = nil
1703
1690
  if ctrlexpr_val.may_be_true?
1704
1691
  branched_eval(ctrlexpr, NARROWING, IMPLICIT_COND) do
1705
- then_var = object_to_variable(interpret(node.then_expression))
1692
+ then_var = object_to_variable(interpret(node.then_expression),
1693
+ node.then_expression)
1706
1694
  end
1707
1695
  end
1708
1696
 
1709
1697
  else_var = nil
1710
1698
  if ctrlexpr_val.may_be_false?
1711
1699
  branched_eval(nil, NARROWING, FINAL, COMPLETE) do
1712
- else_var = object_to_variable(interpret(node.else_expression))
1700
+ else_var = object_to_variable(interpret(node.else_expression),
1701
+ node.else_expression)
1713
1702
  end
1714
1703
  else
1715
1704
  branched_eval(nil, NARROWING, FINAL, COMPLETE) {}
@@ -69,11 +69,11 @@ module Cc1 #:nodoc:
69
69
  @object_names.leave_scope
70
70
  end
71
71
 
72
- def start_identifier_translation
72
+ def enable_identifier_translation
73
73
  @identifier_translation = true
74
74
  end
75
75
 
76
- def stop_identifier_translation
76
+ def disable_identifier_translation
77
77
  @identifier_translation = false
78
78
  end
79
79
 
@@ -119,14 +119,35 @@ module Cc1 #:nodoc:
119
119
  end
120
120
 
121
121
  def translate_identifier(tok, lexer_ctxt)
122
+ # NOTE: To translate given IDENTIFIER into TYPEDEF_NAME if needed.
123
+
124
+ # NOTE: The ISO C99 standard says;
125
+ #
126
+ # 6.2.3 Name spaces of identifiers
127
+ #
128
+ # 1 If more than one declaration of a particular identifier is visible at
129
+ # any point in a translation unit, the syntactic context disambiguates
130
+ # uses that refer to different entities. Thus, there are separate name
131
+ # spaces for various categories of identifiers, as follows:
132
+ # -- label names (disambiguated by the syntax of the label declaration
133
+ # and use);
134
+ # -- the tags of structures, unions, and enumerations (disambiguated by
135
+ # following any of the keywords struct, union, or enum);
136
+ # -- the members of structures or unions; each structure or union has a
137
+ # separate name space for its members (disambiguated by the type of
138
+ # the expression used to access the member via the . or ->
139
+ # operator);
140
+ # -- all other identifiers, called ordinary identifiers (declared in
141
+ # ordinary declarators or as enumeration constants).
142
+
122
143
  if @identifier_translation
123
144
  if tok.type == :IDENTIFIER
124
145
  return tok if @object_names.include?(tok.value)
125
146
  if @typedef_names.include?(tok.value)
126
147
  unless @lst_tok and
127
- @lst_tok.type == :STRUCT || @lst_tok.type == :UNION ||
128
- @lst_tok.type == :ENUM ||
129
- @lst_tok.type == "->" || @lst_tok.type == "."
148
+ @lst_tok.type == :STRUCT || @lst_tok.type == :UNION ||
149
+ @lst_tok.type == :ENUM ||
150
+ @lst_tok.type == "->" || @lst_tok.type == "."
130
151
  tok = tok.class.new(:TYPEDEF_NAME, tok.value, tok.location)
131
152
  end
132
153
  end