Skip to content

Commit

Permalink
Handling function pointer bounds (#587)
Browse files Browse the repository at this point in the history
* Handling function pointer bounds

* Update clang/lib/3C/AVarBoundsInfo.cpp

Co-authored-by: John Kastner <[email protected]>

* Update clang/lib/3C/AVarBoundsInfo.cpp

Co-authored-by: John Kastner <[email protected]>

* Update clang/lib/3C/ConstraintVariables.cpp

Co-authored-by: John Kastner <[email protected]>

Co-authored-by: John Kastner <[email protected]>
  • Loading branch information
Machiry and john-h-kastner authored Jun 18, 2021
1 parent 2a96dfb commit a929d23
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 21 deletions.
23 changes: 17 additions & 6 deletions clang/lib/3C/AVarBoundsInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -601,9 +601,15 @@ PotentialBoundsInfo::addPotentialBoundsPOne(BoundsKey BK,
}

bool AVarBoundsInfo::isValidBoundVariable(clang::Decl *D) {
// All parameters, return, and field values are valid bound variables.
if (D && (isa<ParmVarDecl>(D) || isa<FunctionDecl>(D) || isa<FieldDecl>(D)))
// All return and field values are valid bound variables.
if (D && (isa<FunctionDecl>(D) || isa<FieldDecl>(D)))
return true;

// For Parameters, check if they belong to a valid function.
// Function pointer types are not considered valid functions, so function
// pointer parameters are are disqualified as valid bound variables here.
if (auto *PD = dyn_cast_or_null<ParmVarDecl>(D))
return PD->getParentFunctionOrMethod() != nullptr;

// For VarDecls, check if these are are not dummy and have a name.
if (auto *VD = dyn_cast_or_null<VarDecl>(D))
Expand All @@ -629,10 +635,15 @@ void AVarBoundsInfo::insertDeclaredBounds(clang::Decl *D, ABounds *B) {
}

bool AVarBoundsInfo::tryGetVariable(clang::Decl *D, BoundsKey &R) {
bool RetVal = false;
if (isValidBoundVariable(D)) {
RetVal = true;
if (ParmVarDecl *PD = dyn_cast<ParmVarDecl>(D)) {
if (PD->getParentFunctionOrMethod())
if (PD->getParentFunctionOrMethod()) {
R = getVariable(PD);
} else {
RetVal = false;
}
} else if (VarDecl *VD = dyn_cast<VarDecl>(D)) {
R = getVariable(VD);
} else if (FieldDecl *FD = dyn_cast<FieldDecl>(D)) {
Expand All @@ -642,9 +653,9 @@ bool AVarBoundsInfo::tryGetVariable(clang::Decl *D, BoundsKey &R) {
} else {
assert(false && "Invalid Declaration\n");
}
return true;
return RetVal;
}
return false;
return RetVal;
}

bool AVarBoundsInfo::tryGetVariable(clang::Expr *E,
Expand Down Expand Up @@ -1506,4 +1517,4 @@ AVarBoundsInfo::getCtxSensFieldBoundsKey(Expr *E, ASTContext *C,
Ret.insert(NewBK);
}
return Ret;
}
}
39 changes: 24 additions & 15 deletions clang/lib/3C/ConstraintVariables.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2046,22 +2046,31 @@ FVComponentVariable::mkString(Constraints &CS, bool EmitName) const {
std::string
FVComponentVariable::mkTypeStr(Constraints &CS, bool EmitName,
std::string UseName) const {
std::string Ret;
// if checked or given new name, generate type
if (hasCheckedSolution(CS) || (EmitName && !UseName.empty()))
return ExternalConstraint->mkString(CS, EmitName, false,
false, false, UseName);
// if no need to generate type, try to use source
if (!SourceDeclaration.empty())
return SourceDeclaration;
// if no source and no name, generate nameless type
if (EmitName && ExternalConstraint->getName().empty())
return ExternalConstraint->getOriginalTy();
// if no source and a have a needed name, generate named type
if (EmitName)
return ExternalConstraint->getRewritableOriginalTy()
+ ExternalConstraint->getName();
// if no source and don't need a name, generate type ready for one
return ExternalConstraint->getRewritableOriginalTy();
if (hasCheckedSolution(CS) || (EmitName && !UseName.empty())) {
Ret = ExternalConstraint->mkString(CS, EmitName, false,
false, false, UseName);
} else {
// if no need to generate type, try to use source
if (!SourceDeclaration.empty())
Ret = SourceDeclaration;
// if no source and no name, generate nameless type
else if (EmitName && ExternalConstraint->getName().empty())
Ret = ExternalConstraint->getOriginalTy();
// if no source and a have a needed name, generate named type
else if (EmitName)
Ret = ExternalConstraint->getRewritableOriginalTy() +
ExternalConstraint->getName();
else
// if no source and don't need a name, generate type ready for one
Ret = ExternalConstraint->getRewritableOriginalTy();
}

if (ExternalConstraint->srcHasBounds())
Ret += " : " + ExternalConstraint->getBoundsStr();

return Ret;
}

std::string FVComponentVariable::mkItypeStr(Constraints &CS) const {
Expand Down
12 changes: 12 additions & 0 deletions clang/test/3C/funcptr_bounds.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/**
Check function pointer bounds rewriting.
**/

// RUN: rm -rf %t*
// RUN: 3c -base-dir=%S -alltypes %s -- | FileCheck -match-full-lines -check-prefixes="CHECK_ALL","CHECK" %s
// RUN: 3c -base-dir=%S -alltypes %s -- | %clang -c -fcheckedc-extension -x c -o %t1.unusedl -
// RUN: 3c -base-dir=%S %s -- | FileCheck -match-full-lines -check-prefixes="CHECK_NOALL","CHECK" %s
// RUN: 3c -base-dir=%S %s -- | %clang -c -fcheckedc-extension -x c -o %t2.unused -

void (*fn)(_Array_ptr<char> buf : count(l), unsigned int l);
//CHECK: _Ptr<void (_Array_ptr<char> buf : count(l), unsigned int l)> fn = ((void *)0);

0 comments on commit a929d23

Please sign in to comment.