adlint 1.14.0 → 1.16.0

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 (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.