adlint 3.0.4 → 3.0.8

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 (73) hide show
  1. data/ChangeLog +374 -13
  2. data/INSTALL +1 -3
  3. data/MANIFEST +12 -0
  4. data/NEWS +30 -4
  5. data/README +0 -4
  6. data/TODO +2 -1
  7. data/etc/mesg.d/c_builtin/en_US/messages.yml +2 -2
  8. data/etc/mesg.d/c_builtin/ja_JP/messages.yml +2 -2
  9. data/etc/mesg.d/core/en_US/messages.yml +5 -1
  10. data/etc/mesg.d/core/ja_JP/messages.yml +5 -1
  11. data/features/code_check/W0422.feature +128 -0
  12. data/features/code_check/W0491.feature +57 -0
  13. data/features/code_check/W0492.feature +80 -0
  14. data/features/code_check/W0542.feature +20 -0
  15. data/features/code_check/W0580.feature +25 -0
  16. data/features/code_check/W0610.feature +36 -0
  17. data/features/code_check/W0642.feature +67 -0
  18. data/features/code_check/W0786.feature +39 -0
  19. data/features/code_check/W0830.feature +27 -0
  20. data/features/code_check/W1047.feature +72 -0
  21. data/features/code_check/W9003.feature +22 -0
  22. data/features/code_extraction/TODO +1 -0
  23. data/features/metric_measurement/TODO +1 -0
  24. data/lib/adlint/analyzer.rb +2 -2
  25. data/lib/adlint/cc1/ctrlexpr.rb +27 -6
  26. data/lib/adlint/cc1/domain.rb +72 -12
  27. data/lib/adlint/cc1/enum.rb +4 -0
  28. data/lib/adlint/cc1/expr.rb +31 -29
  29. data/lib/adlint/cc1/interp.rb +45 -56
  30. data/lib/adlint/cc1/lexer.rb +26 -5
  31. data/lib/adlint/cc1/mediator.rb +35 -6
  32. data/lib/adlint/cc1/object.rb +62 -19
  33. data/lib/adlint/cc1/parser.rb +948 -904
  34. data/lib/adlint/cc1/parser.y +59 -29
  35. data/lib/adlint/cc1/phase.rb +6 -8
  36. data/lib/adlint/cc1/syntax.rb +70 -17
  37. data/lib/adlint/cc1/util.rb +4 -4
  38. data/lib/adlint/code.rb +16 -6
  39. data/lib/adlint/cpp/eval.rb +31 -25
  40. data/lib/adlint/cpp/lexer.rb +11 -5
  41. data/lib/adlint/cpp/macro.rb +34 -7
  42. data/lib/adlint/cpp/phase.rb +8 -8
  43. data/lib/adlint/error.rb +6 -0
  44. data/lib/adlint/exam/c_builtin/cc1_check.rb +557 -594
  45. data/lib/adlint/exam/c_builtin/cc1_check_shima.rb +72 -72
  46. data/lib/adlint/exam/c_builtin/cc1_code.rb +72 -52
  47. data/lib/adlint/exam/c_builtin/cc1_metric.rb +131 -131
  48. data/lib/adlint/exam/c_builtin/cpp_check.rb +48 -48
  49. data/lib/adlint/exam/c_builtin/cpp_check_shima.rb +2 -2
  50. data/lib/adlint/exam/c_builtin/cpp_code.rb +21 -21
  51. data/lib/adlint/exam/c_builtin/ld_check.rb +88 -87
  52. data/lib/adlint/exam/c_builtin/ld_metric.rb +4 -5
  53. data/lib/adlint/exam/c_builtin.rb +6 -6
  54. data/lib/adlint/ld/object.rb +269 -186
  55. data/lib/adlint/ld/phase.rb +19 -19
  56. data/lib/adlint/ld/typedef.rb +7 -7
  57. data/lib/adlint/ld/util.rb +25 -17
  58. data/lib/adlint/location.rb +6 -1
  59. data/lib/adlint/memo.rb +66 -13
  60. data/lib/adlint/prelude.rb +2 -2
  61. data/lib/adlint/report.rb +13 -14
  62. data/lib/adlint/util.rb +1 -1
  63. data/lib/adlint/version.rb +2 -2
  64. data/share/doc/Makefile +6 -2
  65. data/share/doc/c99gram.dot +502 -0
  66. data/share/doc/c99gram.pdf +0 -0
  67. data/share/doc/developers_guide_ja.html +4 -3
  68. data/share/doc/developers_guide_ja.texi +2 -1
  69. data/share/doc/users_guide_en.html +9 -9
  70. data/share/doc/users_guide_en.texi +7 -7
  71. data/share/doc/users_guide_ja.html +9 -9
  72. data/share/doc/users_guide_ja.texi +7 -7
  73. metadata +14 -2
@@ -0,0 +1,128 @@
1
+ Feature: W0422
2
+
3
+ W0422 detects that an inconstant expression may cause NULL pointer
4
+ dereference.
5
+
6
+ Scenario: pointer variable definition with self referring sizeof-expression
7
+ in the initializer
8
+ Given a target source named "fixture.c" with:
9
+ """
10
+ struct foo { int i; };
11
+ extern void *malloc(unsigned long);
12
+
13
+ static int bar(void)
14
+ {
15
+ struct foo * const p = (struct foo *) malloc(sizeof *p);
16
+ return p->i; /* W0422 */
17
+ }
18
+
19
+ static int baz(void)
20
+ {
21
+ struct foo * const p = (struct foo *) malloc(sizeof(struct foo));
22
+ return p->i; /* W0422 */
23
+ }
24
+ """
25
+ When I successfully run `adlint fixture.c` on noarch
26
+ Then the output should exactly match with:
27
+ | mesg | line | column |
28
+ | W0118 | 2 | 14 |
29
+ | W1076 | 4 | 12 |
30
+ | W0422 | 7 | 13 |
31
+ | W1076 | 10 | 12 |
32
+ | W0422 | 13 | 13 |
33
+ | W0629 | 4 | 12 |
34
+ | W0629 | 10 | 12 |
35
+ | W0628 | 4 | 12 |
36
+ | W0628 | 10 | 12 |
37
+
38
+ Scenario: pointer variable as a part of controlling expression
39
+ Given a target source named "fixture.c" with:
40
+ """
41
+ struct node { struct node *prev; };
42
+
43
+ void foo(const struct node *list)
44
+ {
45
+ if (list != NULL)
46
+ {
47
+ while (1)
48
+ {
49
+ list = list->prev; /* OK */
50
+ if (list == NULL)
51
+ {
52
+ break;
53
+ }
54
+ }
55
+ }
56
+ }
57
+ """
58
+ When I successfully run `adlint fixture.c` on noarch
59
+ Then the output should exactly match with:
60
+ | mesg | line | column |
61
+ | W0117 | 3 | 6 |
62
+ | W0114 | 7 | 9 |
63
+ | W0628 | 3 | 6 |
64
+
65
+ Scenario: pointer variable as a part of controlling expression is declared in
66
+ the iteration body
67
+ Given a target source named "fixture.c" with:
68
+ """
69
+ static int *bar(void);
70
+
71
+ void foo(void)
72
+ {
73
+ if (1) {
74
+ int *p1;
75
+ p1 = bar();
76
+ while (1) {
77
+ int *p2;
78
+ p2 = p1;
79
+ while (*p2 != 3) { /* W0422 */
80
+ p2++;
81
+ }
82
+ if (*p2 == 4) {
83
+ break;
84
+ }
85
+ else {
86
+ p1 = bar();
87
+ }
88
+ }
89
+ }
90
+ }
91
+ """
92
+ When I successfully run `adlint fixture.c` on noarch
93
+ Then the output should exactly match with:
94
+ | mesg | line | column |
95
+ | W0117 | 3 | 6 |
96
+ | W0422 | 11 | 20 |
97
+ | W0024 | 12 | 19 |
98
+ | W0114 | 5 | 5 |
99
+ | W0114 | 8 | 9 |
100
+ | W0628 | 3 | 6 |
101
+
102
+ Scenario: pointer variable has the same name with previously declared
103
+ function
104
+ Given a target source named "fixture.c" with:
105
+ """
106
+ extern void instr(void);
107
+
108
+ void foo(char *instr)
109
+ {
110
+ if (instr[0] == '*') { /* W0422 */
111
+ return;
112
+ }
113
+ }
114
+ """
115
+ When I successfully run `adlint fixture.c` on noarch
116
+ Then the output should exactly match with:
117
+ | mesg | line | column |
118
+ | W0118 | 1 | 13 |
119
+ | W0117 | 3 | 6 |
120
+ | W0704 | 3 | 16 |
121
+ | C0001 | 1 | 13 |
122
+ | W0422 | 5 | 14 |
123
+ | W0123 | 5 | 14 |
124
+ | W0104 | 3 | 16 |
125
+ | W0105 | 3 | 16 |
126
+ | W1071 | 3 | 6 |
127
+ | W0948 | 5 | 21 |
128
+ | W0628 | 3 | 6 |
@@ -0,0 +1,57 @@
1
+ Feature: W0491
2
+
3
+ W0491 detects that the same name appears in different namespaces.
4
+
5
+ Scenario: hard to parse
6
+ Given a target source named "fixture.c" with:
7
+ """
8
+ typedef struct named_ref {
9
+ int id;
10
+ } named_ref; /* W0491 */
11
+
12
+ typedef struct code_props {
13
+ named_ref *named_ref; /* W0492 */
14
+ } code_props; /* W0491 */
15
+
16
+ void func(named_ref *named_ref);
17
+ void bar(int, named_ref *, named_ref *);
18
+ """
19
+ When I successfully run `adlint fixture.c` on noarch
20
+ Then the output should exactly match with:
21
+ | mesg | line | column |
22
+ | W0491 | 3 | 3 |
23
+ | C0001 | 1 | 16 |
24
+ | W0492 | 6 | 16 |
25
+ | C0001 | 3 | 3 |
26
+ | C0001 | 1 | 16 |
27
+ | W0491 | 7 | 3 |
28
+ | C0001 | 5 | 16 |
29
+ | W0118 | 9 | 6 |
30
+ | W0118 | 10 | 6 |
31
+
32
+ Scenario: hard to parse
33
+ Given a target source named "fixture.c" with:
34
+ """
35
+ #define RETSIGTYPE void
36
+
37
+ typedef int sighandler_t;
38
+ typedef RETSIGTYPE (*sighandler_t)(int);
39
+
40
+ struct sighandler_t {
41
+ RETSIGTYPE (*ptr)(int);
42
+ };
43
+
44
+ typedef struct sighandler_t *(*sighandler_t)(struct sighandler_t *);
45
+ """
46
+ When I successfully run `adlint fixture.c` on noarch
47
+ Then the output should exactly match with:
48
+ | mesg | line | column |
49
+ | W0491 | 6 | 8 |
50
+ | C0001 | 3 | 13 |
51
+ | C0001 | 4 | 22 |
52
+ | W0491 | 10 | 32 |
53
+ | C0001 | 6 | 8 |
54
+ | W0482 | 1 | 1 |
55
+ | W0586 | 3 | 13 |
56
+ | W0586 | 4 | 22 |
57
+ | W0586 | 10 | 32 |
@@ -0,0 +1,80 @@
1
+ Feature: W0492
2
+
3
+ W0492 detects that the same name appears in different namespaces.
4
+
5
+ Scenario: hard to parse
6
+ Given a target source named "fixture.c" with:
7
+ """
8
+ typedef int foo;
9
+
10
+ foo bar(foo baz)
11
+ {
12
+ goto foo;
13
+ foo:
14
+ return baz;
15
+ }
16
+
17
+ struct foo { foo foo, (*bar)(foo); }; /* W0492 */
18
+ union bar { foo foo, (*bar)(foo (*baz)(foo)); }; /* W0492 */
19
+ enum baz { baz };
20
+
21
+ struct {
22
+ foo :1;
23
+ foo foo:1; /* W0492 */
24
+ foo :1;
25
+ foo bar:1; /* W0492 */
26
+ foo :1;
27
+ } qux;
28
+
29
+ struct qux {
30
+ foo;
31
+ union bar bar; /* W0492 */
32
+ };
33
+
34
+ int const long volatile unsigned cv_ulong;
35
+ const foo volatile cv_foo;
36
+ """
37
+ When I successfully run `adlint fixture.c` on noarch
38
+ Then the output should exactly match with:
39
+ | mesg | line | column |
40
+ | W0117 | 3 | 5 |
41
+ | W0625 | 1 | 13 |
42
+ | W0491 | 6 | 1 |
43
+ | C0001 | 1 | 13 |
44
+ | W0104 | 3 | 13 |
45
+ | W0491 | 10 | 8 |
46
+ | C0001 | 1 | 13 |
47
+ | W0492 | 10 | 18 |
48
+ | C0001 | 1 | 13 |
49
+ | C0001 | 10 | 8 |
50
+ | W0492 | 11 | 7 |
51
+ | C0001 | 10 | 25 |
52
+ | W0492 | 11 | 17 |
53
+ | C0001 | 1 | 13 |
54
+ | C0001 | 10 | 8 |
55
+ | W0492 | 11 | 24 |
56
+ | C0001 | 11 | 7 |
57
+ | W0492 | 16 | 9 |
58
+ | C0001 | 1 | 13 |
59
+ | C0001 | 10 | 8 |
60
+ | W0492 | 18 | 9 |
61
+ | C0001 | 11 | 7 |
62
+ | W0117 | 20 | 3 |
63
+ | W0491 | 22 | 8 |
64
+ | C0001 | 20 | 3 |
65
+ | W0492 | 24 | 15 |
66
+ | C0001 | 11 | 7 |
67
+ | W0080 | 27 | 34 |
68
+ | W0117 | 27 | 34 |
69
+ | W0080 | 28 | 20 |
70
+ | W0117 | 28 | 20 |
71
+ | W1072 | 5 | 5 |
72
+ | W0551 | 11 | 7 |
73
+ | W0525 | 16 | 9 |
74
+ | W0525 | 18 | 9 |
75
+ | W0040 | 14 | 1 |
76
+ | W0425 | 10 | 25 |
77
+ | W0425 | 11 | 24 |
78
+ | W0431 | 6 | 1 |
79
+ | W0432 | 6 | 1 |
80
+ | W0628 | 3 | 5 |
@@ -0,0 +1,20 @@
1
+ Feature: W0542
2
+
3
+ W0542 detects that some of parameters have an identifier.
4
+
5
+ Scenario: hard to parse
6
+ Given a target source named "fixture.c" with:
7
+ """
8
+ typedef unsigned int VALUE;
9
+ typedef void *ANYARGS;
10
+
11
+ VALUE foo(VALUE(*p1)(VALUE),VALUE,VALUE(*p2)(ANYARGS),VALUE); /* W0542 */
12
+ VALUE bar(VALUE(*)(VALUE),VALUE,VALUE(*)(ANYARGS),VALUE);
13
+ """
14
+ When I successfully run `adlint fixture.c` on noarch
15
+ Then the output should exactly match with:
16
+ | mesg | line | column |
17
+ | W0118 | 4 | 7 |
18
+ | W0625 | 1 | 22 |
19
+ | W0118 | 5 | 7 |
20
+ | W0542 | 4 | 7 |
@@ -0,0 +1,25 @@
1
+ Feature: W0580
2
+
3
+ W0580 detects that address of the function local static variable is assigned
4
+ to the global pointer variable declared in wider scope.
5
+
6
+ Scenario: assigning address of an array element to the global pointer
7
+ Given a target source named "fixture.c" with:
8
+ """
9
+ extern int *p;
10
+
11
+ static void foo(void)
12
+ {
13
+ static int a[] = { 1, 2, 3 };
14
+ p = &a[1]; /* W0580 */
15
+ }
16
+ """
17
+ When I successfully run `adlint fixture.c` on noarch
18
+ Then the output should exactly match with:
19
+ | mesg | line | column |
20
+ | W0118 | 1 | 13 |
21
+ | W1076 | 3 | 13 |
22
+ | W0580 | 6 | 7 |
23
+ | W0100 | 5 | 16 |
24
+ | W0629 | 3 | 13 |
25
+ | W0628 | 3 | 13 |
@@ -0,0 +1,36 @@
1
+ Feature: W0610
2
+
3
+ W0610 detects that a logical expression makes always true.
4
+
5
+ Scenario: comparison of static storage duration variable
6
+ Given a target source named "fixture.c" with:
7
+ """
8
+ struct { char *p; } foo = { NULL };
9
+ int *p = NULL;
10
+
11
+ static void bar(void)
12
+ {
13
+ if (p != NULL) { /* OK */
14
+ return;
15
+ }
16
+
17
+ if (foo.p != NULL) { /* OK */
18
+ return;
19
+ }
20
+ }
21
+ """
22
+ When I successfully run `adlint fixture.c` on noarch
23
+ Then the output should exactly match with:
24
+ | mesg | line | column |
25
+ | W0117 | 1 | 21 |
26
+ | W0117 | 2 | 6 |
27
+ | W0492 | 2 | 6 |
28
+ | C0001 | 1 | 16 |
29
+ | W1076 | 4 | 13 |
30
+ | W1071 | 4 | 13 |
31
+ | W0629 | 4 | 13 |
32
+ | W0628 | 4 | 13 |
33
+ | W0589 | 1 | 21 |
34
+ | W0593 | 1 | 21 |
35
+ | W0589 | 2 | 6 |
36
+ | W0593 | 2 | 6 |
@@ -0,0 +1,67 @@
1
+ Feature: W0642
2
+
3
+ W0642 detects that an expression trys to derive address of the array declared
4
+ as `register'.
5
+
6
+ Scenario: register array passed as function parameter
7
+ Given a target source named "fixture.c" with:
8
+ """
9
+ extern void foo(char *);
10
+
11
+ static void bar(void)
12
+ {
13
+ register char a[3];
14
+ foo(a); /* W0642 */
15
+ }
16
+ """
17
+ When I successfully run `adlint fixture.c` on noarch
18
+ Then the output should exactly match with:
19
+ | mesg | line | column |
20
+ | W0118 | 1 | 13 |
21
+ | W1076 | 3 | 13 |
22
+ | W0642 | 6 | 9 |
23
+ | W0100 | 5 | 19 |
24
+ | W0629 | 3 | 13 |
25
+ | W0950 | 5 | 21 |
26
+ | W0628 | 3 | 13 |
27
+
28
+ Scenario: register array designated in initializer
29
+ Given a target source named "fixture.c" with:
30
+ """
31
+ static void foo(void)
32
+ {
33
+ register char a[3];
34
+ char *p = a; /* W0642 */
35
+ }
36
+ """
37
+ When I successfully run `adlint fixture.c` on noarch
38
+ Then the output should exactly match with:
39
+ | mesg | line | column |
40
+ | W1076 | 1 | 13 |
41
+ | W0642 | 4 | 15 |
42
+ | W0100 | 3 | 19 |
43
+ | W0100 | 4 | 11 |
44
+ | W0629 | 1 | 13 |
45
+ | W0950 | 3 | 21 |
46
+ | W0628 | 1 | 13 |
47
+
48
+ Scenario: register array designated in assignment
49
+ Given a target source named "fixture.c" with:
50
+ """
51
+ static void foo(void)
52
+ {
53
+ register char a[3];
54
+ char *p;
55
+ p = a; /* W0642 */
56
+ }
57
+ """
58
+ When I successfully run `adlint fixture.c` on noarch
59
+ Then the output should exactly match with:
60
+ | mesg | line | column |
61
+ | W1076 | 1 | 13 |
62
+ | W0642 | 5 | 9 |
63
+ | W0100 | 3 | 19 |
64
+ | W0100 | 4 | 11 |
65
+ | W0629 | 1 | 13 |
66
+ | W0950 | 3 | 21 |
67
+ | W0628 | 1 | 13 |
@@ -0,0 +1,39 @@
1
+ Feature: W0786
2
+
3
+ W0786 detects that a bit-field whose base type is not in signed or unsigned
4
+ `int' is declared.
5
+
6
+ Scenario: typedefed `unsigned long' bit-field declaration
7
+ Given a target source named "fixture.c" with:
8
+ """
9
+ typedef unsigned long base_t;
10
+
11
+ static struct { /* W0786 */
12
+ base_t :1; /* bit padding */
13
+ base_t foo:1;
14
+ base_t :1; /* bit padding */
15
+ base_t bar:1;
16
+ base_t :1; /* bit padding */
17
+ } bf;
18
+ """
19
+ When I successfully run `adlint fixture.c` on noarch
20
+ Then the output should exactly match with:
21
+ | mesg | line | column |
22
+ | W0786 | 3 | 8 |
23
+
24
+ Scenario: typedefed `unsigned int' bit-field declaration
25
+ Given a target source named "fixture.c" with:
26
+ """
27
+ typedef unsigned int base_t;
28
+
29
+ static struct { /* OK */
30
+ base_t :1; /* bit padding */
31
+ base_t foo:1;
32
+ base_t :1; /* bit padding */
33
+ base_t bar:1;
34
+ base_t :1; /* bit padding */
35
+ } bf;
36
+ """
37
+ When I successfully run `adlint fixture.c` on noarch
38
+ Then the output should exactly match with:
39
+ | mesg | line | column |
@@ -61,3 +61,30 @@ Feature: W0830
61
61
  Then the output should exactly match with:
62
62
  | mesg | line | column |
63
63
  | W0830 | 1 | 36 |
64
+
65
+ Scenario: hard to preprocess
66
+ Given a target source named "fixture.c" with:
67
+ """
68
+ #include "config.h"
69
+ """
70
+ And a target source named "config.h" with:
71
+ """
72
+ typedef enum jid {
73
+ #define DEFINE_JOB(id, func) JOBID_##id,
74
+ #include "job_tbl.h"
75
+ #undef DEFINE_JOB
76
+ } jid_t;
77
+ """
78
+ And a target source named "job_tbl.h" with:
79
+ """
80
+ DEFINE_JOB(1id, func1)
81
+ DEFINE_JOB(id2, func2)
82
+ """
83
+ When I successfully run `adlint fixture.c` on noarch
84
+ Then the output should exactly match with:
85
+ | mesg | line | column |
86
+ | W0442 | 2 | 1 |
87
+ | W0073 | 1 | 1 |
88
+ | W0073 | 1 | 1 |
89
+ | W0830 | 2 | 1 |
90
+ | W0071 | 3 | 1 |
@@ -159,3 +159,75 @@ Feature: W1047
159
159
  | W0100 | 22 | 18 |
160
160
  | W0551 | 14 | 5 |
161
161
  | W0628 | 20 | 5 |
162
+
163
+ Scenario: initializing array with address-constant
164
+ Given a target source named "fixture.c" with:
165
+ """
166
+ extern int foo(void);
167
+ extern int bar(void);
168
+ extern int baz(void);
169
+
170
+ static int (*fun_tbl[])(void) = { foo, bar, baz }; /* OK */
171
+ """
172
+ When I successfully run `adlint fixture.c` on noarch
173
+ Then the output should exactly match with:
174
+ | mesg | line | column |
175
+ | W0118 | 1 | 12 |
176
+ | W0118 | 2 | 12 |
177
+ | W0118 | 3 | 12 |
178
+
179
+ Scenario: initializing struct with constant-specifier and address-constant
180
+ Given a target source named "fixture.c" with:
181
+ """
182
+ typedef struct handler {
183
+ int id;
184
+ int (*ptr)(void);
185
+ } handler_t;
186
+
187
+ extern int foo(void);
188
+ extern int bar(void);
189
+ extern int baz(void);
190
+
191
+ static handler_t h = { 1, foo }; /* OK */
192
+ """
193
+ When I successfully run `adlint fixture.c` on noarch
194
+ Then the output should exactly match with:
195
+ | mesg | line | column |
196
+ | W0118 | 6 | 12 |
197
+ | W0118 | 7 | 12 |
198
+ | W0118 | 8 | 12 |
199
+
200
+ Scenario: initializing struct with inconstant expression and address-constant
201
+ Given a target source named "fixture.c" with:
202
+ """
203
+ typedef struct handler {
204
+ int id;
205
+ int (*ptr)(void);
206
+ } handler_t;
207
+
208
+ extern int foo(void);
209
+ extern int bar;
210
+ extern int baz;
211
+
212
+ static handler_t h = { bar + baz, foo }; /* W1047 */
213
+ """
214
+ When I successfully run `adlint fixture.c` on noarch
215
+ Then the output should exactly match with:
216
+ | mesg | line | column |
217
+ | W0118 | 6 | 12 |
218
+ | W0118 | 7 | 12 |
219
+ | W0118 | 8 | 12 |
220
+ | W0723 | 10 | 28 |
221
+ | W1047 | 10 | 18 |
222
+
223
+ Scenario: initializing array with address-constant
224
+ Given a target source named "fixture.c" with:
225
+ """
226
+ static int i, j, k;
227
+ static int *var_tbl[] = { &i, &j, &k }; /* OK */
228
+ """
229
+ When I successfully run `adlint fixture.c` on noarch
230
+ Then the output should exactly match with:
231
+ | mesg | line | column |
232
+ | W0425 | 1 | 15 |
233
+ | W0425 | 1 | 18 |
@@ -269,3 +269,25 @@ Feature: W9003
269
269
  | W0105 | 1 | 23 |
270
270
  | W0629 | 1 | 13 |
271
271
  | W0628 | 1 | 13 |
272
+
273
+ Scenario: no implicit convertion of register variable
274
+ Given a target source named "fixture.c" with:
275
+ """
276
+ static void foo(void)
277
+ {
278
+ register char a[3];
279
+ char *p;
280
+ p = &a[0]; /* OK */
281
+ }
282
+ """
283
+ When I successfully run `adlint fixture.c` on noarch
284
+ Then the output should exactly match with:
285
+ | mesg | line | column |
286
+ | W1076 | 1 | 13 |
287
+ | W0459 | 5 | 9 |
288
+ | W0642 | 5 | 9 |
289
+ | W0100 | 3 | 19 |
290
+ | W0100 | 4 | 11 |
291
+ | W0629 | 1 | 13 |
292
+ | W0950 | 3 | 21 |
293
+ | W0628 | 1 | 13 |
@@ -0,0 +1 @@
1
+ Must write functional specifications about the code extraction feature.
@@ -0,0 +1 @@
1
+ Must write functional specifications about the metric measurement feature.
@@ -199,8 +199,8 @@ module AdLint #:nodoc:
199
199
  Ld::MapTypedefPhase,
200
200
  Ld::MapFunctionPhase,
201
201
  Ld::MapVariablePhase,
202
- Ld::LinkFunctionPhase,
203
- Ld::LinkVariablePhase,
202
+ Ld::BuildCallGraphPhase,
203
+ Ld::BuildXRefGraphPhase,
204
204
  Ld::PreparePhase,
205
205
  Ld::TypedefReviewPhase,
206
206
  Ld::FunctionReviewPhase,
@@ -669,6 +669,27 @@ module Cc1 #:nodoc:
669
669
 
670
670
  def_delegator :@manipulator, :interpreter
671
671
  private :interpreter
672
+
673
+ alias :_org_interpret :interpret
674
+ def interpret(node)
675
+ case node
676
+ when ObjectSpecifier
677
+ if safely_evaluable_object_specifier?(node)
678
+ _org_interpret(node)
679
+ else
680
+ # NOTE: Nothing to do with an undeclared object.
681
+ create_tmpvar
682
+ end
683
+ else
684
+ _org_interpret(node)
685
+ end
686
+ end
687
+
688
+ def safely_evaluable_object_specifier?(obj_spec)
689
+ variable_named(obj_spec.identifier.value) ||
690
+ function_named(obj_spec.identifier.value) ||
691
+ enumerator_named(obj_spec.identifier.value)
692
+ end
672
693
  end
673
694
 
674
695
  class ValueComparison < ValueDomainNarrowing
@@ -682,10 +703,10 @@ module Cc1 #:nodoc:
682
703
  private
683
704
  def do_narrowing
684
705
  @lhs_manip.execute!
685
- lhs_var = object_to_variable(@lhs_manip.result)
706
+ lhs_var = object_to_variable(@lhs_manip.result, @node.lhs_operand)
686
707
 
687
708
  @rhs_manip.execute!
688
- rhs_var = object_to_variable(@rhs_manip.result)
709
+ rhs_var = object_to_variable(@rhs_manip.result, @node.rhs_operand)
689
710
 
690
711
  unless lhs_var.type.scalar? && rhs_var.type.scalar?
691
712
  return create_tmpvar(int_t)
@@ -754,7 +775,7 @@ module Cc1 #:nodoc:
754
775
  def do_narrowing
755
776
  @lhs_manip.execute!
756
777
  @lhs_manip.ensure_result_equal_to(scalar_value_of_true)
757
- lhs_var = object_to_variable(@lhs_manip.result)
778
+ lhs_var = object_to_variable(@lhs_manip.result, @node.lhs_operand)
758
779
 
759
780
  # NOTE: The ISO C99 standard says;
760
781
  #
@@ -772,7 +793,7 @@ module Cc1 #:nodoc:
772
793
  @rhs_manip.load_original_values!(@lhs_manip)
773
794
  @rhs_manip.execute!
774
795
  @rhs_manip.ensure_result_equal_to(scalar_value_of_true)
775
- rhs_var = object_to_variable(@rhs_manip.result)
796
+ rhs_var = object_to_variable(@rhs_manip.result, @node.rhs_operand)
776
797
 
777
798
  notify_sequence_point_reached(SequencePoint.new(@node.rhs_operand))
778
799
 
@@ -811,7 +832,7 @@ module Cc1 #:nodoc:
811
832
  def do_narrowing
812
833
  @lhs_manip.execute!
813
834
  @lhs_manip.ensure_result_equal_to(scalar_value_of_true)
814
- lhs_var = object_to_variable(@lhs_manip.result)
835
+ lhs_var = object_to_variable(@lhs_manip.result, @node.lhs_operand)
815
836
 
816
837
  # NOTE: The ISO C99 standard says;
817
838
  #
@@ -830,7 +851,7 @@ module Cc1 #:nodoc:
830
851
  # the LHS condition is false.
831
852
  @rhs_manip.execute!
832
853
  @rhs_manip.ensure_result_equal_to(scalar_value_of_true)
833
- rhs_var = object_to_variable(@rhs_manip.result)
854
+ rhs_var = object_to_variable(@rhs_manip.result, @node.rhs_operand)
834
855
 
835
856
  notify_sequence_point_reached(SequencePoint.new(@node.rhs_operand))
836
857