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.
- data/ChangeLog +374 -13
- data/INSTALL +1 -3
- data/MANIFEST +12 -0
- data/NEWS +30 -4
- data/README +0 -4
- data/TODO +2 -1
- data/etc/mesg.d/c_builtin/en_US/messages.yml +2 -2
- data/etc/mesg.d/c_builtin/ja_JP/messages.yml +2 -2
- data/etc/mesg.d/core/en_US/messages.yml +5 -1
- data/etc/mesg.d/core/ja_JP/messages.yml +5 -1
- data/features/code_check/W0422.feature +128 -0
- data/features/code_check/W0491.feature +57 -0
- data/features/code_check/W0492.feature +80 -0
- data/features/code_check/W0542.feature +20 -0
- data/features/code_check/W0580.feature +25 -0
- data/features/code_check/W0610.feature +36 -0
- data/features/code_check/W0642.feature +67 -0
- data/features/code_check/W0786.feature +39 -0
- data/features/code_check/W0830.feature +27 -0
- data/features/code_check/W1047.feature +72 -0
- data/features/code_check/W9003.feature +22 -0
- data/features/code_extraction/TODO +1 -0
- data/features/metric_measurement/TODO +1 -0
- data/lib/adlint/analyzer.rb +2 -2
- data/lib/adlint/cc1/ctrlexpr.rb +27 -6
- data/lib/adlint/cc1/domain.rb +72 -12
- data/lib/adlint/cc1/enum.rb +4 -0
- data/lib/adlint/cc1/expr.rb +31 -29
- data/lib/adlint/cc1/interp.rb +45 -56
- data/lib/adlint/cc1/lexer.rb +26 -5
- data/lib/adlint/cc1/mediator.rb +35 -6
- data/lib/adlint/cc1/object.rb +62 -19
- data/lib/adlint/cc1/parser.rb +948 -904
- data/lib/adlint/cc1/parser.y +59 -29
- data/lib/adlint/cc1/phase.rb +6 -8
- data/lib/adlint/cc1/syntax.rb +70 -17
- data/lib/adlint/cc1/util.rb +4 -4
- data/lib/adlint/code.rb +16 -6
- data/lib/adlint/cpp/eval.rb +31 -25
- data/lib/adlint/cpp/lexer.rb +11 -5
- data/lib/adlint/cpp/macro.rb +34 -7
- data/lib/adlint/cpp/phase.rb +8 -8
- data/lib/adlint/error.rb +6 -0
- data/lib/adlint/exam/c_builtin/cc1_check.rb +557 -594
- data/lib/adlint/exam/c_builtin/cc1_check_shima.rb +72 -72
- data/lib/adlint/exam/c_builtin/cc1_code.rb +72 -52
- data/lib/adlint/exam/c_builtin/cc1_metric.rb +131 -131
- data/lib/adlint/exam/c_builtin/cpp_check.rb +48 -48
- data/lib/adlint/exam/c_builtin/cpp_check_shima.rb +2 -2
- data/lib/adlint/exam/c_builtin/cpp_code.rb +21 -21
- data/lib/adlint/exam/c_builtin/ld_check.rb +88 -87
- data/lib/adlint/exam/c_builtin/ld_metric.rb +4 -5
- data/lib/adlint/exam/c_builtin.rb +6 -6
- data/lib/adlint/ld/object.rb +269 -186
- data/lib/adlint/ld/phase.rb +19 -19
- data/lib/adlint/ld/typedef.rb +7 -7
- data/lib/adlint/ld/util.rb +25 -17
- data/lib/adlint/location.rb +6 -1
- data/lib/adlint/memo.rb +66 -13
- data/lib/adlint/prelude.rb +2 -2
- data/lib/adlint/report.rb +13 -14
- data/lib/adlint/util.rb +1 -1
- data/lib/adlint/version.rb +2 -2
- data/share/doc/Makefile +6 -2
- data/share/doc/c99gram.dot +502 -0
- data/share/doc/c99gram.pdf +0 -0
- data/share/doc/developers_guide_ja.html +4 -3
- data/share/doc/developers_guide_ja.texi +2 -1
- data/share/doc/users_guide_en.html +9 -9
- data/share/doc/users_guide_en.texi +7 -7
- data/share/doc/users_guide_ja.html +9 -9
- data/share/doc/users_guide_ja.texi +7 -7
- 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.
|
data/lib/adlint/analyzer.rb
CHANGED
@@ -199,8 +199,8 @@ module AdLint #:nodoc:
|
|
199
199
|
Ld::MapTypedefPhase,
|
200
200
|
Ld::MapFunctionPhase,
|
201
201
|
Ld::MapVariablePhase,
|
202
|
-
Ld::
|
203
|
-
Ld::
|
202
|
+
Ld::BuildCallGraphPhase,
|
203
|
+
Ld::BuildXRefGraphPhase,
|
204
204
|
Ld::PreparePhase,
|
205
205
|
Ld::TypedefReviewPhase,
|
206
206
|
Ld::FunctionReviewPhase,
|
data/lib/adlint/cc1/ctrlexpr.rb
CHANGED
@@ -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
|
|