adlint 1.0.0 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
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)