Skip to content

Commit 9c5c790

Browse files
Andrew RuefAndrew Ruef
Andrew Ruef
authored and
Andrew Ruef
committed
Rewrite tool (#34)
* Initial version of the checked-c conversion tool. Current features: - Processes single C files or multiple C files (up to whole programs) - Infers "ptr-ness" for local variables used in those programs. - Re-write many source files - Supports many aspects of the C grammar - Contains unit tests Current weaknesses: - Macro support is limited - Casting support is limited, needs structural type equality checks - No inherent support for standard library functions. - Doesn't honor existing checked C types
1 parent a366249 commit 9c5c790

21 files changed

+2801
-0
lines changed

test/CheckedCRewriter/lit.local.cfg

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
config.suffixes = ['.c']

test/CheckedCRewriter/simple_locals.c

Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
// Tests for Checked C rewriter tool.
2+
//
3+
// Checks very simple inference properties for local variables.
4+
//
5+
// RUN: checked-c-convert %s -- | FileCheck %s
6+
// RUN: checked-c-convert %s -- | %clang_cc1 -verify -fcheckedc-extension -x c -
7+
// expected-no-diagnostics
8+
9+
void f1() {
10+
int b = 0;
11+
int *a = &b;
12+
*a = 1;
13+
}
14+
// CHECK: void f1() {
15+
// CHECK-NEXT: int b = 0;
16+
// CHECK-NEXT: ptr<int> a = &b;
17+
18+
void f2() {
19+
char b = 'a';
20+
char *a = &b;
21+
*a = 'b';
22+
}
23+
//CHECK: void f2() {
24+
//CHECK-NEXT: char b = 'a';
25+
//CHECK-NEXT: ptr<char> a = &b;
26+
27+
typedef struct _BarRec {
28+
int a;
29+
int b;
30+
int c;
31+
int *d;
32+
} BarRec;
33+
34+
void upd(BarRec *P, int a) {
35+
P->a = a;
36+
}
37+
//CHECK: void upd(ptr<BarRec> P, int a) {
38+
//CHECK-NEXT: P->a = a;
39+
//CHECK-NEXT: }
40+
41+
void canthelp(int *a, int b, int c) {
42+
*(a + b) = c;
43+
}
44+
//CHECK: void canthelp(int *a, int b, int c) {
45+
//CHECK-NEXT: *(a + b) = c;
46+
//CHECK-NEXT: }
47+
48+
void partialhelp(int *a, int b, int c) {
49+
int *d = a;
50+
*d = 0;
51+
*(a + b) = c;
52+
}
53+
//CHECK: void partialhelp(int *a, int b, int c) {
54+
//CHECK-NEXT: ptr<int> d = a;
55+
//CHECK-NEXT: *d = 0;
56+
//CHECK-NEXT: *(a + b) = c;
57+
//CHECK-NEXT: }
58+
59+
void g(void) {
60+
int a = 0, *b = &a;
61+
*b = 1;
62+
}
63+
//CHECK: void g(void) {
64+
//CHECK-NEXT: int a = 0;
65+
//CHECK-NEXT: ptr<int> b = &a;
66+
67+
void gg(void) {
68+
int a = 0, *b = &a, **c = &b;
69+
70+
*b = 1;
71+
**c = 2;
72+
}
73+
//CHECK: void gg(void) {
74+
//CHECK-NEXT: int a = 0;
75+
//CHECK-NEXT: ptr<int> b = &a;
76+
//CHECK-NEXT: ptr<ptr<int> > c = &b;
77+
78+
#define ONE 1
79+
80+
int goo(int *, int);
81+
//CHECK: int goo(ptr<int>, int);
82+
83+
struct blah {
84+
int a;
85+
int b;
86+
struct blah *c;
87+
};
88+
89+
int bar(int, int);
90+
91+
int foo(int a, int b) {
92+
int tmp = a + ONE;
93+
int *tmp2 = &tmp;
94+
return tmp + b + *tmp2;
95+
}
96+
//CHECK: int foo(int a, int b) {
97+
//CHECK-NEXT: int tmp = a + ONE;
98+
//CHECK-NEXT: ptr<int> tmp2 = &tmp;
99+
//CHECK-NEXT: return tmp + b + *tmp2;
100+
//CHECK-NEXT: }
101+
102+
int bar(int a, int b) {
103+
return a + b;
104+
}
105+
//CHECK: int bar(int a, int b) {
106+
//CHECK-NEXT: return a + b;
107+
//CHECK-NEXT: }
108+
109+
int baz(int *a, int b, int c) {
110+
int tmp = b + c;
111+
int *aa = a;
112+
*aa = tmp;
113+
return tmp;
114+
}
115+
//CHECK: int baz(ptr<int> a, int b, int c) {
116+
//CHECK-NEXT: int tmp = b + c;
117+
//CHECK-NEXT: ptr<int> aa = a;
118+
//CHECK-NEXT: *aa = tmp;
119+
//CHECK-NEXT: return tmp;
120+
121+
int arrcheck(int *a, int b) {
122+
return a[b];
123+
}
124+
//CHECK: int arrcheck(int *a, int b) {
125+
//CHECK-NEXT: return a[b];
126+
//CHECK-NEXT: }
127+
128+
int badcall(int *a, int b) {
129+
return arrcheck(a, b);
130+
}
131+
//CHECK: int badcall(int *a, int b) {
132+
//CHECK-NEXT: return arrcheck(a, b);
133+
//CHECK-NEXT: }
134+
135+
void pullit(char *base, char *out, int *index) {
136+
char tmp = base[*index];
137+
*out = tmp;
138+
*index = *index + 1;
139+
140+
return;
141+
}
142+
//CHECK: void pullit(char* base, ptr<char> out, ptr<int> index) {
143+
144+
void driver() {
145+
char buf[10] = { 0 };
146+
int index = 0;
147+
char v;
148+
149+
pullit(buf, &v, &index);
150+
pullit(buf, &v, &index);
151+
pullit(buf, &v, &index);
152+
}

tools/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ add_clang_subdirectory(driver)
55
add_clang_subdirectory(clang-format)
66
add_clang_subdirectory(clang-format-vs)
77
add_clang_subdirectory(clang-fuzzer)
8+
add_clang_subdirectory(checked-c-convert)
89

910
add_clang_subdirectory(c-index-test)
1011

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
set( LLVM_LINK_COMPONENTS
2+
${LLVM_TARGETS_TO_BUILD}
3+
Option
4+
Support
5+
)
6+
7+
add_clang_executable(checked-c-convert
8+
CheckedCConvert.cpp
9+
NewTyp.cpp
10+
ProgramInfo.cpp
11+
MappingVisitor.cpp
12+
ConstraintBuilder.cpp
13+
PersistentSourceLoc.cpp
14+
Constraints.cpp
15+
)
16+
17+
target_link_libraries(checked-c-convert
18+
clangAST
19+
clangBasic
20+
clangDriver
21+
clangFrontend
22+
clangRewriteFrontend
23+
clangStaticAnalyzerFrontend
24+
clangTooling
25+
)
26+
27+
install(TARGETS checked-c-convert
28+
RUNTIME DESTINATION bin)

0 commit comments

Comments
 (0)