adlint 1.0.0 → 1.2.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 (54) hide show
  1. data/AUTHORS +3 -2
  2. data/ChangeLog +208 -63
  3. data/MANIFEST +4 -0
  4. data/NEWS +24 -5
  5. data/etc/conf.d/fallback/traits.erb +1 -1
  6. data/etc/conf.d/i686-cygwin/traits-gcc_4.3.4.erb +1 -1
  7. data/etc/conf.d/i686-devkit/traits-gcc_4.5.2.erb +1 -1
  8. data/etc/conf.d/i686-linux/traits-gcc_4.5.1.erb +1 -1
  9. data/etc/conf.d/i686-mingw/traits-gcc_4.6.1.erb +1 -1
  10. data/etc/mesg.d/en_US/messages.yml +3 -3
  11. data/etc/mesg.d/ja_JP/messages.yml +4 -4
  12. data/lib/adlint/c/builtin.rb +3 -3
  13. data/lib/adlint/c/ctrlexpr.rb +7 -11
  14. data/lib/adlint/c/expr.rb +548 -363
  15. data/lib/adlint/c/interp.rb +233 -525
  16. data/lib/adlint/c/mediator.rb +1 -0
  17. data/lib/adlint/c/message.rb +144 -1
  18. data/lib/adlint/c/object.rb +15 -6
  19. data/lib/adlint/c/parser.rb +170 -128
  20. data/lib/adlint/c/parser.y +36 -0
  21. data/lib/adlint/c/phase.rb +4 -0
  22. data/lib/adlint/c/seqp.rb +72 -0
  23. data/lib/adlint/c/syntax.rb +254 -3
  24. data/lib/adlint/c.rb +1 -0
  25. data/lib/adlint/cpp/code.rb +2 -2
  26. data/lib/adlint/cpp/eval.rb +29 -13
  27. data/lib/adlint/cpp/message.rb +71 -70
  28. data/lib/adlint/cpp/message_shima.rb +100 -0
  29. data/lib/adlint/cpp/phase.rb +4 -0
  30. data/lib/adlint/cpp/syntax.rb +5 -1
  31. data/lib/adlint/cpp.rb +1 -0
  32. data/lib/adlint/message.rb +6 -3
  33. data/lib/adlint/traits.rb +1 -1
  34. data/lib/adlint/version.rb +5 -5
  35. data/share/demo/Makefile +3 -1
  36. data/share/demo/bad_line/bad_line.c +27 -0
  37. data/share/demo/sequence_point/sequence_point.c +31 -0
  38. data/share/doc/adlint_on_vim_en.png +0 -0
  39. data/share/doc/adlint_on_vim_ja.png +0 -0
  40. data/share/doc/developers_guide_ja.html +3 -3
  41. data/share/doc/developers_guide_ja.texi +1 -1
  42. data/share/doc/users_guide_en.html +3118 -41
  43. data/share/doc/users_guide_en.texi +3090 -37
  44. data/share/doc/users_guide_ja.html +3120 -47
  45. data/share/doc/users_guide_ja.texi +3106 -65
  46. data/share/sample/ctags-5.8/adlint/GNUmakefile +13 -1
  47. data/share/sample/ctags-5.8/adlint/adlint_cinit.h +14 -2
  48. data/share/sample/ctags-5.8/adlint/adlint_pinit.h +14 -4
  49. data/share/sample/ctags-5.8/adlint/adlint_traits.yml +14 -1
  50. data/share/sample/flex-2.5.35/adlint/GNUmakefile +13 -1
  51. data/share/sample/flex-2.5.35/adlint/adlint_cinit.h +14 -2
  52. data/share/sample/flex-2.5.35/adlint/adlint_pinit.h +14 -4
  53. data/share/sample/flex-2.5.35/adlint/adlint_traits.yml +14 -1
  54. metadata +6 -2
@@ -852,6 +852,7 @@ type_specifier
852
852
  {
853
853
  checkpoint(val[0].location)
854
854
 
855
+ val[2].full = true
855
856
  result = TypeofTypeSpecifier.new(val[2], nil)
856
857
  result.head_token = val[0]
857
858
  result.tail_token = val[3]
@@ -1054,6 +1055,7 @@ struct_declarator
1054
1055
  {
1055
1056
  checkpoint(val[0].location)
1056
1057
 
1058
+ val[1].full = true
1057
1059
  result = StructDeclarator.new(nil, val[1])
1058
1060
  result.head_token = val[0]
1059
1061
  result.tail_token = val[1].tail_token
@@ -1062,6 +1064,7 @@ struct_declarator
1062
1064
  {
1063
1065
  checkpoint(val[0].location)
1064
1066
 
1067
+ val[2].full = true
1065
1068
  result = StructDeclarator.new(val[0], val[2])
1066
1069
  result.head_token = val[0].head_token
1067
1070
  result.tail_token = val[2].tail_token
@@ -1139,6 +1142,7 @@ enumerator
1139
1142
  {
1140
1143
  checkpoint(val[0].location)
1141
1144
 
1145
+ val[2].full = true
1142
1146
  symbol = @symbol_table.create_new_symbol(EnumeratorName, val[0])
1143
1147
  result = Enumerator.new(val[0], val[2], symbol)
1144
1148
  result.head_token = val[0]
@@ -1164,8 +1168,15 @@ declarator
1164
1168
  result = val[1]
1165
1169
  result.pointer = val[0]
1166
1170
  result.head_token = val[0].first
1171
+ result.full = true
1167
1172
  }
1168
1173
  | direct_declarator
1174
+ {
1175
+ checkpoint(val[0].location)
1176
+
1177
+ result = val[0]
1178
+ result.full = true
1179
+ }
1169
1180
  ;
1170
1181
 
1171
1182
  direct_declarator
@@ -1190,6 +1201,7 @@ direct_declarator
1190
1201
  {
1191
1202
  checkpoint(val[0].location)
1192
1203
 
1204
+ val[3].full = true
1193
1205
  result = ArrayDeclarator.new(val[0], val[3])
1194
1206
  result.head_token = val[0].head_token
1195
1207
  result.tail_token = val[4]
@@ -1206,6 +1218,7 @@ direct_declarator
1206
1218
  {
1207
1219
  checkpoint(val[0].location)
1208
1220
 
1221
+ val[2].full = true
1209
1222
  result = ArrayDeclarator.new(val[0], val[2])
1210
1223
  result.head_token = val[0].head_token
1211
1224
  result.tail_token = val[3]
@@ -1215,6 +1228,7 @@ direct_declarator
1215
1228
  {
1216
1229
  checkpoint(val[0].location)
1217
1230
 
1231
+ val[3].full = true
1218
1232
  result = ArrayDeclarator.new(val[0], val[4])
1219
1233
  result.head_token = val[0].head_token
1220
1234
  result.tail_token = val[5]
@@ -1224,6 +1238,7 @@ direct_declarator
1224
1238
  {
1225
1239
  checkpoint(val[0].location)
1226
1240
 
1241
+ val[4].full = true
1227
1242
  result = ArrayDeclarator.new(val[0], val[4])
1228
1243
  result.head_token = val[0].head_token
1229
1244
  result.tail_token = val[5]
@@ -1429,6 +1444,7 @@ abstract_declarator
1429
1444
  result = PointerAbstractDeclarator.new(nil, val[0])
1430
1445
  result.head_token = val[0].first
1431
1446
  result.tail_token = val[0].last
1447
+ result.full = true
1432
1448
  }
1433
1449
  | pointer direct_abstract_declarator
1434
1450
  {
@@ -1437,8 +1453,15 @@ abstract_declarator
1437
1453
  result = PointerAbstractDeclarator.new(val[1], val[0])
1438
1454
  result.head_token = val[0].first
1439
1455
  result.tail_token = val[1].tail_token
1456
+ result.full = true
1440
1457
  }
1441
1458
  | direct_abstract_declarator
1459
+ {
1460
+ checkpoint(val[0].location)
1461
+
1462
+ result = val[0]
1463
+ result.full = true
1464
+ }
1442
1465
  ;
1443
1466
 
1444
1467
  direct_abstract_declarator
@@ -1468,6 +1491,7 @@ direct_abstract_declarator
1468
1491
 
1469
1492
  @lexer.start_identifier_translation
1470
1493
 
1494
+ val[1].full = true
1471
1495
  result = ArrayAbstractDeclarator.new(nil, val[1])
1472
1496
  result.head_token = val[0]
1473
1497
  result.tail_token = val[2]
@@ -1484,6 +1508,7 @@ direct_abstract_declarator
1484
1508
  {
1485
1509
  checkpoint(val[0].location)
1486
1510
 
1511
+ val[2].full = true
1487
1512
  result = ArrayAbstractDeclarator.new(val[0], val[2])
1488
1513
  result.head_token = val[0].head_token
1489
1514
  result.tail_token = val[3]
@@ -1549,6 +1574,7 @@ initializer
1549
1574
  {
1550
1575
  checkpoint(val[0].location)
1551
1576
 
1577
+ val[0].full = true
1552
1578
  result = Initializer.new(val[0], nil)
1553
1579
  result.head_token = val[0].head_token
1554
1580
  result.tail_token = val[0].tail_token
@@ -1645,6 +1671,7 @@ labeled_statement
1645
1671
  {
1646
1672
  checkpoint(val[0].location)
1647
1673
 
1674
+ val[1].full = true
1648
1675
  result = CaseLabeledStatement.new(val[1], val[3])
1649
1676
  result.head_token = val[0]
1650
1677
  result.tail_token = val[3].tail_token
@@ -1711,6 +1738,7 @@ expression_statement
1711
1738
  {
1712
1739
  checkpoint(val[0].location)
1713
1740
 
1741
+ val[0].full = true
1714
1742
  result = ExpressionStatement.new(val[0])
1715
1743
  result.head_token = val[0].head_token
1716
1744
  result.tail_token = val[1]
@@ -1722,6 +1750,7 @@ selection_statement
1722
1750
  {
1723
1751
  checkpoint(val[0].location)
1724
1752
 
1753
+ val[2].full = true
1725
1754
  result = IfStatement.new(val[2], val[4], val[3])
1726
1755
  result.head_token = val[0]
1727
1756
  result.tail_token = val[4].tail_token
@@ -1730,6 +1759,7 @@ selection_statement
1730
1759
  {
1731
1760
  checkpoint(val[0].location)
1732
1761
 
1762
+ val[2].full = true
1733
1763
  result = IfElseStatement.new(val[2], val[4], val[6], val[3], val[5])
1734
1764
  result.head_token = val[0]
1735
1765
  result.tail_token = val[6].tail_token
@@ -1738,6 +1768,7 @@ selection_statement
1738
1768
  {
1739
1769
  checkpoint(val[0].location)
1740
1770
 
1771
+ val[2].full = true
1741
1772
  result = SwitchStatement.new(val[2], val[4])
1742
1773
  result.head_token = val[0]
1743
1774
  result.tail_token = val[4].tail_token
@@ -1749,6 +1780,7 @@ iteration_statement
1749
1780
  {
1750
1781
  checkpoint(val[0].location)
1751
1782
 
1783
+ val[2].full = true
1752
1784
  result = WhileStatement.new(val[2], val[4], val[3])
1753
1785
  result.head_token = val[0]
1754
1786
  result.tail_token = val[4].tail_token
@@ -1757,6 +1789,7 @@ iteration_statement
1757
1789
  {
1758
1790
  checkpoint(val[0].location)
1759
1791
 
1792
+ val[4].full = true
1760
1793
  result = DoStatement.new(val[1], val[4], val[0], val[2])
1761
1794
  result.head_token = val[0]
1762
1795
  result.tail_token = val[6]
@@ -1774,6 +1807,7 @@ iteration_statement
1774
1807
  {
1775
1808
  checkpoint(val[0].location)
1776
1809
 
1810
+ val[4].full = true
1777
1811
  result = ForStatement.new(val[2], val[3], val[4], val[6], val[5])
1778
1812
  result.head_token = val[0]
1779
1813
  result.tail_token = val[6].tail_token
@@ -1790,6 +1824,7 @@ iteration_statement
1790
1824
  {
1791
1825
  checkpoint(val[0].location)
1792
1826
 
1827
+ val[4].full = true
1793
1828
  result = C99ForStatement.new(val[2], val[3], val[4], val[6], val[5])
1794
1829
  result.head_token = val[0]
1795
1830
  result.tail_token = val[6].tail_token
@@ -1842,6 +1877,7 @@ jump_statement
1842
1877
  {
1843
1878
  checkpoint(val[0].location)
1844
1879
 
1880
+ val[1].full = true
1845
1881
  result = ReturnStatement.new(val[1])
1846
1882
  result.head_token = val[0]
1847
1883
  result.tail_token = val[2]
@@ -558,6 +558,10 @@ module C #:nodoc:
558
558
  W0583.new(context),
559
559
  W0584.new(context),
560
560
  W0585.new(context),
561
+ W0597.new(context),
562
+ W0598.new(context),
563
+ W0599.new(context),
564
+ W0600.new(context),
561
565
  W0605.new(context),
562
566
  W0609.new(context),
563
567
  W0610.new(context),
@@ -0,0 +1,72 @@
1
+ # Sequence points of C language evaluation.
2
+ #
3
+ # Author:: Yutaka Yanoh <mailto:yanoh@users.sourceforge.net>
4
+ # Copyright:: Copyright (C) 2010-2012, OGIS-RI Co.,Ltd.
5
+ # License:: GPLv3+: GNU General Public License version 3 or later
6
+ #
7
+ # Owner:: Yutaka Yanoh <mailto:yanoh@users.sourceforge.net>
8
+
9
+ #--
10
+ # ___ ____ __ ___ _________
11
+ # / | / _ |/ / / / | / /__ __/ Source Code Static Analyzer
12
+ # / /| | / / / / / / / |/ / / / AdLint - Advanced Lint
13
+ # / __ |/ /_/ / /___/ / /| / / /
14
+ # /_/ |_|_____/_____/_/_/ |_/ /_/ Copyright (C) 2010-2012, OGIS-RI Co.,Ltd.
15
+ #
16
+ # This file is part of AdLint.
17
+ #
18
+ # AdLint is free software: you can redistribute it and/or modify it under the
19
+ # terms of the GNU General Public License as published by the Free Software
20
+ # Foundation, either version 3 of the License, or (at your option) any later
21
+ # version.
22
+ #
23
+ # AdLint is distributed in the hope that it will be useful, but WITHOUT ANY
24
+ # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
25
+ # A PARTICULAR PURPOSE. See the GNU General Public License for more details.
26
+ #
27
+ # You should have received a copy of the GNU General Public License along with
28
+ # AdLint. If not, see <http://www.gnu.org/licenses/>.
29
+ #
30
+ #++
31
+
32
+ module AdLint #:nodoc:
33
+ module C #:nodoc:
34
+
35
+ # NOTE: The ISO C99 standard saids;
36
+ #
37
+ # Annex C (informative) Sequence points
38
+ #
39
+ # 1 The following are the sequence points described in 5.1.2.3:
40
+ #
41
+ # -- The call to a function, after the arguments have been evaluated
42
+ # (6.5.2.2).
43
+ # -- The end of the first operand of the following operators: logical AND
44
+ # && (6.5.13); logical OR || (6.5.14); conditional ? (6.5.15); comma ,
45
+ # (6.5.17).
46
+ # -- The end of a full declarator: declarators (6.7.5).
47
+ # -- The end of a full expression: an initializer (6.7.8); the expression
48
+ # in an expression statement (6.8.3); the controlling expression of a
49
+ # while or do statement (6.8.5); each of the expressions of a for
50
+ # statement (6.8.5.3); the expression in a return statement (6.8.6.4).
51
+ # -- Immediately before a library function returns (7.1.4).
52
+ # -- After the actions associated with each formatted input/output function
53
+ # conversion specifier (7.19.6, 7.24.2).
54
+ # -- Immediately before and immediately after each call to a comparison
55
+ # function, and also between any call to a comparison function and any
56
+ # movement of the objects passed as arguments to that call (7.20.5).
57
+
58
+ class SequencePoint
59
+ def initialize(last_node, obvious = true)
60
+ @last_node = last_node
61
+ @obvious = obvious
62
+ end
63
+
64
+ attr_reader :last_node
65
+
66
+ def obvious?
67
+ @obvious
68
+ end
69
+ end
70
+
71
+ end
72
+ end
@@ -31,20 +31,142 @@
31
31
 
32
32
  require "adlint/symbol"
33
33
  require "adlint/util"
34
+ require "adlint/c/seqp"
34
35
 
35
36
  module AdLint #:nodoc:
36
37
  module C #:nodoc:
37
38
 
39
+ # == DESCRIPTION
40
+ # === SyntaxNode class hierarchy
41
+ # SyntaxNode
42
+ # <--- Expression
43
+ # <--- ErrorExpression
44
+ # <--- PrimaryExpression
45
+ # <--- ObjectSpecifier
46
+ # <--- ConstantSpecifier
47
+ # <--- StringLiteralSpecifier
48
+ # <--- NullConstantSpecifier
49
+ # <--- GroupedExpression
50
+ # <--- PostfixExpression
51
+ # <--- ArraySubscriptExpression
52
+ # <--- FunctionCallExpression
53
+ # <--- MemberAccessByValueExpression
54
+ # <--- MemberAccessByPointerExpression
55
+ # <--- BitAccessByValueExpression
56
+ # <--- BitAccessByPointerExpression
57
+ # <--- PostfixIncrementExpression
58
+ # <--- PostfixDecrementExpression
59
+ # <--- CompoundLiteralExpression
60
+ # <--- UnaryExpression
61
+ # <--- PrefixIncrementExpression
62
+ # <--- PrefixDecrementExpression
63
+ # <--- AddressExpression
64
+ # <--- IndirectionExpression
65
+ # <--- UnaryArithmeticExpression
66
+ # <--- SizeofExpression
67
+ # <--- SizeofTypeExpression
68
+ # <--- AlignofExpression
69
+ # <--- AlignofTypeExpression
70
+ # <--- CastExpression
71
+ # <--- BinaryExpression
72
+ # <--- MultiplicativeExpression
73
+ # <--- AdditiveExpression
74
+ # <--- ShiftExpression
75
+ # <--- RelationalExpression
76
+ # <--- EqualityExpression
77
+ # <--- AndExpression
78
+ # <--- ExclusiveOrExpression
79
+ # <--- InclusiveOrExpression
80
+ # <--- LogicalAndExpression
81
+ # <--- LogicalOrExpression
82
+ # <--- ConditionalExpression
83
+ # <--- SimpleAssignmentExpression
84
+ # <--- CompoundAssignmentExpression
85
+ # <--- CommaSeparatedExpression
86
+ # <--- Declaration
87
+ # <--- FunctionDeclaration -------------------- SymbolicElement <<module>>
88
+ # <--- VariableDeclaration ----------------------+ | | | |
89
+ # <--- Definition | | | |
90
+ # <--- VariableDefinition -------------------+ | | |
91
+ # <--- PseudoVariableDefinition | | |
92
+ # <--- FunctionDefinition ----------------------+ | |
93
+ # <--- KandRFunctionDefinition | |
94
+ # <--- AnsiFunctionDefinition | |
95
+ # <--- ParameterDefinition | |
96
+ # <--- TypeDeclaration -----------------------------------+ |
97
+ # <--- TypedefDeclaration |
98
+ # <--- StructTypeDeclaration |
99
+ # <--- PseudoStructTypeDeclaration |
100
+ # <--- UnionTypeDeclaration |
101
+ # <--- PseudoUnionTypeDeclaration |
102
+ # <--- EnumTypeDeclaration |
103
+ # <--- PseudoEnumTypeDeclaration |
104
+ # <--- DeclarationSpecifiers |
105
+ # <--- InitDeclarator |
106
+ # <--- TypeSpecifier |
107
+ # <--- StandardTypeSpecifier |
108
+ # <--- TypedefTypeSpecifier |
109
+ # <--- StructSpecifier |
110
+ # <--- UnionSpecifier |
111
+ # <--- TypeofTypeSpecifier |
112
+ # <--- StructDeclaration |
113
+ # <--- MemberDeclaration |
114
+ # <--- SpecifierQualifierList |
115
+ # <--- StructDeclarator |
116
+ # <--- EnumSpecifier |
117
+ # <--- Enumerator -------------------------------------------+
118
+ # <--- Declarator
119
+ # <--- IdentifierDeclarator
120
+ # <--- GroupedDeclarator
121
+ # <--- ArrayDeclarator
122
+ # <--- FunctionDeclarator
123
+ # <--- AnsiFunctionDeclarator
124
+ # <--- KandRFunctionDeclarator
125
+ # <--- AbbreviatedFunctionDeclarator
126
+ # <--- AbstractDeclarator
127
+ # <--- PointerAbstractDeclarator
128
+ # <--- GroupedAbstractDeclarator
129
+ # <--- ArrayAbstractDeclarator
130
+ # <--- FunctionAbstractDeclarator
131
+ # <--- ParameterTypeList
132
+ # <--- ParameterDeclaration
133
+ # <--- Statement
134
+ # <--- ErrorStatement
135
+ # <--- LabeledStatement
136
+ # <--- GenericLabeledStatement
137
+ # <--- CaseLabeledStatement
138
+ # <--- DefaultLabeledStatement
139
+ # <--- CompoundStatement
140
+ # <--- ExpressionStatement
141
+ # <--- SelectionStatement
142
+ # <--- IfStatement
143
+ # <--- IfElseStatement
144
+ # <--- SwitchStatement
145
+ # <--- IterationStatement
146
+ # <--- WhileStatement
147
+ # <--- DoStatement
148
+ # <--- ForStatement
149
+ # <--- C99ForStatement
150
+ # <--- JumpStatement
151
+ # <--- GotoStatement
152
+ # <--- ContinueStatement
153
+ # <--- BreakStatement
154
+ # <--- ReturnStatement
155
+ # <--- TranslationUnit
156
+ # <--- TypeName
157
+ # <--- Initializer
38
158
  class SyntaxNode
39
159
  include Visitable
40
160
 
41
161
  def initialize
42
162
  @head_token = nil
43
163
  @tail_token = nil
164
+ @subsequent_sequence_point = nil
44
165
  end
45
166
 
46
167
  attr_accessor :head_token
47
168
  attr_accessor :tail_token
169
+ attr_reader :subsequent_sequence_point
48
170
 
49
171
  def location
50
172
  subclass_responsibility
@@ -65,6 +187,19 @@ module C #:nodoc:
65
187
  def short_class_name
66
188
  self.class.name.sub(/\A.*::/, "")
67
189
  end
190
+
191
+ protected
192
+ # === DESCRIPTION
193
+ # Append a subsequent sequence-point of this node.
194
+ def append_sequence_point!
195
+ @subsequent_sequence_point = SequencePoint.new(self)
196
+ end
197
+
198
+ # === DESCRIPTION
199
+ # Delete a subsequent sequence-point of this node.
200
+ def delete_sequence_point!
201
+ @subsequent_sequence_point = nil
202
+ end
68
203
  end
69
204
 
70
205
  module SyntaxNodeCollector
@@ -246,6 +381,32 @@ module C #:nodoc:
246
381
  end
247
382
 
248
383
  class Expression < SyntaxNode
384
+ def initialize
385
+ super
386
+ @full = false
387
+ end
388
+
389
+ def full=(full_expression)
390
+ @full = full_expression
391
+
392
+ # NOTE: The ISO C99 standard saids;
393
+ #
394
+ # Annex C (informative) Sequence points
395
+ #
396
+ # 1 The following are the sequence points described in 5.1.2.3:
397
+ #
398
+ # -- The end of a full expression: an initializer (6.7.8); the
399
+ # expression in an expression statement (6.8.3); the controlling
400
+ # expression of a while or do statement (6.8.5); each of the
401
+ # expressions of a for statement (6.8.5.3); the expression in a
402
+ # return statement (6.8.6.4).
403
+ if full_expression
404
+ append_sequence_point!
405
+ else
406
+ delete_sequence_point!
407
+ end
408
+ end
409
+
249
410
  def have_side_effect?
250
411
  subclass_responsibility
251
412
  end
@@ -801,9 +962,41 @@ module C #:nodoc:
801
962
 
802
963
  class InclusiveOrExpression < BinaryExpression; end
803
964
 
804
- class LogicalAndExpression < BinaryExpression; end
965
+ class LogicalAndExpression < BinaryExpression
966
+ def initialize(operator, lhs_operand, rhs_operand)
967
+ super
968
+
969
+ # NOTE: The ISO C99 standard saids;
970
+ #
971
+ # 6.5.13 Logical AND operator
972
+ #
973
+ # Semantics
974
+ #
975
+ # 4 Unlike the bitwise binary & operator, the && operator guarantees
976
+ # left-to-right evaluation; there is a sequence point after the
977
+ # evaluation of the first operand. If the first operand compares equal
978
+ # to 0, the second operand is not evaluated.
979
+ @lhs_operand.append_sequence_point!
980
+ end
981
+ end
982
+
983
+ class LogicalOrExpression < BinaryExpression
984
+ def initialize(operator, lhs_operand, rhs_operand)
985
+ super
805
986
 
806
- class LogicalOrExpression < BinaryExpression; end
987
+ # NOTE: The ISO C99 standard saids;
988
+ #
989
+ # 6.5.14 Logical OR operator
990
+ #
991
+ # Semantics
992
+ #
993
+ # 4 Unlike the bitwise | operator, the || operator guarantees
994
+ # left-to-right evaluation; there is a sequence point after the
995
+ # evaluation of the first operand. If the first operand compares
996
+ # unequal to 0, the second operand is not evaluated.
997
+ @lhs_operand.append_sequence_point!
998
+ end
999
+ end
807
1000
 
808
1001
  class ConditionalExpression < Expression
809
1002
  def initialize(condition, then_expression, else_expression, question_mark)
@@ -812,6 +1005,22 @@ module C #:nodoc:
812
1005
  @then_expression = then_expression
813
1006
  @else_expression = else_expression
814
1007
  @question_mark = question_mark
1008
+
1009
+ # NOTE: The ISO C99 standard saids;
1010
+ #
1011
+ # 6.5.15 Conditional operator
1012
+ #
1013
+ # Semantics
1014
+ #
1015
+ # 4 The first operand is evaluated; there is a sequence poit after its
1016
+ # evaluation. The second operand is evaluated only if the first
1017
+ # compares unequal to 0; the third operand is evaluated only if the
1018
+ # first compares equal to 0; thre result is the value of the second or
1019
+ # third operand (whichever is evaluated), converted to the type
1020
+ # described below. If an attempt is made to modify the result of a
1021
+ # conditional operator or to access it after the next sequence point,
1022
+ # the behavior is undefined.
1023
+ @condition.append_sequence_point!
815
1024
  end
816
1025
 
817
1026
  attr_reader :condition
@@ -856,7 +1065,8 @@ module C #:nodoc:
856
1065
  class CommaSeparatedExpression < Expression
857
1066
  def initialize(first_expression)
858
1067
  super()
859
- @expressions = [first_expression]
1068
+ @expressions = []
1069
+ push(first_expression)
860
1070
  end
861
1071
 
862
1072
  attr_reader :expressions
@@ -875,6 +1085,19 @@ module C #:nodoc:
875
1085
 
876
1086
  def push(expression)
877
1087
  @expressions.push(expression)
1088
+
1089
+ # NOTE: The ISO C99 standard saids;
1090
+ #
1091
+ # 6.5.17 Comma operator
1092
+ #
1093
+ # Semantics
1094
+ #
1095
+ # 2 The left operand of a comma operator is evaluated as a void
1096
+ # expression; there is a sequence point after its evaluation. Then the
1097
+ # right operand is evaluated; the result has its type and value. If an
1098
+ # attempt is made to modify the result of a comma operator or to access
1099
+ # it after the next sequence point, the behavior is undefined.
1100
+ @expressions[-2].append_sequence_point! if @expressions.size > 1
878
1101
  self
879
1102
  end
880
1103
 
@@ -1644,6 +1867,7 @@ module C #:nodoc:
1644
1867
  def initialize
1645
1868
  super
1646
1869
  @pointer = nil
1870
+ @full = false
1647
1871
  end
1648
1872
 
1649
1873
  attr_accessor :pointer
@@ -1656,6 +1880,33 @@ module C #:nodoc:
1656
1880
  false
1657
1881
  end
1658
1882
 
1883
+ def full=(full_declarator)
1884
+ @full = full_declarator
1885
+
1886
+ # NOTE: The ISO C99 standard saids;
1887
+ #
1888
+ # 6.7.5 Declarators
1889
+ #
1890
+ # Semantics
1891
+ #
1892
+ # 3 A full declarator is a declarator that is not part of another
1893
+ # declarator. The end of a full declarator is a sequence point. If,
1894
+ # in the nested sequence of declarators in a full declarator, there is
1895
+ # a declarator specifying a variable length array type, the type
1896
+ # specified by the full declarator is said to be variably modified.
1897
+ # Furthermore, any type derived by declarator type derivation from a
1898
+ # variably modified type is itself variably modified.
1899
+ if full_declarator
1900
+ append_sequence_point!
1901
+ else
1902
+ delete_sequence_point!
1903
+ end
1904
+ end
1905
+
1906
+ def full?
1907
+ @full
1908
+ end
1909
+
1659
1910
  def base
1660
1911
  subclass_responsibility
1661
1912
  end
data/lib/adlint/c.rb CHANGED
@@ -50,6 +50,7 @@ require "adlint/c/phase"
50
50
  require "adlint/c/resolver"
51
51
  require "adlint/c/scanner"
52
52
  require "adlint/c/scope"
53
+ require "adlint/c/seqp"
53
54
  require "adlint/c/syntax"
54
55
  require "adlint/c/type"
55
56
  require "adlint/c/util"
@@ -166,7 +166,7 @@ module Cpp #:nodoc:
166
166
 
167
167
  def extract_line(line_line)
168
168
  PP_DIRECTIVE(line_line.location, line_line.keyword.value,
169
- line_line.pp_tokens.tokens.map { |t| t.value }.join(" "))
169
+ line_line.pp_tokens ? line_line.pp_tokens.to_s : "")
170
170
  end
171
171
 
172
172
  def extract_error(error_line)
@@ -176,7 +176,7 @@ module Cpp #:nodoc:
176
176
 
177
177
  def extract_pragma(pragma_line)
178
178
  PP_DIRECTIVE(pragma_line.location, pragma_line.keyword.value,
179
- pragma_line.pp_tokens.tokens.map { |t| t.value }.join(" "))
179
+ pragma_line.pp_tokens ? pragma_line.pp_tokens.to_s : "")
180
180
  end
181
181
 
182
182
  def extract_null(null_directive)