Skip to content

Commit d37e5ca

Browse files
Fix array bounds heuristics on itype parameters (#654)
The internal constraint variable for function parameters was used to checked the solved pointer type when adding array bounds heuristics. This made itype parameters look like wild pointers instead of array or nt array pointers, so the heuristics were not applied. Heuristics are now applied based on the external parameter, which solves to a checked type for itype parameters. This resolves the remaining issue in #487
1 parent 12fd211 commit d37e5ca

File tree

2 files changed

+55
-11
lines changed

2 files changed

+55
-11
lines changed

clang/lib/3C/ArrayBoundsInferenceConsumer.cpp

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -118,16 +118,20 @@ static bool needArrayBounds(Expr *E, ProgramInfo &Info, ASTContext *C) {
118118
return false;
119119
}
120120

121+
static bool
122+
needArrayBounds(ConstraintVariable *CV, ProgramInfo &Info, bool IsNtArr) {
123+
const auto &E = Info.getConstraints().getVariables();
124+
if (IsNtArr)
125+
return needNTArrayBounds(CV, E);
126+
return needArrayBounds(CV, E);
127+
}
128+
121129
static bool needArrayBounds(Decl *D, ProgramInfo &Info, ASTContext *C,
122130
bool IsNtArr) {
123-
const auto &E = Info.getConstraints().getVariables();
124131
CVarOption CVar = Info.getVariable(D, C);
125132
if (CVar.hasValue()) {
126133
ConstraintVariable &CV = CVar.getValue();
127-
if ((!IsNtArr && needArrayBounds(&CV, E)) ||
128-
(IsNtArr && needNTArrayBounds(&CV, E)))
129-
return true;
130-
return false;
134+
return needArrayBounds(&CV, Info, IsNtArr);
131135
}
132136
return false;
133137
}
@@ -440,6 +444,11 @@ bool GlobalABVisitor::VisitFunctionDecl(FunctionDecl *FD) {
440444
std::map<unsigned, std::pair<std::string, BoundsKey>> ParamNtArrays;
441445
std::map<unsigned, std::pair<std::string, BoundsKey>> LengthParams;
442446

447+
// The FVConstraint is needed to access the external parameter
448+
// ConstraintVariables. External CVs are required because these
449+
// are there variables can solve to a checked array type when the
450+
// parameter has an itype while the internals will solve to WILD.
451+
FVConstraint *FV = Info.getFuncConstraint(FD, Context);
443452
for (unsigned I = 0; I < FT->getNumParams(); I++) {
444453
ParmVarDecl *PVD = FD->getParamDecl(I);
445454
BoundsKey PK;
@@ -451,14 +460,14 @@ bool GlobalABVisitor::VisitFunctionDecl(FunctionDecl *FD) {
451460
// Here, we are using heuristics. So we only use heuristics when
452461
// there are no bounds already computed.
453462
if (!ABInfo.getBounds(PK)) {
454-
if (needArrayBounds(PVD, Info, Context, true)) {
455-
// Is this an NTArray?
463+
PVConstraint *ParamCV = FV->getExternalParam(I);
464+
const EnvironmentMap &Env = Info.getConstraints().getVariables();
465+
// Is this an NTArray?
466+
if (needNTArrayBounds(ParamCV, Env))
456467
ParamNtArrays[I] = PVal;
457-
}
458-
if (needArrayBounds(PVD, Info, Context, false)) {
459-
// Is this an array?
468+
// Is this an array?
469+
if (needArrayBounds(ParamCV, Env))
460470
ParamArrays[I] = PVal;
461-
}
462471
}
463472

464473
// If this is a length field?
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// RUN: rm -rf %t*
2+
// RUN: 3c -base-dir=%S -addcr %s -- | FileCheck -match-full-lines -check-prefixes="CHECK,CHECK_NOALL" %s
3+
// RUN: 3c -base-dir=%S -alltypes -addcr %s -- | FileCheck -match-full-lines -check-prefixes="CHECK,CHECK_ALL" %s
4+
// RUN: 3c -base-dir=%S -alltypes -addcr %s -- | %clang -c -x c -o /dev/null -
5+
// RUN: 3c -base-dir=%S -alltypes -output-dir=%t.checked %s --
6+
// RUN: 3c -base-dir=%t.checked -alltypes %t.checked/arrboundsheuristicsitype.c -- | diff %t.checked/arrboundsheuristicsitype.c -
7+
8+
// Verify that array bounds heuristics are correctly applied to parameters with
9+
// itypes.
10+
11+
void foo(void *);
12+
13+
void test0(int *a, int len) {
14+
//CHECK_ALL: void test0(int *a : itype(_Array_ptr<int>) count(len), int len) {
15+
//CHECK_NOALL: void test0(int *a : itype(_Ptr<int>), int len) {
16+
foo(a);
17+
(void) a[len - 1];
18+
}
19+
20+
void test1(int *a : itype(_Array_ptr<int>), int len) {
21+
//CHECK_ALL: void test1(int *a : itype(_Array_ptr<int>) count(len), int len) {
22+
//CHECK_NOALL: void test1(int *a : itype(_Ptr<int>), int len) {
23+
foo(a);
24+
(void) a[len - 1];
25+
}
26+
27+
#include<stdlib.h>
28+
29+
void test2(int *a, int len) {
30+
//CHECK_ALL: void test2(int *a : itype(_Array_ptr<int>) count(len), int len) {
31+
//CHECK_NOALL: void test2(int *a : itype(_Ptr<int>), int len) {
32+
a = malloc(sizeof(int)*len);
33+
foo(a);
34+
(void) a[len - 1];
35+
}

0 commit comments

Comments
 (0)