Skip to content

Commit f8ee74e

Browse files
Cleanup
1 parent cd5d4ca commit f8ee74e

File tree

5 files changed

+51
-42
lines changed

5 files changed

+51
-42
lines changed

clang/include/clang/3C/AVarBoundsInfo.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,7 @@ class AVarBoundsInfo {
262262
// Check if the bounds keys will need to be rewritten with range bounds. This
263263
// is true for bounds keys that are subject to pointer arithmetic but
264264
// otherwise have inferred bounds.
265-
bool needsRangeBound(BoundsKey BK);
265+
bool needsRangeBound(ConstraintVariable *CV);
266266

267267
// Get the ProgramVar for the provided VarKey.
268268
ProgramVar *getProgramVar(BoundsKey VK);

clang/lib/3C/AVarBoundsInfo.cpp

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -813,6 +813,10 @@ BoundsKey AVarBoundsInfo::getVariable(clang::VarDecl *VD) {
813813
insertProgramVar(NK, PVar);
814814
if (isPtrOrArrayType(VD->getType())) {
815815
PointerBoundsKey.insert(NK);
816+
// Global variables cannot be given range bounds because it is not
817+
// possible to initialize a duplicated pointer variable with the same
818+
// value as the original.
819+
// TODO: Followup issue.
816820
if (!VD->isLocalVarDeclOrParm())
817821
IneligibleForRangeBounds.insert(NK);
818822
}
@@ -880,6 +884,10 @@ BoundsKey AVarBoundsInfo::getVariable(clang::FieldDecl *FD) {
880884
insertProgramVar(NK, PVar);
881885
if (isPtrOrArrayType(FD->getType())) {
882886
PointerBoundsKey.insert(NK);
887+
// Fields are not rewritten with range bounds because we would need to
888+
// duplicate the field and update all structure initializations to
889+
// properly set the new field.
890+
// TODO: Followup issue.
883891
IneligibleForRangeBounds.insert(NK);
884892
}
885893
}
@@ -951,16 +959,17 @@ bool AVarBoundsInfo::handleAssignment(clang::Decl *L, CVarOption LCVars,
951959
}
952960

953961
bool AVarBoundsInfo::addAssignment(BoundsKey L, BoundsKey R) {
954-
// Before adding an edge from L to R or R to L, first verify that the source
955-
// BoundsKey for the edge is not computed by pointer arithmetic. The pointer
956-
// arithmetic invalidates the bounds on the pointer, so bounds should not
957-
// propagate through it. The bounds are allowed to exist on the pointer
958-
// because they will emitted as range bounds based on a different base
959-
// pointer. For future work, all bounds "down stream" of pointer arithmetic
960-
// could also use range bounds using the same base pointer.
961962
auto AddEdgeUnlessPointerArithmetic = [this](BoundsKey From, BoundsKey To) {
962-
if (!hasPointerArithmetic(From) &&
963-
(!hasPointerArithmetic(To) || canInferRangeBounds(To)))
963+
// Verify that the source BoundsKey for the edge is not computed by pointer
964+
// arithmetic. Pointer arithmetic invalidates the bounds on the pointer, so
965+
// bounds should not propagate through it.
966+
// TODO: Followup issue
967+
bool FromValid = !hasPointerArithmetic(From);
968+
// The destination BoundsKey may be computed by pointer arithmetic as long
969+
// 3C can emit range bounds the pointer. If 3C cannot emit range bounds,
970+
// then the incoming edge is not added so that no bounds will be inferred.
971+
bool ToValid = !hasPointerArithmetic(To) || canInferRangeBounds(To);
972+
if (FromValid && ToValid)
964973
ProgVarGraph.addUniqueEdge(From, To);
965974
};
966975

@@ -1016,7 +1025,10 @@ bool AVarBoundsInfo::canInferRangeBounds(BoundsKey BK) {
10161025
return IneligibleForRangeBounds.find(BK) == IneligibleForRangeBounds.end();
10171026
}
10181027

1019-
bool AVarBoundsInfo::needsRangeBound(BoundsKey BK) {
1028+
bool AVarBoundsInfo::needsRangeBound(ConstraintVariable *CV) {
1029+
if (!CV->hasBoundsKey())
1030+
return false;
1031+
BoundsKey BK = CV->getBoundsKey();
10201032
// A pointer should get range bounds if it is computed by pointer arithmetic
10211033
// and would otherwise need bounds. Some pointers (global variables and struct
10221034
// fields) can't be rewritten to use range bounds (by 3C; Checked C does

clang/lib/3C/DeclRewriter.cpp

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,7 @@ void DeclRewriter::buildItypeDecl(PVConstraint *Defn, DeclaratorDecl *Decl,
3737
ProgramInfo &Info, ArrayBoundsRewriter &ABR,
3838
std::vector<std::string> *SDecls) {
3939
bool NeedsRangeBound =
40-
SDecls != nullptr &&
41-
Defn->hasBoundsKey() &&
42-
Info.getABoundsInfo().needsRangeBound(Defn->getBoundsKey());
40+
SDecls != nullptr && Info.getABoundsInfo().needsRangeBound(Defn);
4341
assert("Adding range bounds on return, global variable, or field!" &&
4442
(!NeedsRangeBound || (isa_and_nonnull<VarDecl>(Decl) &&
4543
cast<VarDecl>(Decl)->isLocalVarDeclOrParm())));
@@ -130,9 +128,7 @@ void DeclRewriter::buildCheckedDecl(PVConstraint *Defn, DeclaratorDecl *Decl,
130128
std::vector<std::string> *SDecls) {
131129
// I don't like using SDecls != nullptr as a nullptr as a sentinel like this.
132130
bool NeedsRangeBound =
133-
SDecls != nullptr &&
134-
Defn->hasBoundsKey() &&
135-
Info.getABoundsInfo().needsRangeBound(Defn->getBoundsKey());
131+
SDecls != nullptr && Info.getABoundsInfo().needsRangeBound(Defn);
136132
assert("Adding range bounds on return, global variable, or field!" &&
137133
(!NeedsRangeBound || (isa_and_nonnull<VarDecl>(Decl) &&
138134
cast<VarDecl>(Decl)->isLocalVarDeclOrParm())));

clang/lib/3C/RewriteUtils.cpp

Lines changed: 24 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -431,31 +431,34 @@ class TypeArgumentAdder : public clang::RecursiveASTVisitor<TypeArgumentAdder> {
431431
class AssignmentUpdater : public RecursiveASTVisitor<AssignmentUpdater> {
432432
public:
433433
explicit AssignmentUpdater(ASTContext *C, ProgramInfo &I, Rewriter &R)
434-
: Info(I), CR(I, C), R(R) {}
434+
: ABInfo(I.getABoundsInfo()), CR(I, C), R(R) {}
435435

436436
bool VisitBinaryOperator(BinaryOperator *O) {
437437
if (O->getOpcode() == clang::BO_Assign) {
438438
if (!isAssignmentPointerArithmetic(O->getLHS(), O->getRHS())) {
439-
// TODO: I don't like calling getExprConstraintVars in the rewriting
440-
// because this has been a persistent source of errors in the cast
441-
// placement code.
442439
CVarSet LHSCVs = CR.getExprConstraintVarsSet(O->getLHS());
443-
// FIXME: This isn't always a singleton: `int **a, **b; *(0 ? a : b) = 0;`
444-
// As long as inner pointers can't have bounds, we should be able
445-
// to differ a proper solution.
446-
ConstraintVariable *CV = getOnly(LHSCVs);
447-
if (CV->hasBoundsKey() &&
448-
Info.getABoundsInfo().needsRangeBound(CV->getBoundsKey())) {
449-
std::string TmpVarName = "__3c_tmp_" + CV->getName();
450-
rewriteSourceRange(R, O->getLHS()->getSourceRange(), TmpVarName);
451-
bool InsertFail = R.InsertTextAfterToken(O->getEndLoc(),
452-
", " + CV->getName() +
453-
" = " + TmpVarName);
454-
if (InsertFail) {
455-
// FIXME: Use rewriteSourceRange so that it handle emitting error messages.
456-
llvm::errs()
457-
<< "Rewriting failed while updating assignment!\n";
458-
O->getEndLoc().print(llvm::errs(), R.getSourceMgr());
440+
// It is possible for multiple ConstraintVariables to exist on the LHS
441+
// of an assignment expression; e.g., `*(0 ? a : b) = 0`. If this
442+
// happens, and one of those variables needed range bounds, then the
443+
// following rewriting is not correct. I believe that it can only happen
444+
// when the LHS is a pointer dereference or struct field access.
445+
// Structure fields and inner pointer levels can never have range bounds
446+
// so this case currently is not possible.
447+
assert(LHSCVs.size() == 1 || llvm::count_if(LHSCVs, [this](
448+
ConstraintVariable *CV) { return ABInfo.needsRangeBound(CV); }) == 0);
449+
for (ConstraintVariable *CV: LHSCVs) {
450+
if (ABInfo.needsRangeBound(CV)) {
451+
std::string TmpVarName = "__3c_tmp_" + CV->getName();
452+
rewriteSourceRange(R, O->getLHS()->getSourceRange(), TmpVarName);
453+
bool InsertFail = R.InsertTextAfterToken(O->getEndLoc(),
454+
", " + CV->getName() +
455+
" = " + TmpVarName);
456+
if (InsertFail) {
457+
// FIXME: Use rewriteSourceRange so that it handle emitting error messages.
458+
llvm::errs()
459+
<< "Rewriting failed while updating assignment!\n";
460+
O->getEndLoc().print(llvm::errs(), R.getSourceMgr());
461+
}
459462
}
460463
}
461464
}
@@ -464,7 +467,7 @@ class AssignmentUpdater : public RecursiveASTVisitor<AssignmentUpdater> {
464467
}
465468

466469
private:
467-
ProgramInfo &Info;
470+
AVarBoundsInfo &ABInfo;
468471
ConstraintResolver CR;
469472
Rewriter &R;
470473
};

clang/lib/3C/Utils.cpp

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -614,16 +614,14 @@ class CollectDeclsVisitor : public RecursiveASTVisitor<CollectDeclsVisitor> {
614614
return true;
615615
}
616616

617-
// For a->b; We need to get `a->b` rather than just `b`. This way assignment
617+
// For `a->b` we need to get `a->b` rather than just `b`. This way assignment
618618
// from a field in one instance of a structure to the same field in another
619619
// instance is not treated as pointer arithmetic.
620620
bool VisitMemberExpr(MemberExpr *ME) {
621-
// TODO: Is this cast legit? `getMemberDecl()` returns a `ValueDecl*`, but I
621+
// TODO: Is this cast legit? `getMemberDecl()` returns a `ValueDecl`, but I
622622
// think it can only be a `FieldDecl` for structs in C.
623623
auto *FD = cast<FieldDecl>(ME->getMemberDecl());
624624

625-
// TODO: Is recursively using a new visitor the right thing to do? It feels
626-
// odd.
627625
CollectDeclsVisitor MEVis;
628626
MEVis.TraverseStmt(ME->getBase());
629627
// Field access through variable.

0 commit comments

Comments
 (0)