adlint 1.14.0 → 1.16.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (70) hide show
  1. data/ChangeLog +265 -0
  2. data/MANIFEST +15 -0
  3. data/NEWS +30 -4
  4. data/etc/conf.d/noarch/adlint_all_bat.erb +1 -1
  5. data/etc/mesg.d/en_US/messages.yml +3 -3
  6. data/etc/mesg.d/ja_JP/messages.yml +3 -3
  7. data/features/message_detection/W0001.feature +2 -0
  8. data/features/message_detection/W0007.feature +8 -0
  9. data/features/message_detection/W0010.feature +4 -1
  10. data/features/message_detection/W0013.feature +8 -0
  11. data/features/message_detection/W0093.feature +3 -0
  12. data/features/message_detection/W0104.feature +7 -0
  13. data/features/message_detection/W0643.feature +80 -0
  14. data/features/message_detection/W0646.feature +115 -0
  15. data/features/message_detection/W0691.feature +100 -0
  16. data/features/message_detection/W0692.feature +32 -0
  17. data/features/message_detection/W0694.feature +128 -0
  18. data/features/message_detection/W0716.feature +3 -0
  19. data/features/message_detection/W0717.feature +3 -0
  20. data/features/message_detection/W0718.feature +3 -0
  21. data/features/message_detection/W0723.feature +2 -0
  22. data/features/message_detection/W0732.feature +3 -0
  23. data/features/message_detection/W0733.feature +3 -0
  24. data/features/message_detection/W0734.feature +8 -0
  25. data/features/message_detection/W0735.feature +8 -0
  26. data/features/message_detection/W0805.feature +92 -0
  27. data/features/message_detection/W0811.feature +79 -0
  28. data/features/message_detection/W1031.feature +7 -0
  29. data/features/message_detection/W1040.feature +89 -0
  30. data/features/message_detection/W1041.feature +15 -0
  31. data/features/message_detection/W1046.feature +60 -0
  32. data/features/message_detection/W1052.feature +3 -0
  33. data/features/message_detection/W1066.feature +3 -0
  34. data/features/message_detection/W1067.feature +3 -0
  35. data/features/message_detection/W1068.feature +3 -0
  36. data/features/message_detection/W1069.feature +5 -0
  37. data/features/message_detection/W1070.feature +6 -0
  38. data/features/message_detection/W1072.feature +1 -0
  39. data/features/message_detection/W1073.feature +145 -0
  40. data/features/message_detection/W1074.feature +139 -0
  41. data/features/message_detection/W1075.feature +86 -0
  42. data/features/message_detection/W1076.feature +66 -0
  43. data/features/message_detection/W1077.feature +105 -0
  44. data/features/message_detection/W9003.feature +4 -0
  45. data/lib/adlint/c/ctrlexpr.rb +3 -0
  46. data/lib/adlint/c/interp.rb +11 -5
  47. data/lib/adlint/c/lexer.rb +14 -3
  48. data/lib/adlint/c/message.rb +192 -0
  49. data/lib/adlint/c/parser.rb +19 -3
  50. data/lib/adlint/c/parser.y +18 -2
  51. data/lib/adlint/c/phase.rb +19 -6
  52. data/lib/adlint/c/syntax.rb +6 -0
  53. data/lib/adlint/c/type.rb +5 -1
  54. data/lib/adlint/cpp/constexpr.rb +3 -3
  55. data/lib/adlint/cpp/constexpr.y +3 -3
  56. data/lib/adlint/cpp/eval.rb +60 -86
  57. data/lib/adlint/cpp/lexer.rb +82 -28
  58. data/lib/adlint/cpp/macro.rb +64 -35
  59. data/lib/adlint/cpp/message.rb +137 -4
  60. data/lib/adlint/cpp/phase.rb +8 -0
  61. data/lib/adlint/cpp/syntax.rb +25 -0
  62. data/lib/adlint/lang.rb +2 -1
  63. data/lib/adlint/version.rb +2 -2
  64. data/share/doc/developers_guide_ja.html +3 -3
  65. data/share/doc/developers_guide_ja.texi +1 -1
  66. data/share/doc/users_guide_en.html +102 -85
  67. data/share/doc/users_guide_en.texi +85 -69
  68. data/share/doc/users_guide_ja.html +102 -94
  69. data/share/doc/users_guide_ja.texi +85 -77
  70. metadata +17 -2
@@ -63,6 +63,7 @@ module Cpp #:nodoc:
63
63
  def_plugin :on_unlexable_char_found
64
64
  def_plugin :on_cr_at_eol_found
65
65
  def_plugin :on_eof_mark_at_eof_found
66
+ def_plugin :on_illformed_newline_escape_found
66
67
 
67
68
  def next_token
68
69
  if @top_token
@@ -125,6 +126,10 @@ module Cpp #:nodoc:
125
126
  on_unlexable_char_found.invoke(char, location)
126
127
  end
127
128
 
129
+ def notify_illformed_newline_escape_found(location)
130
+ on_illformed_newline_escape_found.invoke(location)
131
+ end
132
+
128
133
  GROUP_DIRECTIVE_RE =
129
134
  /.*?(?=^[ \t]*#[ \t]*(?:if|ifdef|ifndef|asm|else|elif|endif|endasm)\b)/m
130
135
  private_constant :GROUP_DIRECTIVE_RE
@@ -200,7 +205,16 @@ module Cpp #:nodoc:
200
205
  end
201
206
 
202
207
  def scan_escaped_newline(content)
203
- content.scan(/\\[ \t]*\n/)
208
+ location = content.location
209
+ case
210
+ when escaped_newline = content.scan(/\\\n/)
211
+ escaped_newline
212
+ when escaped_newline = content.scan(/\\[ \t]+\n/)
213
+ @lexer.notify_illformed_newline_escape_found(location)
214
+ escaped_newline
215
+ else
216
+ nil
217
+ end
204
218
  end
205
219
 
206
220
  def tokenize_pp_token(content)
@@ -259,6 +273,15 @@ module Cpp #:nodoc:
259
273
  end
260
274
  nil
261
275
  end
276
+
277
+ def tokenize_extra_token(content)
278
+ # NOTE: #tokenize_pp_token can tokenize almost all types of tokens.
279
+ if token = tokenize_pp_token(content)
280
+ Token.new(:EXTRA_TOKEN, token.value, token.location)
281
+ else
282
+ nil
283
+ end
284
+ end
262
285
  end
263
286
 
264
287
  class Initial < LexerState
@@ -301,7 +324,8 @@ module Cpp #:nodoc:
301
324
  when token = tokenize_endasm_directive(@lexer.content)
302
325
  @lexer.transit(InEndasmDirective.new(@lexer))
303
326
  else
304
- token = tokenize_null_directive(@lexer.content)
327
+ token = tokenize_null_directive(@lexer.content) ||
328
+ tokenize_unknown_directive(@lexer.content)
305
329
  end
306
330
  else
307
331
  token = tokenize_text_line(@lexer.content)
@@ -433,21 +457,28 @@ module Cpp #:nodoc:
433
457
  end
434
458
 
435
459
  def tokenize_null_directive(content)
460
+ location = content.location
461
+ if value = content.scan(/[ \t]*#[ \t]\n/)
462
+ return Token.new(:NULL_DIRECTIVE, value, location)
463
+ end
464
+ nil
465
+ end
466
+
467
+ def tokenize_unknown_directive(content)
436
468
  location = content.location
437
469
  value = content.scan(/[ \t]*#/)
438
470
  until content.empty?
439
- if token = content.scan(/.*?(?=\\[ \t]*\n|\n)/)
440
- value += token
441
- end
471
+ next if discard_heading_comments || scan_escaped_newline(content)
442
472
 
443
- next if scan_escaped_newline(content)
444
-
445
- if new_line = content.scan(/\n/)
446
- value += new_line
473
+ case
474
+ when str = content.scan(/.+?(?=\/\*|\/\/|\\[ \t]*\n|L?"|L?'|\n)/i)
475
+ value += str
476
+ when str = content.scan(/\n/)
477
+ value += str
447
478
  break
448
479
  end
449
480
  end
450
- Token.new(:NULL_DIRECTIVE, value, location)
481
+ Token.new(:UNKNOWN_DIRECTIVE, value, location)
451
482
  end
452
483
 
453
484
  def tokenize_text_line(content)
@@ -487,11 +518,13 @@ module Cpp #:nodoc:
487
518
  class InIfDirective < LexerState
488
519
  def next_token
489
520
  until @lexer.content.empty?
490
- next if discard_heading_comments
491
- next if scan_escaped_newline(@lexer.content)
521
+ if discard_heading_comments || scan_escaped_newline(@lexer.content)
522
+ next
523
+ end
492
524
 
493
525
  token = tokenize_pp_token(@lexer.content) ||
494
- tokenize_new_line(@lexer.content)
526
+ tokenize_new_line(@lexer.content) ||
527
+ tokenize_extra_token(@lexer.content)
495
528
 
496
529
  if token
497
530
  break
@@ -516,11 +549,13 @@ module Cpp #:nodoc:
516
549
  class InIfdefDirective < LexerState
517
550
  def next_token
518
551
  until @lexer.content.empty?
519
- next if discard_heading_comments
520
- next if scan_escaped_newline(@lexer.content)
552
+ if discard_heading_comments || scan_escaped_newline(@lexer.content)
553
+ next
554
+ end
521
555
 
522
556
  token = tokenize_identifier(@lexer.content) ||
523
- tokenize_new_line(@lexer.content)
557
+ tokenize_new_line(@lexer.content) ||
558
+ tokenize_extra_token(@lexer.content)
524
559
 
525
560
  if token
526
561
  break
@@ -549,10 +584,14 @@ module Cpp #:nodoc:
549
584
  class InElseDirective < LexerState
550
585
  def next_token
551
586
  until @lexer.content.empty?
552
- next if discard_heading_comments
553
- next if scan_escaped_newline(@lexer.content)
587
+ if discard_heading_comments || scan_escaped_newline(@lexer.content)
588
+ next
589
+ end
554
590
 
555
- if token = tokenize_new_line(@lexer.content)
591
+ token = tokenize_new_line(@lexer.content) ||
592
+ tokenize_extra_token(@lexer.content)
593
+
594
+ if token
556
595
  break
557
596
  else
558
597
  @lexer.content.eat!
@@ -577,12 +616,14 @@ module Cpp #:nodoc:
577
616
  class InIncludeDirective < LexerState
578
617
  def next_token
579
618
  until @lexer.content.empty?
580
- next if discard_heading_comments
581
- next if scan_escaped_newline(@lexer.content)
619
+ if discard_heading_comments || scan_escaped_newline(@lexer.content)
620
+ next
621
+ end
582
622
 
583
623
  token = tokenize_header_name(@lexer.content) ||
584
624
  tokenize_pp_token(@lexer.content) ||
585
- tokenize_new_line(@lexer.content)
625
+ tokenize_new_line(@lexer.content) ||
626
+ tokenize_extra_token(@lexer.content)
586
627
 
587
628
  if token
588
629
  break
@@ -626,7 +667,8 @@ module Cpp #:nodoc:
626
667
  private
627
668
  def tokenize_macro_name(content)
628
669
  until content.empty?
629
- next if discard_heading_comments
670
+ next if discard_heading_comments || scan_escaped_newline(content)
671
+
630
672
  if token = tokenize_identifier(content)
631
673
  @tokens.push(token)
632
674
  break
@@ -639,8 +681,7 @@ module Cpp #:nodoc:
639
681
 
640
682
  paren_depth = 0
641
683
  until content.empty?
642
- next if discard_heading_comments
643
- next if scan_escaped_newline(content)
684
+ next if discard_heading_comments || scan_escaped_newline(content)
644
685
 
645
686
  if token = tokenize_identifier(content)
646
687
  @tokens.push(token)
@@ -670,8 +711,7 @@ module Cpp #:nodoc:
670
711
 
671
712
  def tokenize_pp_tokens(content)
672
713
  until content.empty?
673
- next if discard_heading_comments
674
- next if scan_escaped_newline(content)
714
+ next if discard_heading_comments || scan_escaped_newline(content)
675
715
 
676
716
  token = tokenize_pp_token(content) || tokenize_new_line(content)
677
717
 
@@ -746,7 +786,8 @@ module Cpp #:nodoc:
746
786
  tokenize_string_literal(context) ||
747
787
  tokenize_null_constant(context) ||
748
788
  tokenize_identifier(context) ||
749
- tokenize_punctuator(context)
789
+ tokenize_punctuator(context) ||
790
+ tokenize_backslash(context)
750
791
 
751
792
  if pp_token
752
793
  token_array.push(pp_token)
@@ -839,6 +880,19 @@ module Cpp #:nodoc:
839
880
 
840
881
  nil
841
882
  end
883
+
884
+ def tokenize_backslash(context)
885
+ location = context.location
886
+
887
+ backslash = context.content.scan(/\\/)
888
+
889
+ if backslash
890
+ context.last_symbol = :BACKSLASH
891
+ return Token.new(:PP_TOKEN, backslash, location, backslash)
892
+ end
893
+
894
+ nil
895
+ end
842
896
  end
843
897
 
844
898
  class TextLineToPPTokensLexer < StringToPPTokensLexer
@@ -33,6 +33,7 @@ require "adlint/token"
33
33
  require "adlint/report"
34
34
  require "adlint/util"
35
35
  require "adlint/cpp/syntax"
36
+ require "adlint/cpp/lexer"
36
37
 
37
38
  module AdLint #:nodoc:
38
39
  module Cpp #:nodoc:
@@ -76,16 +77,18 @@ module Cpp #:nodoc:
76
77
 
77
78
  def expand(tokens, macro_table, context)
78
79
  super
79
- macro_table.notify_object_like_macro_replacement(self, tokens)
80
80
 
81
81
  if replacement_list
82
82
  location = tokens.first.location
83
- replacement_list.tokens.map { |t|
83
+ result = replacement_list.tokens.map { |t|
84
84
  ReplacedToken.new(t.type, t.value, location, t.type_hint, false)
85
85
  }
86
86
  else
87
- []
87
+ result = []
88
88
  end
89
+
90
+ macro_table.notify_object_like_macro_replacement(self, tokens, result)
91
+ result
89
92
  end
90
93
 
91
94
  def function_like?; false end
@@ -105,22 +108,22 @@ module Cpp #:nodoc:
105
108
 
106
109
  def replaceable_size(tokens)
107
110
  return 0 unless name.value == tokens.first.value
108
- arg_array, index = parse_arguments(tokens, 1)
109
- arg_array && @parameter_names.size >= arg_array.size ? index + 1 : 0
111
+ args, index = parse_arguments(tokens, 1)
112
+ args && @parameter_names.size >= args.size ? index + 1 : 0
110
113
  end
111
114
 
112
115
  def expand(tokens, macro_table, context)
113
116
  super
114
- arg_array = parse_arguments(tokens, 1).first
115
- macro_table.notify_function_like_macro_replacement(self, tokens)
116
117
 
117
- args = {}
118
- @parameter_names.each_with_index do |param, i|
119
- arg = arg_array[i] and args[param] = arg
120
- end
118
+ args, * = parse_arguments(tokens, 1)
119
+ result = expand_replacement_list(
120
+ @parameter_names.each_with_index.with_object({}) { |(name, i), hash|
121
+ arg = args[i] and hash[name] = arg
122
+ }, tokens.first.location, macro_table, context)
121
123
 
122
- location = tokens.first.location
123
- expand_replacement_list(args, location, macro_table, context)
124
+ macro_table.notify_function_like_macro_replacement(self, tokens, args,
125
+ result)
126
+ result
124
127
  end
125
128
 
126
129
  def function_like?; true end
@@ -186,7 +189,7 @@ module Cpp #:nodoc:
186
189
  return (arg.empty? ? nil : arg), index
187
190
  end
188
191
 
189
- def expand_replacement_list(args, expansion_location, macro_table, context)
192
+ def expand_replacement_list(args, location, macro_table, context)
190
193
  return [] unless replacement_list
191
194
 
192
195
  result = []
@@ -200,27 +203,27 @@ module Cpp #:nodoc:
200
203
  macro_table, context)
201
204
  when curr_token.value == "#"
202
205
  if next_token and arg = args[next_token.value]
203
- result.push(stringize_argument(arg, expansion_location))
206
+ stringized = stringize_argument(arg, location, macro_table)
207
+ result.push(stringized)
204
208
  index += 1
205
209
  end
206
210
  when curr_token.value == "##" && next_token.value == "#"
207
211
  if next_next_token = replacement_list.tokens[index + 2] and
208
212
  arg = args[next_next_token.value]
209
- stringized = stringize_argument(arg, expansion_location)
210
- concat_with_last_token([stringized], expansion_location, result)
213
+ stringized = stringize_argument(arg, location, macro_table)
214
+ concat_with_last_token([stringized], location, result, macro_table)
211
215
  index += 2
212
216
  end
213
217
  when curr_token.value == "##"
214
218
  if next_token and arg = args[next_token.value]
215
- concat_with_last_token(arg, expansion_location, result)
219
+ concat_with_last_token(arg, location, result, macro_table)
216
220
  else
217
- concat_with_last_token([next_token], expansion_location, result)
221
+ concat_with_last_token([next_token], location, result, macro_table)
218
222
  end
219
223
  index += 1
220
224
  else
221
225
  result.push(ReplacedToken.new(curr_token.type, curr_token.value,
222
- expansion_location,
223
- curr_token.type_hint, false))
226
+ location, curr_token.type_hint, false))
224
227
  end
225
228
  index += 1
226
229
  end
@@ -254,7 +257,7 @@ module Cpp #:nodoc:
254
257
  end
255
258
  end
256
259
 
257
- def stringize_argument(arg, expansion_location)
260
+ def stringize_argument(arg, expansion_location, macro_table)
258
261
  # NOTE: The ISO C99 standard saids;
259
262
  #
260
263
  # 6.10.3.2 The # operator
@@ -290,12 +293,18 @@ module Cpp #:nodoc:
290
293
  # NOTE: This code does not concern about contents of the string literal.
291
294
  # But, it is enough for analysis.
292
295
 
293
- ReplacedToken.new(:PP_TOKEN,
294
- "\"#{arg.map { |token| token.value }.join(' ')}\"",
295
- expansion_location, :STRING_LITERAL, false)
296
+ str = arg.map { |token| token.value }.join
297
+ if str =~ /((:?\\*))\\\z/ && $1.length.even?
298
+ str.chop!
299
+ macro_table.notify_last_backslash_ignored(arg.last)
300
+ end
301
+
302
+ ReplacedToken.new(:PP_TOKEN, "\"#{str}\"", expansion_location,
303
+ :STRING_LITERAL, false)
296
304
  end
297
305
 
298
- def concat_with_last_token(tokens, expansion_location, result)
306
+ def concat_with_last_token(arg_tokens, expansion_location, result_tokens,
307
+ macro_table)
299
308
  # NOTE: The ISO C99 standard saids;
300
309
  #
301
310
  # 6.10.3.3 The ## operator
@@ -327,12 +336,18 @@ module Cpp #:nodoc:
327
336
  # The resulting token is available for further macro replacement. The
328
337
  # order of evaluation of ## operators is unspecified.
329
338
 
330
- if last_token = result.pop
331
- result.push(
332
- ReplacedToken.new(:PP_TOKEN, last_token.value + tokens.first.value,
333
- expansion_location, nil, false))
339
+ if lhs = result_tokens.pop and rhs = arg_tokens.first
340
+ # NOTE: To avoid syntax error when the concatenated token can be
341
+ # retokenize to two or more tokens.
342
+ new_tokens = StringToPPTokensLexer.new(lhs.value + rhs.value).execute
343
+ new_tokens.map! do |token|
344
+ ReplacedToken.new(token.type, token.value, expansion_location,
345
+ token.type_hint, false)
346
+ end
347
+ macro_table.notify_sharpsharp_operator_evaled(lhs, rhs, new_tokens)
334
348
 
335
- result.concat(tokens[1..-1].map { |token|
349
+ result_tokens.concat(new_tokens)
350
+ result_tokens.concat(arg_tokens[1..-1].map { |token|
336
351
  ReplacedToken.new(token.type, token.value, expansion_location,
337
352
  token.type_hint, false)
338
353
  })
@@ -528,6 +543,8 @@ module Cpp #:nodoc:
528
543
 
529
544
  def_plugin :on_object_like_macro_replacement
530
545
  def_plugin :on_function_like_macro_replacement
546
+ def_plugin :on_sharpsharp_operator_evaled
547
+ def_plugin :on_last_backslash_ignored
531
548
 
532
549
  def define(macro)
533
550
  @macros[macro.name.value] = macro
@@ -569,12 +586,24 @@ module Cpp #:nodoc:
569
586
  replaced
570
587
  end
571
588
 
572
- def notify_object_like_macro_replacement(macro, tokens)
573
- on_object_like_macro_replacement.invoke(macro, tokens)
589
+ def notify_object_like_macro_replacement(macro, replacing_tokens,
590
+ result_tokens)
591
+ on_object_like_macro_replacement.invoke(macro, replacing_tokens,
592
+ result_tokens)
593
+ end
594
+
595
+ def notify_function_like_macro_replacement(macro, replacing_tokens, args,
596
+ result_tokens)
597
+ on_function_like_macro_replacement.invoke(macro, replacing_tokens, args,
598
+ result_tokens)
599
+ end
600
+
601
+ def notify_sharpsharp_operator_evaled(lhs_token, rhs_token, new_tokens)
602
+ on_sharpsharp_operator_evaled.invoke(lhs_token, rhs_token, new_tokens)
574
603
  end
575
604
 
576
- def notify_function_like_macro_replacement(macro, tokens)
577
- on_function_like_macro_replacement.invoke(macro, tokens)
605
+ def notify_last_backslash_ignored(token)
606
+ on_last_backslash_ignored.invoke(token)
578
607
  end
579
608
 
580
609
  private
@@ -221,8 +221,10 @@ module Cpp #:nodoc:
221
221
  end
222
222
 
223
223
  private
224
- def check(macro, tokens)
225
- W(:W0057, tokens.first.location) if macro.parameter_names.size > 31
224
+ def check(macro, replacing_tokens, *)
225
+ if macro.parameter_names.size > 31
226
+ W(:W0057, replacing_tokens.first.location)
227
+ end
226
228
  end
227
229
  end
228
230
 
@@ -1025,6 +1027,55 @@ module Cpp #:nodoc:
1025
1027
  end
1026
1028
  end
1027
1029
 
1030
+ class W0643 < PassiveMessageDetection
1031
+ # NOTE: W0643 may be duplicative when the same header which has references
1032
+ # to the undefined macro is included twice or more.
1033
+ ensure_uniqueness_of :W0643
1034
+
1035
+ def initialize(context)
1036
+ super
1037
+ macro_table = context[:cpp_macro_table]
1038
+ macro_table.on_last_backslash_ignored +=
1039
+ lambda { |token| W(:W0643, token.location) }
1040
+ end
1041
+ end
1042
+
1043
+ class W0691 < PassiveMessageDetection
1044
+ # NOTE: W0691 may be duplicative when the same header which has references
1045
+ # to the undefined macro is included twice or more.
1046
+ ensure_uniqueness_of :W0691
1047
+
1048
+ def initialize(context)
1049
+ super
1050
+ macro_table = context[:cpp_macro_table]
1051
+ macro_table.on_sharpsharp_operator_evaled += method(:check)
1052
+ end
1053
+
1054
+ private
1055
+ def check(lhs_token, rhs_token, new_tokens)
1056
+ W(:W0691, new_tokens.first.location) if new_tokens.size > 1
1057
+ end
1058
+ end
1059
+
1060
+ class W0692 < PassiveMessageDetection
1061
+ # NOTE: W0692 may be duplicative when the same header which has references
1062
+ # to the undefined macro is included twice or more.
1063
+ ensure_uniqueness_of :W0692
1064
+
1065
+ def initialize(context)
1066
+ super
1067
+ macro_table = context[:cpp_macro_table]
1068
+ macro_table.on_function_like_macro_replacement += method(:check)
1069
+ end
1070
+
1071
+ private
1072
+ def check(macro, replacing_tokens, args, *)
1073
+ if args.empty?
1074
+ W(:W0692, replacing_tokens.first.location, macro.name.value)
1075
+ end
1076
+ end
1077
+ end
1078
+
1028
1079
  class W0696 < PassiveMessageDetection
1029
1080
  # NOTE: W0696 may be duplicative when the same header which has references
1030
1081
  # to the undefined macro is included twice or more.
@@ -1045,8 +1096,43 @@ module Cpp #:nodoc:
1045
1096
 
1046
1097
  def initialize(context)
1047
1098
  super
1048
- context[:cpp_interpreter].on_illformed_defined_op_found +=
1049
- lambda { |location| W(:W0804, location) }
1099
+ context[:cpp_interpreter].on_illformed_defined_op_found += method(:check)
1100
+ end
1101
+
1102
+ private
1103
+ def check(location, *)
1104
+ W(:W0804, location)
1105
+ end
1106
+ end
1107
+
1108
+ class W0805 < W0804
1109
+ # NOTE: W0805 may be duplicative when the same header which causes this
1110
+ # warning is included twice or more.
1111
+ ensure_uniqueness_of :W0805
1112
+
1113
+ private
1114
+ def check(location, no_args)
1115
+ W(:W0805, location) unless no_args
1116
+ end
1117
+ end
1118
+
1119
+ class W0811 < PassiveMessageDetection
1120
+ # NOTE: W0811 may be duplicative when the same header which causes this
1121
+ # warning is included twice or more.
1122
+ ensure_uniqueness_of :W0811
1123
+
1124
+ def initialize(context)
1125
+ super
1126
+ macro_table = context[:cpp_macro_table]
1127
+ macro_table.on_object_like_macro_replacement += method(:check)
1128
+ macro_table.on_function_like_macro_replacement += method(:check)
1129
+ end
1130
+
1131
+ private
1132
+ def check(*, result_tokens)
1133
+ if defined_token = result_tokens.find { |t| t.value == "defined" }
1134
+ W(:W0811, defined_token.location)
1135
+ end
1050
1136
  end
1051
1137
  end
1052
1138
 
@@ -1067,6 +1153,53 @@ module Cpp #:nodoc:
1067
1153
  end
1068
1154
  end
1069
1155
 
1156
+ class W1040 < PassiveMessageDetection
1157
+ # NOTE: W1040 may be duplicative when the same header which causes this
1158
+ # warning is included twice or more.
1159
+ ensure_uniqueness_of :W1040
1160
+
1161
+ def initialize(context)
1162
+ super
1163
+ interp = context[:cpp_interpreter]
1164
+ interp.on_extra_tokens_found += method(:check)
1165
+ end
1166
+
1167
+ private
1168
+ def check(extra_tokens)
1169
+ W(:W1040, extra_tokens.first.location)
1170
+ end
1171
+ end
1172
+
1173
+ class W1041 < PassiveMessageDetection
1174
+ # NOTE: W1041 may be duplicative when the same header which causes this
1175
+ # warning is included twice or more.
1176
+ ensure_uniqueness_of :W1041
1177
+
1178
+ def initialize(context)
1179
+ super
1180
+ visitor = context[:cpp_visitor]
1181
+ visitor.enter_unknown_directive += method(:check)
1182
+ end
1183
+
1184
+ private
1185
+ def check(node)
1186
+ W(:W1041, node.location, node.token.value.chomp.strip)
1187
+ end
1188
+ end
1189
+
1190
+ class W1046 < PassiveMessageDetection
1191
+ # NOTE: W1046 may be duplicative when the same header which causes this
1192
+ # warning is included twice or more.
1193
+ ensure_uniqueness_of :W1046
1194
+
1195
+ def initialize(context)
1196
+ super
1197
+ interp = context[:cpp_interpreter]
1198
+ interp.on_illformed_newline_escape_found +=
1199
+ lambda { |location| W(:W1046, location) }
1200
+ end
1201
+ end
1202
+
1070
1203
  class W0832 < PassiveMessageDetection
1071
1204
  # NOTE: W0832 may be duplicative when the same header which causes this
1072
1205
  # warning is included twice or more.