Skip to content

Commit ad9b01e

Browse files
authored
* Fixing issue: correctcomputation#390 * Adding -verify
1 parent a17fd2d commit ad9b01e

File tree

4 files changed

+76
-50
lines changed

4 files changed

+76
-50
lines changed

clang/include/clang/3C/ConstraintsGraph.h

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -150,11 +150,13 @@ class DataGraph
150150
}
151151
}
152152

153-
bool getNeighbors(Data D, std::set<Data> &DataSet, bool Succ) {
153+
bool getNeighbors(Data D, std::set<Data> &DataSet, bool Succ,
154+
bool Append = false) {
154155
NodeType *N = this->findNode(D);
155156
if (N == nullptr)
156157
return false;
157-
DataSet.clear();
158+
if (!Append)
159+
DataSet.clear();
158160
llvm::SetVector<EdgeType *> Edges;
159161
if (Succ)
160162
Edges = N->getEdges();
@@ -165,12 +167,12 @@ class DataGraph
165167
return !DataSet.empty();
166168
}
167169

168-
bool getSuccessors(Data D, std::set<Data> &DataSet) {
169-
return getNeighbors(D, DataSet, true);
170+
bool getSuccessors(Data D, std::set<Data> &DataSet, bool Append = false) {
171+
return getNeighbors(D, DataSet, true, Append);
170172
}
171173

172-
bool getPredecessors(Data D, std::set<Data> &DataSet) {
173-
return getNeighbors(D, DataSet, false);
174+
bool getPredecessors(Data D, std::set<Data> &DataSet, bool Append = false) {
175+
return getNeighbors(D, DataSet, false, Append);
174176
}
175177

176178
NodeType *findNode(Data D) {

clang/lib/3C/AVarBoundsInfo.cpp

Lines changed: 38 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -601,11 +601,13 @@ void AvarBoundsInference::mergeReachableProgramVars(
601601
if (!TmpB->isNumConstant()) {
602602
// We give preference to non-constant lengths.
603603
BVar = TmpB;
604-
} else if (!this->BI->areSameProgramVar(BVar->getKey(),
605-
TmpB->getKey())) {
606-
// If both are different constants?
607-
BVar = nullptr;
608-
break;
604+
} else {
605+
// If we need to merge two constants? Pick the lesser value.
606+
int CVal = std::stoi(BVar->getVarName());
607+
int TmpVal = std::stoi(TmpB->getVarName());
608+
if (TmpVal < CVal) {
609+
BVar = TmpB;
610+
}
609611
}
610612
} else if (!TmpB->isNumConstant() && BVar->getKey() != TmpB->getKey()) {
611613
// If they are different variables?
@@ -737,22 +739,6 @@ bool AvarBoundsInference::getRelevantBounds(BoundsKey BK,
737739
return HasBounds;
738740
}
739741

740-
// Variable comparison. Comparator implementation: where given two BoundsKey
741-
// they are checked to see if they correspond to the same program variable.
742-
struct BVarCmp {
743-
public:
744-
BVarCmp(AVarBoundsInfo *ABI) { this->ABInfo = ABI; }
745-
bool operator()(BoundsKey A, BoundsKey B) const {
746-
if (this->ABInfo != nullptr && this->ABInfo->areSameProgramVar(A, B)) {
747-
return false;
748-
}
749-
return A < B;
750-
};
751-
752-
private:
753-
AVarBoundsInfo *ABInfo;
754-
};
755-
756742
bool AvarBoundsInference::areDeclaredBounds(
757743
BoundsKey K,
758744
const std::pair<ABounds::BoundsKind, std::set<BoundsKey>> &Bnds) {
@@ -827,7 +813,7 @@ bool AvarBoundsInference::predictBounds(BoundsKey K,
827813
if (!InferredNBnds.empty()) {
828814
// All the possible inferred bounds for K
829815
InferredKBnds.clear();
830-
std::set<BoundsKey> TmpBKeys;
816+
std::set<BoundsKey> TmpBKeys, AllKeys;
831817
// TODO: Figure out if there is a discrepency and try to implement
832818
// root-cause analysis.
833819

@@ -838,16 +824,23 @@ bool AvarBoundsInference::predictBounds(BoundsKey K,
838824
InferredKBnds[INB.first] = INB.second;
839825
} else {
840826
TmpBKeys.clear();
841-
// Here, we should use intersection by taking care of comparing
842-
// bounds key that correspond to the same constant.
843-
// Note, DO NOT use findIntersection here, as we need to take
844-
// care of comparing bounds key that correspond to the same
845-
// constant.
827+
AllKeys.clear();
828+
// Find intersection between the current bounds and the
829+
// bounds propagated from current neighbour, i.e., INB.first.
846830
auto &S1 = InferredKBnds[INB.first];
847831
auto &S2 = INB.second;
848-
std::set_intersection(S1.begin(), S1.end(), S2.begin(), S2.end(),
849-
std::inserter(TmpBKeys, TmpBKeys.begin()),
850-
BVarCmp(this->BI));
832+
// Find intersection of bounds propagated from all neighbours.
833+
findIntersection(S1, S2, TmpBKeys);
834+
835+
AllKeys = S1;
836+
AllKeys.insert(S2.begin(), S2.end());
837+
// Also, add all constants as potential bounds so that we can pick
838+
// a constant with least value later.
839+
for (auto CK: AllKeys) {
840+
auto *CKVar = this->BI->getProgramVar(CK);
841+
if (CKVar != nullptr && CKVar->isNumConstant())
842+
TmpBKeys.insert(CK);
843+
}
851844
InferredKBnds[INB.first] = TmpBKeys;
852845
}
853846
}
@@ -1132,20 +1125,18 @@ void AVarBoundsInfo::computerArrPointers(ProgramInfo *PI,
11321125
// counterparts.
11331126
std::set<BoundsKey> CtxSensBKeys;
11341127
CtxSensBKeys.clear();
1135-
std::set<BoundsKey> TmpBKeys, TmpBKeysF;
1128+
std::set<BoundsKey> TmpBKeys;
11361129
for (auto BK : ArrPointers) {
1137-
TmpBKeys.clear();
1138-
ProgVarGraph.getPredecessors(BK, TmpBKeys);
1139-
TmpBKeysF.insert(TmpBKeys.begin(), TmpBKeys.end());
1140-
TmpBKeys.clear();
1141-
ProgVarGraph.getSuccessors(BK, TmpBKeys);
1142-
TmpBKeysF.insert(TmpBKeys.begin(), TmpBKeys.end());
1143-
for (auto TBK : TmpBKeysF) {
1144-
ProgramVar *TmpPVar = getProgramVar(TBK);
1145-
if (TmpPVar != nullptr) {
1146-
if (isa<CtxFunctionArgScope>(TmpPVar->getScope())) {
1147-
CtxSensBKeys.insert(TBK);
1148-
}
1130+
CtxSensProgVarGraph.getSuccessors(BK, TmpBKeys, true);
1131+
CtxSensProgVarGraph.getPredecessors(BK, TmpBKeys, true);
1132+
RevCtxSensProgVarGraph.getSuccessors(BK, TmpBKeys, true);
1133+
RevCtxSensProgVarGraph.getPredecessors(BK, TmpBKeys, true);
1134+
}
1135+
for (auto TBK : TmpBKeys) {
1136+
ProgramVar *TmpPVar = getProgramVar(TBK);
1137+
if (TmpPVar != nullptr) {
1138+
if (isa<CtxFunctionArgScope>(TmpPVar->getScope())) {
1139+
CtxSensBKeys.insert(TBK);
11491140
}
11501141
}
11511142
}
@@ -1193,6 +1184,10 @@ bool AVarBoundsInfo::performFlowAnalysis(ProgramInfo *PI) {
11931184
// Repopulate array bounds key.
11941185
ArrPointerBoundsKey.clear();
11951186
ArrPointerBoundsKey.insert(ArrPointers.begin(), ArrPointers.end());
1187+
// All BoundsKey that has bounds are also array pointers.
1188+
for (auto &T : this->BInfo) {
1189+
ArrPointerBoundsKey.insert(T.first);
1190+
}
11961191

11971192
// Keep only highest priority bounds.
11981193
// Any thing changed? which means bounds of a variable changed

clang/lib/3C/ConstraintResolver.cpp

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,8 @@ CVarSet ConstraintResolver::getInvalidCastPVCons(CastExpr *E) {
190190
// ignore parts of it that do not contribute to the final result
191191
CVarSet ConstraintResolver::getExprConstraintVars(Expr *E) {
192192
CVarSet EmptyCSet;
193+
auto &ABInfo = Info.getABoundsInfo();
194+
193195
if (E != nullptr) {
194196
auto &CS = Info.getConstraints();
195197
QualType TypE = E->getType();
@@ -535,7 +537,6 @@ CVarSet ConstraintResolver::getExprConstraintVars(Expr *E) {
535537

536538
// Make the bounds key context sensitive.
537539
if (NewCV->hasBoundsKey()) {
538-
auto &ABInfo = Info.getABoundsInfo();
539540
auto CSensBKey =
540541
ABInfo.getContextSensitiveBoundsKey(CE, NewCV->getBoundsKey());
541542
NewCV->setBoundsKey(CSensBKey);
@@ -600,6 +601,15 @@ CVarSet ConstraintResolver::getExprConstraintVars(Expr *E) {
600601
new PVConstraint(Str->getType(), nullptr, Str->getStmtClassName(),
601602
Info, *Context, nullptr);
602603
P->constrainOuterTo(CS, CS.getNTArr()); // NB: ARR already there
604+
605+
BoundsKey TmpKey = ABInfo.getRandomBKey();
606+
P->setBoundsKey(TmpKey);
607+
608+
BoundsKey CBKey = ABInfo.getConstKey(Str->getByteLength());
609+
ABounds *NB = new CountBound(CBKey);
610+
ABInfo.replaceBounds(TmpKey, Declared, NB);
611+
612+
603613
T = {P};
604614

605615
Ret = T;

clang/test/3C/multiconstant_bounds.c

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// Tests for the 3C.
2+
//
3+
// When multiple constants are potential bounds, pick the lower constant.
4+
// Issue: https://github.com/correctcomputation/checkedc-clang/issues/390
5+
//
6+
// RUN: 3c -alltypes %s | FileCheck -match-full-lines %s
7+
// RUN: 3c -alltypes %s | %clang -c -fcheckedc-extension -Xclang -verify -x c -o %t1.unused -
8+
// expected-no-diagnostics
9+
//
10+
int a(char * : itype(_Nt_array_ptr<char>));
11+
//CHECK: int a(char * : itype(_Nt_array_ptr<char>));
12+
void b(char *p) { a(p); }
13+
//CHECK: void b(_Nt_array_ptr<char> p : count(4)) { a(p); }
14+
void c(void) {
15+
char foo[256];
16+
b(foo);
17+
b("test");
18+
}
19+
//CHECK: char foo _Nt_checked[256];

0 commit comments

Comments
 (0)