Skip to content

Commit 1821e9a

Browse files
committed
TESTS: add tests for gcc-like attributes
1 parent 9021751 commit 1821e9a

File tree

12 files changed

+342
-2
lines changed

12 files changed

+342
-2
lines changed

chc/app/CGlobalDeclarations.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -767,7 +767,8 @@ def f(n: ET.Element, r: IndexedTableValue) -> None:
767767
continue
768768
if len(self.varinfo_storage_classes[vid]) > 1:
769769
chklogger.logger.warning(
770-
"Multiple storage classes for variable %d", vid)
770+
"Multiple storage classes for variable %d: %s",
771+
vid, ", ".join(self.varinfo_storage_classes[vid]))
771772
continue
772773
else:
773774
storageclass = list(self.varinfo_storage_classes[vid])[0]

chc/cmdline/c_file/cfileutil.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -358,6 +358,7 @@ def cfile_run_file(args: argparse.Namespace) -> NoReturn:
358358
copen: bool = args.open
359359
jsonoutput: bool = args.json
360360
outputfile: Optional[str] = args.output
361+
verbose: bool = args.verbose
361362
loglevel: str = args.loglevel
362363
logfilename: Optional[str] = args.logfilename
363364
logfilemode: str = args.logfilemode
@@ -451,7 +452,7 @@ def cfile_run_file(args: argparse.Namespace) -> NoReturn:
451452
capp.initialize_single_file(cfilename)
452453
cfile = capp.get_cfile()
453454

454-
am = AnalysisManager(capp)
455+
am = AnalysisManager(capp, verbose=verbose)
455456

456457
am.create_file_primary_proofobligations(cfilename)
457458
am.reset_tables(cfile)

chc/cmdline/chkc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -749,6 +749,9 @@ def parse() -> argparse.Namespace:
749749
cfilerun.add_argument(
750750
"--output", "-o",
751751
help="name of outputfile (without extension)")
752+
cfilerun.add_argument(
753+
"--verbose", "-v",
754+
action="store_true")
752755
cfilerun.add_argument(
753756
"--loglevel", "-log",
754757
choices=UL.LogLevel.options(),

tests/attributes/test_access.c

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/* test access attribute */
2+
3+
void f_no_attr(int *p, int len);
4+
5+
/* the access attribute specifies that the first argument must be able to
6+
be read, with a minimum size specified by the second argument. */
7+
void f_attr(int *p, int len) __attribute__((__access__ (read_only, 1, 2)));
8+
9+
10+
void test_no_attr() {
11+
int buffer[12];
12+
13+
f_no_attr(buffer, 12);
14+
f_no_attr(buffer, 20);
15+
}
16+
17+
18+
/* should show violation for the second call */
19+
void test_attr() {
20+
int buffer[12];
21+
22+
f_attr(buffer, 12);
23+
f_attr(buffer, 20);
24+
}
25+
26+
27+
int main(int argc, char **argv) {
28+
29+
test_no_attr();
30+
test_attr();
31+
32+
return 0;
33+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/* tests the inequality attributes for global variables:
2+
- chkc_le
3+
- chkc_lt
4+
- chkc_ge
5+
- chkc_gt
6+
7+
These attributes can be used to enforce a global bounds on the value
8+
of a global variable; they will generate proof obligations and can be
9+
used in the discharge of other proof obligations.
10+
*/
11+
12+
#define BUFSIZE 12
13+
14+
int g_no_attr;
15+
16+
int g_attr
17+
__attribute__ ((__chkc_lt__ (BUFSIZE))) __attribute__ ((__chkc_ge__ (0)));
18+
19+
int buffer[BUFSIZE];
20+
21+
22+
void test_no_attr() {
23+
24+
buffer[g_no_attr] = 0;
25+
}
26+
27+
28+
/* attributes are used to discharge the index-lower and index-upper-bound
29+
proof obligations. */
30+
void test_attr() {
31+
32+
buffer[g_attr] = 0;
33+
}
34+
35+
36+
int main(int argc, char **argv) {
37+
38+
g_no_attr = 10;
39+
g_attr = 10;
40+
41+
test_no_attr();
42+
test_attr();
43+
44+
return 0;
45+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/* test of the chkc_not_null attribute on the value of a global variable */
2+
3+
extern int *g_no_attr;
4+
5+
extern int *g_attr __attribute__ ((__chkc_not_null__));
6+
7+
void f(int *p) __attribute__ ((__nonnull__ (1)));
8+
9+
10+
void test_no_attr() {
11+
12+
f(g_no_attr);
13+
}
14+
15+
16+
void test_attr() {
17+
18+
f(g_attr);
19+
}
20+
21+
22+
int main(int argc, char **argv) {
23+
24+
test_no_attr();
25+
test_attr();
26+
27+
return 0;
28+
}

tests/attributes/test_malloc.c

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/* test_malloc attribute
2+
3+
The malloc attribute allows discharge of the allocation-base proof
4+
obligation for free.
5+
6+
Note: this test should show the discharge of the no-overlap requirement
7+
for memcpy. It does not do so yet.
8+
*/
9+
10+
void *f_no_attr(int len);
11+
12+
void *f_attr(int len) __attribute__ ((__malloc__));
13+
14+
void *memcpy(void *dst, const void *src, int len);
15+
16+
17+
void test_no_attr() {
18+
19+
char *p = (char *) f_no_attr(10);
20+
char *q = (char *) f_no_attr(10);
21+
22+
if (p && q) {
23+
memcpy(q, p, 10);
24+
}
25+
26+
free(p);
27+
free(q);
28+
}
29+
30+
31+
void test_attr() {
32+
33+
char *p = (char *) f_attr(10);
34+
char *q = (char *) f_attr(10);
35+
36+
if (p && q) {
37+
memcpy(q, p, 10);
38+
}
39+
40+
free(p);
41+
free(q);
42+
}
43+
44+
45+
int main(int argc, char **argv) {
46+
47+
test_no_attr();
48+
test_attr();
49+
50+
return 0;
51+
}

tests/attributes/test_nonnull.c

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/* test attribute nonnull */
2+
3+
void f_no_attr(int *p);
4+
5+
void f_attr(int *p) __attribute__ ((__nonnull__ (1)));
6+
7+
void *malloc(int len);
8+
9+
10+
void test_no_attr() {
11+
int buffer[12];
12+
13+
f_no_attr(buffer);
14+
15+
int *p = malloc(12);
16+
17+
f_no_attr(p);
18+
}
19+
20+
21+
/* Adds two proof obligation for not-null, one of which can be discharged
22+
against the data type, the other one is open, because malloc may return
23+
NULL. */
24+
void test_attr() {
25+
int buffer[12];
26+
27+
f_attr(buffer);
28+
29+
int *p = malloc(12);
30+
31+
f_attr(p);
32+
}
33+
34+
35+
int main(int argc, char **argv) {
36+
37+
test_no_attr();
38+
test_attr();
39+
40+
return 0;
41+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/* test chkc_preserves_all_memory attribute
2+
3+
can be used to discharge proof obligations that memory has not been freed
4+
*/
5+
6+
int f_no_attr(void *p);
7+
8+
int f_attr(void *p) __attribute__ ((__chkc_preserves_all_memory__));
9+
10+
void *malloc(int len);
11+
12+
13+
void test_no_attr() {
14+
15+
void *p = malloc(10);
16+
17+
f_no_attr(p);
18+
f_no_attr(p);
19+
20+
return 0;
21+
}
22+
23+
24+
/* the valid-mem proof obligation is discharged based on the guarantee that
25+
the first call to f_attr does not free p. */
26+
void test_attr() {
27+
28+
void *p = malloc(10);
29+
30+
f_attr(p);
31+
f_attr(p);
32+
33+
return 0;
34+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/* test chkc_preserves_memory attribute
2+
3+
can be used to discharge proof obligations that memory has not been freed
4+
5+
Note: does not yet work.
6+
*/
7+
8+
int f_no_attr(void *p);
9+
10+
int f_attr(void *p) __attribute__ ((__chkc_preserves_memory__ (1)));
11+
12+
void *malloc(int len);
13+
14+
15+
void test_no_attr() {
16+
17+
void *p = malloc(10);
18+
19+
f_no_attr(p);
20+
f_no_attr(p);
21+
22+
return 0;
23+
}
24+
25+
26+
void test_attr() {
27+
28+
void *p = malloc(10);
29+
30+
f_attr(p);
31+
f_attr(p);
32+
33+
return 0;
34+
}

0 commit comments

Comments
 (0)