adlint 2.4.10 → 2.6.0

Sign up to get free protection for your applications and to get access to all the features.
data/lib/adlint/c/type.rb CHANGED
@@ -5080,7 +5080,7 @@ module C #:nodoc:
5080
5080
  rhs_base = rhs_unqualified.base_type
5081
5081
 
5082
5082
  unless lhs_base.more_cv_qualified?(rhs_base)
5083
- lhs_base.void? || lhs_base.convertible?(rhs_base)
5083
+ rhs_base.void? || lhs_base.convertible?(rhs_base)
5084
5084
  else
5085
5085
  false
5086
5086
  end
@@ -5555,7 +5555,7 @@ module C #:nodoc:
5555
5555
  rhs_base = rhs_unqualified.base_type
5556
5556
 
5557
5557
  unless lhs_base.more_cv_qualified?(rhs_base)
5558
- lhs_base.convertible?(rhs_base)
5558
+ rhs_base.void? || lhs_base.convertible?(rhs_base)
5559
5559
  else
5560
5560
  false
5561
5561
  end
@@ -6741,7 +6741,11 @@ module C #:nodoc:
6741
6741
  extend Forwardable
6742
6742
 
6743
6743
  def_delegator :@base_type, :image
6744
- def_delegator :@base_type, :brief_image
6744
+
6745
+ def brief_image
6746
+ name
6747
+ end
6748
+
6745
6749
  def_delegator :@base_type, :bit_size
6746
6750
  def_delegator :@base_type, :bit_alignment
6747
6751
  def_delegator :@base_type, :real_type
@@ -6911,6 +6915,8 @@ module C #:nodoc:
6911
6915
  def_delegator :@type, :incomplete?
6912
6916
  def_delegator :@type, :compatible?
6913
6917
  def_delegator :@type, :coercible?
6918
+ def_delegator :@type, :convertible?
6919
+ def_delegator :@type, :more_cv_qualified?
6914
6920
 
6915
6921
  def parameter?
6916
6922
  true
@@ -6942,6 +6948,7 @@ module C #:nodoc:
6942
6948
  def_delegator :@type, :parameter_types
6943
6949
  def_delegator :@type, :enumerators
6944
6950
  def_delegator :@type, :length
6951
+ def_delegator :@type, :length=
6945
6952
  def_delegator :@type, :impl_length
6946
6953
  def_delegator :@type, :members
6947
6954
  def_delegator :@type, :member_named
@@ -39,6 +39,7 @@ require "adlint/c/syntax"
39
39
  require "adlint/c/type"
40
40
  require "adlint/c/format"
41
41
  require "adlint/c/option"
42
+ require "adlint/c/conv"
42
43
  require "adlint/c/util"
43
44
  require "adlint/cpp/syntax"
44
45
 
@@ -1818,29 +1819,34 @@ module CBuiltin #:nodoc:
1818
1819
 
1819
1820
  def initialize(context)
1820
1821
  super
1821
- visitor = context[:c_visitor]
1822
- visitor.enter_expression_statement += method(:enter_expression_statement)
1823
- visitor.leave_expression_statement += method(:leave_expression_statement)
1824
- visitor.enter_logical_and_expression += method(:check)
1825
- visitor.enter_logical_or_expression += method(:check)
1826
- @in_expression_statement = false
1822
+ interp = context[:c_interpreter]
1823
+ interp.on_expression_stmt_started += method(:enter_expression_statement)
1824
+ interp.on_expression_stmt_ended += method(:leave_expression_statement)
1825
+ interp.on_logical_and_expr_evaled += method(:check)
1826
+ interp.on_logical_or_expr_evaled += method(:check)
1827
+ @current_expr_stmt = nil
1827
1828
  end
1828
1829
 
1829
1830
  private
1830
- def enter_expression_statement(node)
1831
- @in_expression_statement = true
1831
+ def enter_expression_statement(expr_stmt)
1832
+ case expr_stmt.expression
1833
+ when C::SimpleAssignmentExpression, C::CompoundAssignmentExpression,
1834
+ C::FunctionCallExpression
1835
+ @current_expr_stmt = nil
1836
+ else
1837
+ @current_expr_stmt = expr_stmt
1838
+ end
1832
1839
  end
1833
1840
 
1834
- def leave_expression_statement(node)
1835
- @in_expression_statement = false
1841
+ def leave_expression_statement(*)
1842
+ @current_expr_stmt = nil
1836
1843
  end
1837
1844
 
1838
- def check(node)
1839
- if @in_expression_statement
1840
- unless node.rhs_operand.have_side_effect?
1841
- W(:W0088, node.operator.location)
1845
+ def check(binary_expr, *)
1846
+ if @current_expr_stmt
1847
+ unless binary_expr.rhs_operand.have_side_effect?
1848
+ W(:W0088, binary_expr.operator.location)
1842
1849
  end
1843
- @in_expression_statement = false
1844
1850
  end
1845
1851
  end
1846
1852
  end
@@ -2023,7 +2029,7 @@ module CBuiltin #:nodoc:
2023
2029
  if rhs_pointee = @interp.pointee_of(rhs_variable)
2024
2030
  if rhs_pointee.variable? && rhs_pointee.named?
2025
2031
  return unless rhs_pointee.binding.memory.dynamic?
2026
- # NOTE: An array typed parameter can be considerd as an alias of the
2032
+ # NOTE: An array typed parameter can be considered as an alias of the
2027
2033
  # corresponding argument. So, it is safe to return an address
2028
2034
  # of the argument.
2029
2035
  return if rhs_pointee.type.parameter? && rhs_pointee.type.array?
@@ -2092,7 +2098,7 @@ module CBuiltin #:nodoc:
2092
2098
  if rhs_pointee = @interp.pointee_of(rhs_variable)
2093
2099
  if rhs_pointee.variable? && rhs_pointee.named?
2094
2100
  return unless rhs_pointee.binding.memory.dynamic?
2095
- # NOTE: An array typed parameter can be considerd as an alias of the
2101
+ # NOTE: An array typed parameter can be considered as an alias of the
2096
2102
  # corresponding argument. So, it is safe to return an address
2097
2103
  # of the argument.
2098
2104
  return if rhs_pointee.type.parameter? && rhs_pointee.type.array?
@@ -2140,7 +2146,7 @@ module CBuiltin #:nodoc:
2140
2146
 
2141
2147
  if pointee = @interp.pointee_of(result_variable)
2142
2148
  if pointee.variable? && pointee.named?
2143
- # NOTE: An array typed parameter can be considerd as an alias of the
2149
+ # NOTE: An array typed parameter can be considered as an alias of the
2144
2150
  # corresponding argument. So, it is safe to return an address
2145
2151
  # of the argument.
2146
2152
  return if pointee.type.parameter? && pointee.type.array?
@@ -2290,7 +2296,7 @@ module CBuiltin #:nodoc:
2290
2296
  if rhs_pointee = @interp.pointee_of(rhs_variable)
2291
2297
  if rhs_pointee.variable? && rhs_pointee.named?
2292
2298
  return unless rhs_pointee.binding.memory.dynamic?
2293
- # NOTE: An array typed parameter can be considerd as an alias of the
2299
+ # NOTE: An array typed parameter can be considered as an alias of the
2294
2300
  # corresponding argument. So, it is safe to return an address
2295
2301
  # of the argument.
2296
2302
  return if rhs_pointee.type.parameter? && rhs_pointee.type.array?
@@ -11462,11 +11468,14 @@ module CBuiltin #:nodoc:
11462
11468
  class W0582 < PassiveCodeCheck
11463
11469
  def_registrant_phase C::Prepare2Phase
11464
11470
 
11471
+ include C::Conversion
11472
+
11465
11473
  def initialize(context)
11466
11474
  super
11467
11475
  interp = context[:c_interpreter]
11468
11476
  interp.on_function_call_expr_evaled += method(:call_function)
11469
11477
  interp.on_function_declared += method(:check)
11478
+ @enum_tbl = interp.environment.enumerator_table
11470
11479
  @function_calls = Hash.new { |hash, key| hash[key] = [] }
11471
11480
  end
11472
11481
 
@@ -11477,23 +11486,26 @@ module CBuiltin #:nodoc:
11477
11486
 
11478
11487
  param_types = function.type.parameter_types.reject { |type| type.void? }
11479
11488
 
11480
- @function_calls[function.name].each do |expr, arg_types|
11481
- if arg_types.size == param_types.size
11482
- conformed = arg_types.zip(param_types).all? { |atype, ptype|
11489
+ @function_calls[function.name].each do |funcall_expr, args|
11490
+ if args.size == param_types.size
11491
+ types = args.map { |ary| ary.first }.zip(param_types)
11492
+ conformed = types.each_with_index.all? { |(atype, ptype), index|
11493
+ funcall_expr.argument_expressions[index].constant?(@enum_tbl) &&
11494
+ untyped_pointer_conversion?(atype, ptype, args[index].last) or
11483
11495
  atype.convertible?(ptype)
11484
11496
  }
11485
11497
  else
11486
11498
  conformed = false
11487
11499
  end
11488
11500
 
11489
- W(:W0582, expr.location) unless conformed
11501
+ W(:W0582, funcall_expr.location) unless conformed
11490
11502
  end
11491
11503
  end
11492
11504
 
11493
- def call_function(expression, function, arg_variables, result_variable)
11505
+ def call_function(funcall_expr, function, arg_vars, result_var)
11494
11506
  if function.named?
11495
- arg_types = arg_variables.map { |var| var.type }
11496
- @function_calls[function.name].push([expression, arg_types])
11507
+ args = arg_vars.map { |var| [var.type, var.value.to_single_value] }
11508
+ @function_calls[function.name].push([funcall_expr, args])
11497
11509
  end
11498
11510
  end
11499
11511
  end
@@ -11501,11 +11513,14 @@ module CBuiltin #:nodoc:
11501
11513
  class W0583 < PassiveCodeCheck
11502
11514
  def_registrant_phase C::Prepare2Phase
11503
11515
 
11516
+ include C::Conversion
11517
+
11504
11518
  def initialize(context)
11505
11519
  super
11506
11520
  interp = context[:c_interpreter]
11507
11521
  interp.on_function_call_expr_evaled += method(:call_function)
11508
11522
  interp.on_function_defined += method(:check)
11523
+ @enum_tbl = interp.environment.enumerator_table
11509
11524
  @function_calls = Hash.new { |hash, key| hash[key] = [] }
11510
11525
  end
11511
11526
 
@@ -11516,23 +11531,26 @@ module CBuiltin #:nodoc:
11516
11531
 
11517
11532
  param_types = function.type.parameter_types.reject { |type| type.void? }
11518
11533
 
11519
- @function_calls[function.name].each do |expr, arg_types|
11520
- if arg_types.size == param_types.size
11521
- conformed = arg_types.zip(param_types).all? { |atype, ptype|
11534
+ @function_calls[function.name].each do |funcall_expr, args|
11535
+ if args.size == param_types.size
11536
+ types = args.map { |ary| ary.first }.zip(param_types)
11537
+ conformed = types.each_with_index.all? { |(atype, ptype), index|
11538
+ funcall_expr.argument_expressions[index].constant?(@enum_tbl) &&
11539
+ untyped_pointer_conversion?(atype, ptype, args[index].last) or
11522
11540
  atype.convertible?(ptype)
11523
11541
  }
11524
11542
  else
11525
11543
  conformed = false
11526
11544
  end
11527
11545
 
11528
- W(:W0583, expr.location) unless conformed
11546
+ W(:W0583, funcall_expr.location) unless conformed
11529
11547
  end
11530
11548
  end
11531
11549
 
11532
- def call_function(expression, function, arg_variables, result_variable)
11550
+ def call_function(funcall_expr, function, arg_vars, result_var)
11533
11551
  if function.named?
11534
- arg_types = arg_variables.map { |var| var.type }
11535
- @function_calls[function.name].push([expression, arg_types])
11552
+ args = arg_vars.map { |var| [var.type, var.value.to_single_value] }
11553
+ @function_calls[function.name].push([funcall_expr, args])
11536
11554
  end
11537
11555
  end
11538
11556
  end
@@ -11540,27 +11558,34 @@ module CBuiltin #:nodoc:
11540
11558
  class W0584 < PassiveCodeCheck
11541
11559
  def_registrant_phase C::Prepare2Phase
11542
11560
 
11561
+ include C::Conversion
11562
+
11543
11563
  def initialize(context)
11544
11564
  super
11545
11565
  interp = context[:c_interpreter]
11546
11566
  interp.on_function_call_expr_evaled += method(:check)
11567
+ @enum_tbl = interp.environment.enumerator_table
11547
11568
  end
11548
11569
 
11549
11570
  private
11550
- def check(expression, function, arg_variables, result_variable)
11571
+ def check(funcall_expr, function, arg_vars, result_var)
11551
11572
  return unless function.named?
11552
11573
  return unless kandr_style_definition_of(function)
11553
11574
  return if function.type.have_va_list?
11554
11575
 
11555
- arg_types = arg_variables.map { |var| var.type }
11576
+ args = arg_vars.map { |var| [var.type, var.value.to_single_value] }
11556
11577
  param_types = function.type.parameter_types.reject { |type| type.void? }
11557
11578
 
11558
- if arg_types.size == param_types.size
11559
- arg_types.zip(param_types).each_with_index do |(atype, ptype), index|
11560
- unless atype.convertible?(ptype)
11561
- W(:W0584,
11562
- expression.argument_expressions[index].location, index + 1)
11563
- end
11579
+ return unless args.size == param_types.size
11580
+
11581
+ args.zip(param_types).each_with_index do |(arg, ptype), index|
11582
+ arg_expr = funcall_expr.argument_expressions[index]
11583
+ if arg_expr.constant?(@enum_tbl)
11584
+ next if untyped_pointer_conversion?(arg.first, ptype, arg.last)
11585
+ end
11586
+
11587
+ unless arg.first.convertible?(ptype)
11588
+ W(:W0584, arg_expr.location, index + 1)
11564
11589
  end
11565
11590
  end
11566
11591
  end
@@ -11928,6 +11953,8 @@ module CBuiltin #:nodoc:
11928
11953
  class W0609 < PassiveCodeCheck
11929
11954
  def_registrant_phase C::Prepare2Phase
11930
11955
 
11956
+ include C::SyntaxNodeCollector
11957
+
11931
11958
  def initialize(context)
11932
11959
  super
11933
11960
  interp = context[:c_interpreter]
@@ -11935,12 +11962,46 @@ module CBuiltin #:nodoc:
11935
11962
  interp.on_equality_expr_evaled += method(:check)
11936
11963
  interp.on_logical_and_expr_evaled += method(:check)
11937
11964
  interp.on_logical_or_expr_evaled += method(:check)
11965
+ interp.on_for_stmt_started += method(:enter_for_statement)
11966
+ interp.on_c99_for_stmt_started += method(:enter_for_statement)
11967
+ interp.on_for_stmt_ended += method(:leave_for_statement)
11968
+ interp.on_c99_for_stmt_ended += method(:leave_for_statement)
11969
+ interp.on_for_ctrlexpr_evaled += method(:memorize_for_ctrlexpr)
11970
+ interp.on_c99_for_ctrlexpr_evaled += method(:memorize_for_ctrlexpr)
11971
+ @for_ctrlexpr_stack = []
11938
11972
  end
11939
11973
 
11940
11974
  private
11941
11975
  def check(binary_expression, lhs_variable, rhs_variable, result_variable)
11942
11976
  if result_variable.value.must_be_true?
11943
- W(:W0609, binary_expression.location)
11977
+ unless should_not_check?(binary_expression)
11978
+ W(:W0609, binary_expression.location)
11979
+ end
11980
+ end
11981
+ end
11982
+
11983
+ def enter_for_statement(for_statement)
11984
+ @for_ctrlexpr_stack.push(nil)
11985
+ end
11986
+
11987
+ def leave_for_statement(*)
11988
+ @for_ctrlexpr_stack.pop
11989
+ end
11990
+
11991
+ def memorize_for_ctrlexpr(for_statement, *)
11992
+ if explicit_ctrlexpr = for_statement.condition_statement.expression
11993
+ @for_ctrlexpr_stack[-1] = explicit_ctrlexpr
11994
+ end
11995
+ end
11996
+
11997
+ def should_not_check?(expr)
11998
+ if ctrlexpr = @for_ctrlexpr_stack.last
11999
+ collect_relational_expressions(ctrlexpr).include?(expr) ||
12000
+ collect_equality_expressions(ctrlexpr).include?(expr) ||
12001
+ collect_logical_and_expressions(ctrlexpr).include?(expr) ||
12002
+ collect_logical_or_expressions(ctrlexpr).include?(expr)
12003
+ else
12004
+ false
11944
12005
  end
11945
12006
  end
11946
12007
  end
@@ -11948,6 +12009,8 @@ module CBuiltin #:nodoc:
11948
12009
  class W0610 < PassiveCodeCheck
11949
12010
  def_registrant_phase C::Prepare2Phase
11950
12011
 
12012
+ include C::SyntaxNodeCollector
12013
+
11951
12014
  def initialize(context)
11952
12015
  super
11953
12016
  interp = context[:c_interpreter]
@@ -11955,12 +12018,46 @@ module CBuiltin #:nodoc:
11955
12018
  interp.on_equality_expr_evaled += method(:check)
11956
12019
  interp.on_logical_and_expr_evaled += method(:check)
11957
12020
  interp.on_logical_or_expr_evaled += method(:check)
12021
+ interp.on_for_stmt_started += method(:enter_for_statement)
12022
+ interp.on_c99_for_stmt_started += method(:enter_for_statement)
12023
+ interp.on_for_stmt_ended += method(:leave_for_statement)
12024
+ interp.on_c99_for_stmt_ended += method(:leave_for_statement)
12025
+ interp.on_for_ctrlexpr_evaled += method(:memorize_for_ctrlexpr)
12026
+ interp.on_c99_for_ctrlexpr_evaled += method(:memorize_for_ctrlexpr)
12027
+ @for_ctrlexpr_stack = []
11958
12028
  end
11959
12029
 
11960
12030
  private
11961
12031
  def check(binary_expression, lhs_variable, rhs_variable, result_variable)
11962
12032
  if result_variable.value.must_be_false?
11963
- W(:W0610, binary_expression.location)
12033
+ unless should_not_check?(binary_expression)
12034
+ W(:W0610, binary_expression.location)
12035
+ end
12036
+ end
12037
+ end
12038
+
12039
+ def enter_for_statement(for_statement)
12040
+ @for_ctrlexpr_stack.push(nil)
12041
+ end
12042
+
12043
+ def leave_for_statement(*)
12044
+ @for_ctrlexpr_stack.pop
12045
+ end
12046
+
12047
+ def memorize_for_ctrlexpr(for_statement, *)
12048
+ if explicit_ctrlexpr = for_statement.condition_statement.expression
12049
+ @for_ctrlexpr_stack[-1] = explicit_ctrlexpr
12050
+ end
12051
+ end
12052
+
12053
+ def should_not_check?(expr)
12054
+ if ctrlexpr = @for_ctrlexpr_stack.last
12055
+ collect_relational_expressions(ctrlexpr).include?(expr) ||
12056
+ collect_equality_expressions(ctrlexpr).include?(expr) ||
12057
+ collect_logical_and_expressions(ctrlexpr).include?(expr) ||
12058
+ collect_logical_or_expressions(ctrlexpr).include?(expr)
12059
+ else
12060
+ false
11964
12061
  end
11965
12062
  end
11966
12063
  end
@@ -14520,7 +14617,7 @@ module CBuiltin #:nodoc:
14520
14617
  when "+"
14521
14618
  unbound_value = lhs_variable.value + rhs_variable.value
14522
14619
  when "-"
14523
- unbound_value = lhs_variable.value + rhs_variable.value
14620
+ unbound_value = lhs_variable.value - rhs_variable.value
14524
14621
  when "*"
14525
14622
  unbound_value = lhs_variable.value * rhs_variable.value
14526
14623
  else
@@ -18051,25 +18148,44 @@ module CBuiltin #:nodoc:
18051
18148
  class W9003 < PassiveCodeCheck
18052
18149
  def_registrant_phase C::Prepare2Phase
18053
18150
 
18151
+ include C::Conversion
18152
+
18054
18153
  def initialize(context)
18055
18154
  super
18056
18155
  interp = context[:c_interpreter]
18057
18156
  interp.on_implicit_conv_performed += method(:check)
18157
+ @enum_tbl = interp.environment.enumerator_table
18058
18158
  end
18059
18159
 
18060
18160
  private
18061
- def check(initializer_or_expression, original_variable, result_variable)
18062
- from_type = original_variable.type
18063
- to_type = result_variable.type
18161
+ def check(init_or_expr, orig_var, result_var)
18162
+ from_type = orig_var.type
18163
+ to_type = result_var.type
18064
18164
 
18065
18165
  if from_type.undeclared? || from_type.unresolved? ||
18066
18166
  to_type.undeclared? || to_type.unresolved?
18067
18167
  return
18068
18168
  end
18069
18169
 
18170
+ case init_or_expr
18171
+ when C::Initializer
18172
+ if expr = init_or_expr.expression and expr.constant?(@enum_tbl)
18173
+ if untyped_pointer_conversion?(from_type, to_type, orig_var.value)
18174
+ return
18175
+ end
18176
+ end
18177
+ when C::Expression
18178
+ if init_or_expr.constant?(@enum_tbl)
18179
+ if untyped_pointer_conversion?(from_type, to_type, orig_var.value)
18180
+ return
18181
+ end
18182
+ end
18183
+ end
18184
+
18070
18185
  unless from_type.standard? && to_type.standard?
18071
18186
  unless from_type.convertible?(to_type)
18072
- W(:W9003, initializer_or_expression.location, from_type.brief_image)
18187
+ W(:W9003, init_or_expr.location,
18188
+ from_type.brief_image, to_type.brief_image)
18073
18189
  end
18074
18190
  end
18075
18191
  end
@@ -32,9 +32,9 @@
32
32
  module AdLint #:nodoc:
33
33
 
34
34
  MAJOR_VERSION = 2
35
- MINOR_VERSION = 4
36
- PATCH_VERSION = 10
37
- RELEASE_DATE = "2012-10-15"
35
+ MINOR_VERSION = 6
36
+ PATCH_VERSION = 0
37
+ RELEASE_DATE = "2012-10-22"
38
38
 
39
39
  TRAITS_SCHEMA_VERSION = "2.4.0"
40
40