adlint 1.4.0 → 1.6.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.
- data/ChangeLog +413 -5
- data/MANIFEST +6 -0
- data/NEWS +43 -4
- data/etc/mesg.d/en_US/messages.yml +1 -1
- data/etc/mesg.d/ja_JP/messages.yml +1 -1
- data/lib/adlint/c.rb +1 -0
- data/lib/adlint/c/enum.rb +52 -0
- data/lib/adlint/c/expr.rb +43 -102
- data/lib/adlint/c/interp.rb +1 -1
- data/lib/adlint/c/mediator.rb +1 -0
- data/lib/adlint/c/message.rb +831 -49
- data/lib/adlint/c/message_shima.rb +236 -0
- data/lib/adlint/c/metric.rb +9 -0
- data/lib/adlint/c/object.rb +37 -32
- data/lib/adlint/c/parser.rb +7 -7
- data/lib/adlint/c/parser.y +7 -7
- data/lib/adlint/c/phase.rb +21 -0
- data/lib/adlint/c/syntax.rb +11 -4
- data/lib/adlint/c/type.rb +1 -1
- data/lib/adlint/cpp.rb +1 -0
- data/lib/adlint/cpp/asm.rb +73 -0
- data/lib/adlint/cpp/message.rb +13 -0
- data/lib/adlint/cpp/message_shima.rb +36 -0
- data/lib/adlint/cpp/phase.rb +3 -0
- data/lib/adlint/cpp/source.rb +9 -0
- data/lib/adlint/version.rb +3 -3
- data/share/demo/Makefile +4 -0
- data/share/demo/bad_conv/bad_conv.c +12 -0
- data/share/demo/bad_enum/bad_enum.c +48 -2
- data/share/demo/bad_label/bad_label.c +26 -0
- data/share/demo/bad_macro/bad_macro.c +3 -0
- data/share/demo/implicit_conv/implicit_conv.c +1 -0
- data/share/demo/inline_asm/inline_asm.c +18 -0
- data/share/demo/invalid_call/invalid_call.c +5 -0
- data/share/demo/multi_decl/multi_decl_1.c +30 -0
- data/share/demo/overflow/overflow.c +3 -3
- data/share/demo/redundant_select/redundant_select.c +25 -0
- data/share/demo/reserved_ident/reserved_ident.c +98 -0
- data/share/doc/developers_guide_ja.html +3 -3
- data/share/doc/developers_guide_ja.texi +1 -1
- data/share/doc/users_guide_en.html +234 -126
- data/share/doc/users_guide_en.texi +207 -98
- data/share/doc/users_guide_ja.html +247 -156
- data/share/doc/users_guide_ja.texi +221 -130
- data/share/sample/vim-7.3/adlint/xxd/adlint_traits.yml +1 -1
- metadata +8 -2
@@ -35,6 +35,53 @@ require "adlint/message"
|
|
35
35
|
module AdLint #:nodoc:
|
36
36
|
module C #:nodoc:
|
37
37
|
|
38
|
+
class W0573 < PassiveMessageDetection
|
39
|
+
def initialize(context)
|
40
|
+
super
|
41
|
+
interp = context[:c_interpreter]
|
42
|
+
interp.on_function_call_expr_evaled += method(:check)
|
43
|
+
@environ = interp.environment
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
def check(function_call_expression, function, arg_variables,
|
48
|
+
result_variable)
|
49
|
+
if function.named? && function.name =~ /\A.*scanf\z/
|
50
|
+
format = create_format(function_call_expression,
|
51
|
+
format_str_index_of(function_call_expression),
|
52
|
+
arg_variables, @environ)
|
53
|
+
return unless format
|
54
|
+
|
55
|
+
format.conversion_specifiers.each_with_index do |cs, index|
|
56
|
+
if cs.scanset && cs.scanset.include?("-")
|
57
|
+
W(:W0573, format.location)
|
58
|
+
break
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def format_str_index_of(function_call_expression)
|
65
|
+
function_call_expression.argument_expressions.index do |arg_expr|
|
66
|
+
arg_expr.kind_of?(StringLiteralSpecifier)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def create_format(function_call_expression,
|
71
|
+
format_str_index, arg_variables, environment)
|
72
|
+
if format_str_index
|
73
|
+
format_str =
|
74
|
+
function_call_expression.argument_expressions[format_str_index]
|
75
|
+
if format_str && format_str.literal.value =~ /\AL?"(.*)"\z/i
|
76
|
+
location = format_str.location
|
77
|
+
trailing_args = arg_variables[(format_str_index + 1)..-1] || []
|
78
|
+
return ScanfFormat.new($1, location, trailing_args, environment)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
nil
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
38
85
|
class W0606 < PassiveMessageDetection
|
39
86
|
def initialize(context)
|
40
87
|
super
|
@@ -55,6 +102,46 @@ module C #:nodoc:
|
|
55
102
|
end
|
56
103
|
end
|
57
104
|
|
105
|
+
class W0685 < W0573
|
106
|
+
def check(function_call_expression, function, arg_variables,
|
107
|
+
result_variable)
|
108
|
+
if function.named? && function.name =~ /\A.*scanf\z/
|
109
|
+
format = create_format(function_call_expression,
|
110
|
+
format_str_index_of(function_call_expression),
|
111
|
+
arg_variables, @environ)
|
112
|
+
return unless format
|
113
|
+
|
114
|
+
format.conversion_specifiers.each do |cs|
|
115
|
+
next unless cs.scanset
|
116
|
+
|
117
|
+
cs.scanset.scan(/(.)-(.)/).each do |lhs, rhs|
|
118
|
+
W(:W0685, format.location) if lhs.ord > rhs.ord
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
class W0686 < W0573
|
126
|
+
def check(function_call_expression, function, arg_variables,
|
127
|
+
result_variable)
|
128
|
+
if function.named? && function.name =~ /\A.*scanf\z/
|
129
|
+
format = create_format(function_call_expression,
|
130
|
+
format_str_index_of(function_call_expression),
|
131
|
+
arg_variables, @environ)
|
132
|
+
return unless format
|
133
|
+
|
134
|
+
format.conversion_specifiers.each do |cs|
|
135
|
+
next unless cs.scanset
|
136
|
+
|
137
|
+
unless cs.valid_scanset?
|
138
|
+
W(:W0686, format.location)
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
58
145
|
class W0698 < PassiveMessageDetection
|
59
146
|
def initialize(context)
|
60
147
|
super
|
@@ -114,6 +201,34 @@ module C #:nodoc:
|
|
114
201
|
end
|
115
202
|
end
|
116
203
|
|
204
|
+
class W0781 < PassiveMessageDetection
|
205
|
+
def initialize(context)
|
206
|
+
super
|
207
|
+
visitor = context[:c_visitor]
|
208
|
+
visitor.enter_switch_statement += method(:enter_switch_statement)
|
209
|
+
visitor.leave_switch_statement += method(:check)
|
210
|
+
visitor.enter_case_labeled_statement += method(:add_exec_path)
|
211
|
+
visitor.enter_default_labeled_statement += method(:add_exec_path)
|
212
|
+
@exec_path_nums = []
|
213
|
+
end
|
214
|
+
|
215
|
+
private
|
216
|
+
def enter_switch_statement(node)
|
217
|
+
@exec_path_nums.push(0)
|
218
|
+
end
|
219
|
+
|
220
|
+
def check(node)
|
221
|
+
if exec_path_num = @exec_path_nums.last and exec_path_num < 2
|
222
|
+
W(:W0781, node.location)
|
223
|
+
end
|
224
|
+
@exec_path_nums.pop
|
225
|
+
end
|
226
|
+
|
227
|
+
def add_exec_path(node)
|
228
|
+
@exec_path_nums[-1] += 1 if node.executed?
|
229
|
+
end
|
230
|
+
end
|
231
|
+
|
117
232
|
class W0801 < PassiveMessageDetection
|
118
233
|
def initialize(context)
|
119
234
|
super
|
@@ -128,6 +243,127 @@ module C #:nodoc:
|
|
128
243
|
end
|
129
244
|
end
|
130
245
|
|
246
|
+
class W0809 < PassiveMessageDetection
|
247
|
+
def initialize(context)
|
248
|
+
super
|
249
|
+
visitor = context[:c_visitor]
|
250
|
+
visitor.enter_function_declaration += method(:check_function_name)
|
251
|
+
visitor.enter_variable_declaration += method(:check_variable_name)
|
252
|
+
visitor.enter_variable_definition += method(:check_variable_name)
|
253
|
+
visitor.enter_parameter_definition += method(:check_variable_name)
|
254
|
+
visitor.enter_typedef_declaration += method(:check_typedef_name)
|
255
|
+
visitor.enter_struct_type_declaration += method(:check_tag_name)
|
256
|
+
visitor.enter_union_type_declaration += method(:check_tag_name)
|
257
|
+
visitor.enter_enum_type_declaration += method(:check_tag_name)
|
258
|
+
visitor.enter_enumerator += method(:check_enumerator_name)
|
259
|
+
visitor.enter_kandr_function_definition += method(:enter_function)
|
260
|
+
visitor.enter_ansi_function_definition += method(:enter_function)
|
261
|
+
visitor.leave_kandr_function_definition += method(:leave_function)
|
262
|
+
visitor.leave_ansi_function_definition += method(:leave_function)
|
263
|
+
@function_def_level = 0
|
264
|
+
end
|
265
|
+
|
266
|
+
private
|
267
|
+
def check_function_name(function_decl)
|
268
|
+
check_object_name(function_decl)
|
269
|
+
end
|
270
|
+
|
271
|
+
def check_variable_name(variable_decl_or_def)
|
272
|
+
check_object_name(variable_decl_or_def)
|
273
|
+
end
|
274
|
+
|
275
|
+
def check_typedef_name(typedef_decl)
|
276
|
+
if typedef_decl.identifier
|
277
|
+
case name = typedef_decl.identifier.value
|
278
|
+
when /\A__/, /\A_[A-Z]/, /\A_/
|
279
|
+
W(:W0809, typedef_decl.location, name)
|
280
|
+
end
|
281
|
+
end
|
282
|
+
end
|
283
|
+
|
284
|
+
def check_tag_name(type_decl)
|
285
|
+
if type_decl.identifier
|
286
|
+
case name = type_decl.identifier.value
|
287
|
+
when /\A__adlint/
|
288
|
+
# NOTE: To ignore AdLint internal tag names.
|
289
|
+
when /\A__/, /\A_[A-Z]/, /\A_/
|
290
|
+
W(:W0809, type_decl.location, name)
|
291
|
+
end
|
292
|
+
end
|
293
|
+
end
|
294
|
+
|
295
|
+
def check_enumerator_name(enumerator)
|
296
|
+
if enumerator.identifier
|
297
|
+
case name = enumerator.identifier.value
|
298
|
+
when /\A__/, /\A_[A-Z]/, /\A_/
|
299
|
+
W(:W0809, enumerator.location, name)
|
300
|
+
end
|
301
|
+
end
|
302
|
+
end
|
303
|
+
|
304
|
+
def enter_function(node)
|
305
|
+
check_object_name(node)
|
306
|
+
@function_def_level += 1
|
307
|
+
end
|
308
|
+
|
309
|
+
def leave_function(node)
|
310
|
+
@function_def_level -= 1
|
311
|
+
end
|
312
|
+
|
313
|
+
def check_object_name(decl_or_def)
|
314
|
+
if decl_or_def.identifier
|
315
|
+
case name = decl_or_def.identifier.value
|
316
|
+
when /\A__/, /\A_[A-Z]/
|
317
|
+
W(:W0809, decl_or_def.location, name)
|
318
|
+
when /\A_/
|
319
|
+
check_filelocal_object_name(name, decl_or_def)
|
320
|
+
end
|
321
|
+
end
|
322
|
+
end
|
323
|
+
|
324
|
+
def check_filelocal_object_name(name, decl_or_def)
|
325
|
+
if @function_def_level == 0
|
326
|
+
storage_class_specifier = decl_or_def.storage_class_specifier
|
327
|
+
if storage_class_specifier && storage_class_specifier.type == :STATIC
|
328
|
+
W(:W0809, decl_or_def.location, name)
|
329
|
+
end
|
330
|
+
end
|
331
|
+
end
|
332
|
+
end
|
333
|
+
|
334
|
+
class W1030 < PassiveMessageDetection
|
335
|
+
def initialize(context)
|
336
|
+
super
|
337
|
+
visitor = context[:c_visitor]
|
338
|
+
visitor.enter_generic_labeled_statement += method(:check)
|
339
|
+
visitor.enter_ansi_function_definition += method(:enter_function)
|
340
|
+
visitor.leave_ansi_function_definition += method(:leave_function)
|
341
|
+
visitor.enter_kandr_function_definition += method(:enter_function)
|
342
|
+
visitor.leave_kandr_function_definition += method(:leave_function)
|
343
|
+
@labels = nil
|
344
|
+
end
|
345
|
+
|
346
|
+
private
|
347
|
+
def check(generic_labeled_statement)
|
348
|
+
return unless @labels
|
349
|
+
|
350
|
+
label = generic_labeled_statement.label
|
351
|
+
if @labels.include?(label.value)
|
352
|
+
W(:W1030, label.location, label.value)
|
353
|
+
else
|
354
|
+
@labels.add(label.value)
|
355
|
+
end
|
356
|
+
end
|
357
|
+
|
358
|
+
def enter_function(node)
|
359
|
+
@labels = Set.new
|
360
|
+
end
|
361
|
+
|
362
|
+
def leave_function(node)
|
363
|
+
@labels = nil
|
364
|
+
end
|
365
|
+
end
|
366
|
+
|
131
367
|
class W1033 < PassiveMessageDetection
|
132
368
|
def initialize(context)
|
133
369
|
super
|
data/lib/adlint/c/metric.rb
CHANGED
@@ -291,6 +291,7 @@ module C #:nodoc:
|
|
291
291
|
interp.on_function_ended += method(:leave_function)
|
292
292
|
interp.on_variable_defined += method(:define_variable)
|
293
293
|
interp.on_parameter_defined += method(:define_variable)
|
294
|
+
interp.on_variable_referred += method(:refer_variable)
|
294
295
|
interp.on_variable_value_referred += method(:read_variable)
|
295
296
|
interp.on_variable_value_updated += method(:write_variable)
|
296
297
|
@current_function = nil
|
@@ -329,6 +330,14 @@ module C #:nodoc:
|
|
329
330
|
end
|
330
331
|
end
|
331
332
|
|
333
|
+
def refer_variable(expression, variable)
|
334
|
+
return unless @current_function
|
335
|
+
|
336
|
+
if variable.named? && @variables[variable.name]
|
337
|
+
@variables[variable.name] += 1
|
338
|
+
end
|
339
|
+
end
|
340
|
+
|
332
341
|
def read_variable(expression, variable)
|
333
342
|
return unless @current_function
|
334
343
|
|
data/lib/adlint/c/object.rb
CHANGED
@@ -661,14 +661,19 @@ module C #:nodoc:
|
|
661
661
|
interpreter.do_conversion(arg, param_type) ||
|
662
662
|
interpreter.temporary_variable(param_type)
|
663
663
|
else
|
664
|
-
|
664
|
+
converted = arg
|
665
665
|
end
|
666
666
|
else
|
667
667
|
converted = interpreter.do_default_argument_promotion(arg)
|
668
|
-
next if arg.type.same_as?(converted.type)
|
669
668
|
end
|
670
669
|
|
671
|
-
|
670
|
+
# NOTE: Value of the argument is referred when the assignment to the
|
671
|
+
# parameter is performed.
|
672
|
+
if arg.variable? && !arg.type.array?
|
673
|
+
interpreter.notify_variable_value_referred(expr, arg)
|
674
|
+
end
|
675
|
+
|
676
|
+
if converted && arg != converted
|
672
677
|
interpreter.notify_implicit_conv_performed(expr, arg, converted)
|
673
678
|
end
|
674
679
|
end
|
@@ -677,26 +682,40 @@ module C #:nodoc:
|
|
677
682
|
def return_values_via_pointer_arguments(interpreter, funcall_expr, args)
|
678
683
|
args.zip(type.parameter_types).each do |(arg, expr), param_type|
|
679
684
|
next if param_type && param_type.void?
|
680
|
-
next unless arg.variable? && arg.
|
685
|
+
next unless arg.variable? && (arg.type.pointer? || arg.type.array?)
|
681
686
|
|
682
687
|
param_type = param_type.unqualify if param_type
|
683
688
|
|
684
|
-
|
685
|
-
|
686
|
-
|
687
|
-
|
688
|
-
|
689
|
-
|
690
|
-
|
691
|
-
|
692
|
-
|
693
|
-
|
694
|
-
|
695
|
-
|
696
|
-
|
697
|
-
|
689
|
+
case
|
690
|
+
when param_type.nil? && (arg.type.pointer? || arg.type.array?),
|
691
|
+
param_type && param_type.pointer? && !param_type.base_type.const?,
|
692
|
+
param_type && param_type.array? && !param_type.base_type.const?
|
693
|
+
else
|
694
|
+
next
|
695
|
+
end
|
696
|
+
|
697
|
+
case
|
698
|
+
when arg.type.pointer?
|
699
|
+
pointee = interpreter.pointee_of(arg)
|
700
|
+
if pointee && pointee.designated_by_lvalue? && pointee.variable?
|
701
|
+
sink = pointee
|
702
|
+
else
|
703
|
+
next
|
698
704
|
end
|
705
|
+
when arg.type.array?
|
706
|
+
sink = arg
|
699
707
|
end
|
708
|
+
|
709
|
+
sink.assign!(sink.type.return_value)
|
710
|
+
interpreter.notify_variable_value_updated(expr, sink)
|
711
|
+
|
712
|
+
# NOTE: Returning a value via a pointer parameter can be considered as
|
713
|
+
# an evaluation of a statement-expression with a
|
714
|
+
# simple-assignment-expression.
|
715
|
+
# Control will reach to a sequence-point at the end of a full
|
716
|
+
# expression.
|
717
|
+
interpreter.notify_sequence_point_reached(
|
718
|
+
SequencePoint.new(funcall_expr, false))
|
700
719
|
end
|
701
720
|
end
|
702
721
|
end
|
@@ -1009,19 +1028,5 @@ module C #:nodoc:
|
|
1009
1028
|
end
|
1010
1029
|
end
|
1011
1030
|
|
1012
|
-
class EnumeratorTable
|
1013
|
-
def initialize
|
1014
|
-
@enumerators = {}
|
1015
|
-
end
|
1016
|
-
|
1017
|
-
def define(enumerator)
|
1018
|
-
@enumerators[enumerator.identifier.value] = enumerator
|
1019
|
-
end
|
1020
|
-
|
1021
|
-
def lookup(name_str)
|
1022
|
-
@enumerators[name_str]
|
1023
|
-
end
|
1024
|
-
end
|
1025
|
-
|
1026
1031
|
end
|
1027
1032
|
end
|
data/lib/adlint/c/parser.rb
CHANGED
@@ -70,7 +70,7 @@ def value_of(token)
|
|
70
70
|
token == "$" ? "EOF" : token.value
|
71
71
|
end
|
72
72
|
|
73
|
-
def
|
73
|
+
def create_unnamed_tag_name(base_token)
|
74
74
|
Token.new(:IDENTIFIER, "__adlint__unnamed_#{@unnamed_type_no += 1}",
|
75
75
|
base_token.location)
|
76
76
|
end
|
@@ -2342,7 +2342,7 @@ module_eval(<<'.,.,', 'parser.y', 904)
|
|
2342
2342
|
def _reduce_126(val, _values, result)
|
2343
2343
|
checkpoint(val[0].location)
|
2344
2344
|
|
2345
|
-
result = StructSpecifier.new(
|
2345
|
+
result = StructSpecifier.new(create_unnamed_tag_name(val[0]), val[2])
|
2346
2346
|
result.head_token = val[0]
|
2347
2347
|
result.tail_token = val[3]
|
2348
2348
|
|
@@ -2354,7 +2354,7 @@ module_eval(<<'.,.,', 'parser.y', 912)
|
|
2354
2354
|
def _reduce_127(val, _values, result)
|
2355
2355
|
checkpoint(val[0].location)
|
2356
2356
|
|
2357
|
-
result = StructSpecifier.new(
|
2357
|
+
result = StructSpecifier.new(create_unnamed_tag_name(val[0]), [])
|
2358
2358
|
result.head_token = val[0]
|
2359
2359
|
result.tail_token = val[2]
|
2360
2360
|
|
@@ -2366,7 +2366,7 @@ module_eval(<<'.,.,', 'parser.y', 920)
|
|
2366
2366
|
def _reduce_128(val, _values, result)
|
2367
2367
|
checkpoint(val[0].location)
|
2368
2368
|
|
2369
|
-
result = UnionSpecifier.new(
|
2369
|
+
result = UnionSpecifier.new(create_unnamed_tag_name(val[0]), val[2])
|
2370
2370
|
result.head_token = val[0]
|
2371
2371
|
result.tail_token = val[3]
|
2372
2372
|
|
@@ -2378,7 +2378,7 @@ module_eval(<<'.,.,', 'parser.y', 928)
|
|
2378
2378
|
def _reduce_129(val, _values, result)
|
2379
2379
|
checkpoint(val[0].location)
|
2380
2380
|
|
2381
|
-
result = UnionSpecifier.new(
|
2381
|
+
result = UnionSpecifier.new(create_unnamed_tag_name(val[0]), [])
|
2382
2382
|
result.head_token = val[0]
|
2383
2383
|
result.tail_token = val[2]
|
2384
2384
|
|
@@ -2578,7 +2578,7 @@ module_eval(<<'.,.,', 'parser.y', 1076)
|
|
2578
2578
|
def _reduce_146(val, _values, result)
|
2579
2579
|
checkpoint(val[0].location)
|
2580
2580
|
|
2581
|
-
result = EnumSpecifier.new(
|
2581
|
+
result = EnumSpecifier.new(create_unnamed_tag_name(val[0]), val[2])
|
2582
2582
|
result.head_token = val[0]
|
2583
2583
|
result.tail_token = val[3]
|
2584
2584
|
|
@@ -2602,7 +2602,7 @@ module_eval(<<'.,.,', 'parser.y', 1092)
|
|
2602
2602
|
def _reduce_148(val, _values, result)
|
2603
2603
|
checkpoint(val[0].location)
|
2604
2604
|
|
2605
|
-
result = EnumSpecifier.new(
|
2605
|
+
result = EnumSpecifier.new(create_unnamed_tag_name(val[0]), val[2])
|
2606
2606
|
result.head_token = val[0]
|
2607
2607
|
result.tail_token = val[4]
|
2608
2608
|
|
data/lib/adlint/c/parser.y
CHANGED
@@ -904,7 +904,7 @@ struct_or_union_specifier
|
|
904
904
|
{
|
905
905
|
checkpoint(val[0].location)
|
906
906
|
|
907
|
-
result = StructSpecifier.new(
|
907
|
+
result = StructSpecifier.new(create_unnamed_tag_name(val[0]), val[2])
|
908
908
|
result.head_token = val[0]
|
909
909
|
result.tail_token = val[3]
|
910
910
|
}
|
@@ -912,7 +912,7 @@ struct_or_union_specifier
|
|
912
912
|
{
|
913
913
|
checkpoint(val[0].location)
|
914
914
|
|
915
|
-
result = StructSpecifier.new(
|
915
|
+
result = StructSpecifier.new(create_unnamed_tag_name(val[0]), [])
|
916
916
|
result.head_token = val[0]
|
917
917
|
result.tail_token = val[2]
|
918
918
|
}
|
@@ -920,7 +920,7 @@ struct_or_union_specifier
|
|
920
920
|
{
|
921
921
|
checkpoint(val[0].location)
|
922
922
|
|
923
|
-
result = UnionSpecifier.new(
|
923
|
+
result = UnionSpecifier.new(create_unnamed_tag_name(val[0]), val[2])
|
924
924
|
result.head_token = val[0]
|
925
925
|
result.tail_token = val[3]
|
926
926
|
}
|
@@ -928,7 +928,7 @@ struct_or_union_specifier
|
|
928
928
|
{
|
929
929
|
checkpoint(val[0].location)
|
930
930
|
|
931
|
-
result = UnionSpecifier.new(
|
931
|
+
result = UnionSpecifier.new(create_unnamed_tag_name(val[0]), [])
|
932
932
|
result.head_token = val[0]
|
933
933
|
result.tail_token = val[2]
|
934
934
|
}
|
@@ -1076,7 +1076,7 @@ enum_specifier
|
|
1076
1076
|
{
|
1077
1077
|
checkpoint(val[0].location)
|
1078
1078
|
|
1079
|
-
result = EnumSpecifier.new(
|
1079
|
+
result = EnumSpecifier.new(create_unnamed_tag_name(val[0]), val[2])
|
1080
1080
|
result.head_token = val[0]
|
1081
1081
|
result.tail_token = val[3]
|
1082
1082
|
}
|
@@ -1092,7 +1092,7 @@ enum_specifier
|
|
1092
1092
|
{
|
1093
1093
|
checkpoint(val[0].location)
|
1094
1094
|
|
1095
|
-
result = EnumSpecifier.new(
|
1095
|
+
result = EnumSpecifier.new(create_unnamed_tag_name(val[0]), val[2])
|
1096
1096
|
result.head_token = val[0]
|
1097
1097
|
result.tail_token = val[4]
|
1098
1098
|
}
|
@@ -2078,7 +2078,7 @@ def value_of(token)
|
|
2078
2078
|
token == "$" ? "EOF" : token.value
|
2079
2079
|
end
|
2080
2080
|
|
2081
|
-
def
|
2081
|
+
def create_unnamed_tag_name(base_token)
|
2082
2082
|
Token.new(:IDENTIFIER, "__adlint__unnamed_#{@unnamed_type_no += 1}",
|
2083
2083
|
base_token.location)
|
2084
2084
|
end
|