Skip to content

Commit a929d23

Browse files
Handling function pointer bounds (#587)
* 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]>
1 parent 2a96dfb commit a929d23

File tree

3 files changed

+53
-21
lines changed

3 files changed

+53
-21
lines changed

clang/lib/3C/AVarBoundsInfo.cpp

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -601,9 +601,15 @@ PotentialBoundsInfo::addPotentialBoundsPOne(BoundsKey BK,
601601
}
602602

603603
bool AVarBoundsInfo::isValidBoundVariable(clang::Decl *D) {
604-
// All parameters, return, and field values are valid bound variables.
605-
if (D && (isa<ParmVarDecl>(D) || isa<FunctionDecl>(D) || isa<FieldDecl>(D)))
604+
// All return and field values are valid bound variables.
605+
if (D && (isa<FunctionDecl>(D) || isa<FieldDecl>(D)))
606606
return true;
607+
608+
// For Parameters, check if they belong to a valid function.
609+
// Function pointer types are not considered valid functions, so function
610+
// pointer parameters are are disqualified as valid bound variables here.
611+
if (auto *PD = dyn_cast_or_null<ParmVarDecl>(D))
612+
return PD->getParentFunctionOrMethod() != nullptr;
607613

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

631637
bool AVarBoundsInfo::tryGetVariable(clang::Decl *D, BoundsKey &R) {
638+
bool RetVal = false;
632639
if (isValidBoundVariable(D)) {
640+
RetVal = true;
633641
if (ParmVarDecl *PD = dyn_cast<ParmVarDecl>(D)) {
634-
if (PD->getParentFunctionOrMethod())
642+
if (PD->getParentFunctionOrMethod()) {
635643
R = getVariable(PD);
644+
} else {
645+
RetVal = false;
646+
}
636647
} else if (VarDecl *VD = dyn_cast<VarDecl>(D)) {
637648
R = getVariable(VD);
638649
} else if (FieldDecl *FD = dyn_cast<FieldDecl>(D)) {
@@ -642,9 +653,9 @@ bool AVarBoundsInfo::tryGetVariable(clang::Decl *D, BoundsKey &R) {
642653
} else {
643654
assert(false && "Invalid Declaration\n");
644655
}
645-
return true;
656+
return RetVal;
646657
}
647-
return false;
658+
return RetVal;
648659
}
649660

650661
bool AVarBoundsInfo::tryGetVariable(clang::Expr *E,
@@ -1506,4 +1517,4 @@ AVarBoundsInfo::getCtxSensFieldBoundsKey(Expr *E, ASTContext *C,
15061517
Ret.insert(NewBK);
15071518
}
15081519
return Ret;
1509-
}
1520+
}

clang/lib/3C/ConstraintVariables.cpp

Lines changed: 24 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2046,22 +2046,31 @@ FVComponentVariable::mkString(Constraints &CS, bool EmitName) const {
20462046
std::string
20472047
FVComponentVariable::mkTypeStr(Constraints &CS, bool EmitName,
20482048
std::string UseName) const {
2049+
std::string Ret;
20492050
// if checked or given new name, generate type
2050-
if (hasCheckedSolution(CS) || (EmitName && !UseName.empty()))
2051-
return ExternalConstraint->mkString(CS, EmitName, false,
2052-
false, false, UseName);
2053-
// if no need to generate type, try to use source
2054-
if (!SourceDeclaration.empty())
2055-
return SourceDeclaration;
2056-
// if no source and no name, generate nameless type
2057-
if (EmitName && ExternalConstraint->getName().empty())
2058-
return ExternalConstraint->getOriginalTy();
2059-
// if no source and a have a needed name, generate named type
2060-
if (EmitName)
2061-
return ExternalConstraint->getRewritableOriginalTy()
2062-
+ ExternalConstraint->getName();
2063-
// if no source and don't need a name, generate type ready for one
2064-
return ExternalConstraint->getRewritableOriginalTy();
2051+
if (hasCheckedSolution(CS) || (EmitName && !UseName.empty())) {
2052+
Ret = ExternalConstraint->mkString(CS, EmitName, false,
2053+
false, false, UseName);
2054+
} else {
2055+
// if no need to generate type, try to use source
2056+
if (!SourceDeclaration.empty())
2057+
Ret = SourceDeclaration;
2058+
// if no source and no name, generate nameless type
2059+
else if (EmitName && ExternalConstraint->getName().empty())
2060+
Ret = ExternalConstraint->getOriginalTy();
2061+
// if no source and a have a needed name, generate named type
2062+
else if (EmitName)
2063+
Ret = ExternalConstraint->getRewritableOriginalTy() +
2064+
ExternalConstraint->getName();
2065+
else
2066+
// if no source and don't need a name, generate type ready for one
2067+
Ret = ExternalConstraint->getRewritableOriginalTy();
2068+
}
2069+
2070+
if (ExternalConstraint->srcHasBounds())
2071+
Ret += " : " + ExternalConstraint->getBoundsStr();
2072+
2073+
return Ret;
20652074
}
20662075

20672076
std::string FVComponentVariable::mkItypeStr(Constraints &CS) const {

clang/test/3C/funcptr_bounds.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
/**
2+
Check function pointer bounds rewriting.
3+
**/
4+
5+
// RUN: rm -rf %t*
6+
// RUN: 3c -base-dir=%S -alltypes %s -- | FileCheck -match-full-lines -check-prefixes="CHECK_ALL","CHECK" %s
7+
// RUN: 3c -base-dir=%S -alltypes %s -- | %clang -c -fcheckedc-extension -x c -o %t1.unusedl -
8+
// RUN: 3c -base-dir=%S %s -- | FileCheck -match-full-lines -check-prefixes="CHECK_NOALL","CHECK" %s
9+
// RUN: 3c -base-dir=%S %s -- | %clang -c -fcheckedc-extension -x c -o %t2.unused -
10+
11+
void (*fn)(_Array_ptr<char> buf : count(l), unsigned int l);
12+
//CHECK: _Ptr<void (_Array_ptr<char> buf : count(l), unsigned int l)> fn = ((void *)0);

0 commit comments

Comments
 (0)