adlint 3.0.4 → 3.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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