Skip to content

Commit

Permalink
Merge pull request #91 from plum-umd/FunctionSets
Browse files Browse the repository at this point in the history
Function sets
  • Loading branch information
Machiry committed Jun 10, 2020
2 parents e50fbd2 + 078a502 commit ed471f6
Show file tree
Hide file tree
Showing 2 changed files with 97 additions and 3 deletions.
20 changes: 17 additions & 3 deletions clang/lib/CConv/ConstraintBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,10 +82,24 @@ class FunctionVisitor : public RecursiveASTVisitor<FunctionVisitor> {

bool VisitCallExpr(CallExpr *E) {
Decl *D = E->getCalleeDecl();
if (!D)
return true;
std::set<ConstraintVariable *> FVCons;
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
if (D == nullptr) {
// If the callee declaration could not be found, then we're doing some
// sort of indirect call through an array or conditional. FV constraints
// can be obtained for this from getExprConstraintVars.
Expr *CalledExpr = E->getCallee();
FVCons = CB.getExprConstraintVars(CalledExpr, CalledExpr->getType());

// When multiple function variables are used in the same expression, they
// must have the same type.
if(FVCons.size() > 1) {
PersistentSourceLoc PL = PersistentSourceLoc::mkPSL(CalledExpr, *Context);
constrainConsVarGeq(FVCons, FVCons, Info.getConstraints(), &PL,
Same_to_Same, false, false, &Info);
}

handleFunctionCall(E, FVCons);
} else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
// Get the function declaration, if exists
if (getDeclaration(FD) != nullptr) {
FD = getDeclaration(FD);
Expand Down
80 changes: 80 additions & 0 deletions clang/test/CheckedCRewriter/fn_sets.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
// RUN: cconv-standalone %s -- | FileCheck -match-full-lines %s

// Tests relating to issue #86 Handling sets of functions

// In the first test case, y WILD due to the (int*)5 assignment. This
// propagates to everything else.

int * f(int *x) {
// CHECK: int * f(int *x) {
return x;
}

int * g(int *y) {
// CHECK: int * g(int *y) {
y = (int*)5;
return 0;
}

void foo(int *z) {
// CHECK: void foo(int *z) {
int *w = (0 ? f : g)(z);
// CHECK: int *w = (0 ? f : g)(z);
}


// The second case verifies that the pointer are still marked checked in the
// absence of anything weird.

int * f1(int *x) {
// CHECK: _Ptr<int> f1(_Ptr<int> x) {
return x;
}

int * g1(int *y) {
// CHECK: _Ptr<int> g1(_Ptr<int> y) {
return 0;
}

void foo1(int *z) {
// CHECK: void foo1(_Ptr<int> z) {
int *w = (0 ? f1 : g1)(z);
// CHECK: _Ptr<int> w = (0 ? f1 : g1)(z);
}


// Testing Something with a larger set of functions

int *a() {
// CHECK: int *a() {
return 0;
}
int *b() {
// CHECK: int *b() {
return 0;
}
int *c() {
// CHECK: int *c() {
return 0;
}
int *d() {
// CHECK: int *d() {
return 0;
}
int *e() {
// CHECK: int *e() {
return (int*) 1;
}
int *i() {
// CHECK: _Ptr<int> i(void) {
return 0;
}

void bar() {
int *w = (0 ? (0 ? a : b) : (0 ? c : (0 ? d : e)))();
// CHECK: int *w = (0 ? (0 ? a : b) : (0 ? c : (0 ? d : e)))();
int *x = a();
// CHECK: int *x = a();
int *y = i();
// CHECK: _Ptr<int> y = i();
}

0 comments on commit ed471f6

Please sign in to comment.