Skip to content

Commit b6146c3

Browse files
authored
Merge pull request #336 from kyleheadley/bugfix#264
Bugfix#264
2 parents 74d2913 + 5f4d71c commit b6146c3

File tree

3 files changed

+95
-26
lines changed

3 files changed

+95
-26
lines changed

clang/include/clang/3C/ProgramInfo.h

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -81,9 +81,6 @@ class ProgramInfo : public ProgramVariableAdder {
8181
FVConstraint *getStaticFuncConstraint(std::string FuncName,
8282
std::string FileName) const;
8383

84-
// Check if the given function is an extern function.
85-
bool isAnExternFunction(const std::string &FName);
86-
8784
// Called when we are done adding constraints and visiting ASTs.
8885
// Links information about global symbols together and adds
8986
// constraints where appropriate.
@@ -128,10 +125,9 @@ class ProgramInfo : public ProgramVariableAdder {
128125
// Is the ProgramInfo persisted? Only tested in asserts. Starts at true.
129126
bool Persisted;
130127

131-
// Map of global decls for which we don't have a body, the keys are
132-
// names of external functions/vars, the value is whether the body/def
128+
// Map of global decls for which we don't have a definition, the keys are
129+
// names of external vars, the value is whether the def
133130
// has been seen before.
134-
std::map<std::string, bool> ExternFunctions;
135131
std::map<std::string, bool> ExternGVars;
136132

137133
// Maps for global/static functions, global variables

clang/lib/3C/ProgramInfo.cpp

Lines changed: 33 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -323,17 +323,16 @@ bool ProgramInfo::link() {
323323
}
324324
}
325325

326-
// For every global function that is an unresolved external, constrain
327-
// its parameter types to be wild. Unless it has a bounds-safe annotation.
328-
for (const auto &U : ExternFunctions) {
326+
// For every global function that is an unresolved external, constrain
327+
// its parameter types to be wild. Unless it has a bounds-safe annotation.
328+
for (const auto &U : ExternalFunctionFVCons) {
329+
std::string FuncName = U.first;
330+
FVConstraint *G = U.second;
329331
// If we've seen this symbol, but never seen a body for it, constrain
330332
// everything about it.
331-
std::string FuncName = U.first;
332-
if (!U.second && !isExternOkay(FuncName)) {
333-
// Some global symbols we don't need to constrain to wild, like
334-
// malloc and free. Check those here and skip if we find them.
335-
FVConstraint *G = getExtFuncDefnConstraint(FuncName);
336-
assert("Function constraints could not be found!" && G != nullptr);
333+
// Some global symbols we don't need to constrain to wild, like
334+
// malloc and free. Check those here and skip if we find them.
335+
if (!G->hasBody() && !isExternOkay(FuncName)) {
337336

338337
// If there was a checked type on a variable in the input program, it
339338
// should stay that way. Otherwise, we shouldn't be adding a checked type
@@ -348,14 +347,35 @@ bool ProgramInfo::link() {
348347
G->getParamVar(I)->constrainToWild(CS, Rsn);
349348
}
350349
}
350+
// repeat for static functions
351+
//
352+
// Static functions that don't have a body will always cause a linking
353+
// error during compilation. They may still be useful as code is developed,
354+
// so we treat them as if they are external, and constrain parameters
355+
// to wild as appropriate.
356+
for (const auto &U :StaticFunctionFVCons) {
357+
for (const auto &V :U.second) {
358+
359+
std::string FileName = U.first;
360+
std::string FuncName = V.first;
361+
FVConstraint *G = V.second;
362+
if (!G->hasBody()) {
363+
364+
std::string Rsn =
365+
"Unchecked pointer in parameter or return of static function " +
366+
FuncName + " in " + FileName;
367+
if (!G->getReturnVar()->getIsGeneric())
368+
G->getReturnVar()->constrainToWild(CS, Rsn);
369+
for (unsigned I = 0; I < G->numParams(); I++)
370+
if (!G->getParamVar(I)->getIsGeneric())
371+
G->getParamVar(I)->constrainToWild(CS, Rsn);
372+
}
373+
}
374+
}
351375

352376
return true;
353377
}
354378

355-
bool ProgramInfo::isAnExternFunction(const std::string &FName) {
356-
return !ExternFunctions[FName];
357-
}
358-
359379
// Populate Variables, VarDeclToStatement, RVariables, and DepthMap with
360380
// AST data structures that correspond do the data stored in PDMap and
361381
// ReversePDMap.
@@ -463,13 +483,6 @@ bool ProgramInfo::insertNewFVConstraint(FunctionDecl *FD, FVConstraint *FVCon,
463483
// external method.
464484
Ret = insertIntoExternalFunctionMap(ExternalFunctionFVCons, FuncName, FVCon,
465485
FD, C);
466-
bool IsDef = FVCon->hasBody();
467-
if (IsDef) {
468-
ExternFunctions[FuncName] = true;
469-
} else {
470-
if (!ExternFunctions[FuncName])
471-
ExternFunctions[FuncName] = false;
472-
}
473486
} else {
474487
// static method
475488
auto Psl = PersistentSourceLoc::mkPSL(FD, *C);

clang/test/3C/bodiless.c

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
// RUN: 3c %s > %S/temp_bodiless.c
2+
// RUN: %clang -c %S/temp_bodiless.c
3+
// RUN: FileCheck -match-full-lines --input-file %S/temp_bodiless.c %s
4+
// RUN: rm %S/temp_bodiless.c
5+
6+
/***********************************************/
7+
/* Tests that functions without bodies */
8+
/* are marked wild when there is no interface */
9+
/***********************************************/
10+
11+
static int *foo1(void) { return (void *)0; }
12+
void test1() {
13+
int *a = foo1();
14+
}
15+
//CHECK _Ptr<int> a = foo1();
16+
17+
static int *foo2(void);
18+
void test2() {
19+
int *a = foo2();
20+
}
21+
//CHECK int *a = foo2();
22+
23+
int *foo3(void) { return (void *)0; }
24+
void test3() {
25+
int *a = foo3();
26+
}
27+
//CHECK: _Ptr<int> a = foo3();
28+
29+
int *foo4(void);
30+
void test4() {
31+
int *a = foo4();
32+
}
33+
//CHECK: int *a = foo4();
34+
35+
int *foo5(void) : itype(_Ptr<int>);
36+
void test5() {
37+
int *a = foo5();
38+
}
39+
//CHECK: _Ptr<int> a = foo5();
40+
41+
extern int *foo6(void);
42+
void test6() {
43+
int *a = foo6();
44+
}
45+
//CHECK: int *a = foo6();
46+
47+
extern int *foo7(void) : itype(_Ptr<int>);
48+
void test7() {
49+
int *a = foo7();
50+
}
51+
//CHECK: _Ptr<int> a = foo7();
52+
53+
54+
// parameters are not defined and therefore unchecked
55+
extern int *foo8() : itype(_Ptr<int>);
56+
void test8() {
57+
int *a = foo8();
58+
}
59+
//CHECK: int *a = foo8();
60+

0 commit comments

Comments
 (0)