Skip to content

Commit 198d0f3

Browse files
authored
Merge pull request #242 from plum-umd/iss110
Fixing issue #110
2 parents fddb3a8 + df649fc commit 198d0f3

31 files changed

+278
-115
lines changed

clang/include/clang/CConv/ConstraintVariables.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -229,8 +229,10 @@ class PointerVariableConstraint : public ConstraintVariable {
229229
void insertQualType(uint32_t TypeIdx, QualType &QTy);
230230
// This function tries to emit an array size for the variable.
231231
// and returns true if the variable is an array and a size is emitted.
232-
bool emitArraySize(std::ostringstream &Pss, uint32_t TypeIdx, bool &EmitName,
233-
bool &EmittedCheckedAnnotation, bool Nt);
232+
bool emitArraySize(std::stack<std::string> &CheckedArrs, uint32_t TypeIdx,
233+
bool &AllArray, bool &ArrayRun, bool Nt);
234+
void addArrayAnnotations(std::stack<std::string> &CheckedArrs,
235+
std::deque<std::string> &EndStrs);
234236
// Flag to indicate that this constraint is a part of function prototype
235237
// e.g., Parameters or Return.
236238
bool partOFFuncPrototype;

clang/lib/CConv/ConstraintVariables.cpp

Lines changed: 117 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,21 @@ PointerVariableConstraint::PointerVariableConstraint(const QualType &QT,
250250
ArrPresent = IsArr = true;
251251
IsIncompleteArr = Ty->isIncompleteArrayType();
252252

253+
// Boil off the typedefs in the array case.
254+
// TODO this will need to change to properly account for typedefs
255+
bool boiling = true;
256+
while (boiling) {
257+
if (const TypedefType *TydTy = dyn_cast<TypedefType>(Ty)) {
258+
QTy = TydTy->desugar();
259+
Ty = QTy.getTypePtr();
260+
} else if (const ParenType *ParenTy = dyn_cast<ParenType>(Ty)) {
261+
QTy = ParenTy->desugar();
262+
Ty = QTy.getTypePtr();
263+
} else {
264+
boiling = false;
265+
}
266+
}
267+
253268
// See if there is a constant size to this array type at this position.
254269
if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(Ty)) {
255270
arrSizes[TypeIdx] = std::pair<OriginalArrType,uint64_t>(
@@ -259,11 +274,6 @@ PointerVariableConstraint::PointerVariableConstraint(const QualType &QT,
259274
O_UnSizedArray,0);
260275
}
261276

262-
// Boil off the typedefs in the array case.
263-
while (const TypedefType *TydTy = dyn_cast<TypedefType>(Ty)) {
264-
QTy = TydTy->desugar();
265-
Ty = QTy.getTypePtr();
266-
}
267277

268278
// Iterate.
269279
if (const ArrayType *ArrTy = dyn_cast<ArrayType>(Ty)) {
@@ -447,10 +457,17 @@ void PointerVariableConstraint::insertQualType(uint32_t TypeIdx,
447457
QualMap[TypeIdx].insert(RestrictQualification);
448458
}
449459

450-
bool PointerVariableConstraint::emitArraySize(std::ostringstream &Pss,
460+
461+
// emitArraySize
462+
// Take an array or nt_array variable, determines if it is
463+
// a constant array, and if so emits the apprioate syntax for a
464+
// stack-based array. This functions also updates various flags.
465+
bool PointerVariableConstraint::emitArraySize(std::stack<std::string> &CheckedArrs,
451466
uint32_t TypeIdx,
452-
bool &EmitName,
453-
bool &EmittedCheckedAnnotation,
467+
// Is the type only an array
468+
bool &AllArrays,
469+
// Are we processing an array
470+
bool &ArrayRun,
454471
bool Nt) {
455472
bool Ret = false;
456473
if (ArrPresent) {
@@ -459,31 +476,39 @@ bool PointerVariableConstraint::emitArraySize(std::ostringstream &Pss,
459476
OriginalArrType Oat = i->second.first;
460477
uint64_t Oas = i->second.second;
461478

462-
if (EmitName == false) {
463-
EmitName = true;
464-
Pss << getName();
465-
}
479+
std::ostringstream SizeStr;
466480

467-
switch (Oat) {
468-
case O_SizedArray:
469-
if (!EmittedCheckedAnnotation) {
470-
Pss << (Nt ? " _Nt_checked" : " _Checked");
471-
EmittedCheckedAnnotation = true;
472-
}
473-
Pss << "[" << Oas << "]";
474-
Ret = true;
475-
break;
476-
/*case O_UnSizedArray:
477-
Pss << "[]";
478-
Ret = true;
479-
break;*/
480-
default: break;
481+
if (Oat == O_SizedArray) {
482+
SizeStr << (Nt ? " _Nt_checked" : " _Checked");
483+
SizeStr << "[" << Oas << "]";
484+
CheckedArrs.push(SizeStr.str());
485+
ArrayRun = true;
486+
Ret = true;
487+
} else {
488+
AllArrays = ArrayRun = false;
481489
}
490+
482491
return Ret;
483492
}
484493
return Ret;
485494
}
486495

496+
497+
/* addArrayAnnotiations
498+
* This function takes all the stacked annotations for constant arrays
499+
* and pops them onto the EndStrs, this ensures the right order of annotations
500+
* */
501+
void PointerVariableConstraint::addArrayAnnotations(
502+
std::stack<std::string> &CheckedArrs,
503+
std::deque<std::string> &EndStrs) {
504+
while(!CheckedArrs.empty()) {
505+
auto NextStr = CheckedArrs.top();
506+
CheckedArrs.pop();
507+
EndStrs.push_front(NextStr);
508+
}
509+
assert(CheckedArrs.empty());
510+
}
511+
487512
// Mesh resolved constraints with the PointerVariableConstraints set of
488513
// variables and potentially nested function pointer declaration. Produces a
489514
// string that can be replaced in the source code.
@@ -493,12 +518,25 @@ PointerVariableConstraint::mkString(EnvironmentMap &E,
493518
bool ForItype,
494519
bool EmitPointee) {
495520
std::ostringstream Ss;
496-
std::ostringstream Pss;
497-
unsigned CaratsToAdd = 0;
521+
// This deque will store all the type strings that need to pushed
522+
// to the end of the type string. This is typically things like
523+
// closing delimiters.
524+
std::deque<std::string> EndStrs;
525+
// This will store stacked array decls to ensure correct order
526+
// We encounter constant arrays variables in the reverse order they
527+
// need to appear in, so the LIFO structure reverses these annotations
528+
std::stack<std::string> CheckedArrs;
529+
// Have we emitted the string for the base type
498530
bool EmittedBase = false;
531+
// Have we emitted the name of the variable yet?
499532
bool EmittedName = false;
500-
bool EmittedCheckedAnnotation = false;
501-
if (EmitName == false && hasItype() == false)
533+
// Was the last variable an Array?
534+
bool PrevArr = false;
535+
// Is the entire type so far an array?
536+
bool AllArrays = true;
537+
// Are we in a sequence of arrays
538+
bool ArrayRun = false;
539+
if ((EmitName == false && hasItype() == false) || getName() == RETVAR)
502540
EmittedName = true;
503541
uint32_t TypeIdx = 0;
504542

@@ -527,17 +565,28 @@ PointerVariableConstraint::mkString(EnvironmentMap &E,
527565
if (!ForItype && BaseType == "void")
528566
K = Atom::A_Wild;
529567

568+
if (PrevArr && K != Atom::A_Arr && !EmittedName) {
569+
EmittedName = true;
570+
addArrayAnnotations(CheckedArrs, EndStrs);
571+
EndStrs.push_front(" " + getName());
572+
}
573+
PrevArr = ((K == Atom::A_Arr || K == Atom::A_NTArr)
574+
&& ArrPresent
575+
&& arrSizes[TypeIdx].first == O_SizedArray);
576+
530577
switch (K) {
531578
case Atom::A_Ptr:
532579
getQualString(TypeIdx, Ss);
533580

534581
// We need to check and see if this level of variable
535582
// is constrained by a bounds safe interface. If it is,
536583
// then we shouldn't re-write it.
584+
AllArrays = false;
537585
if (hasItype() == false) {
538586
EmittedBase = false;
539587
Ss << "_Ptr<";
540-
CaratsToAdd++;
588+
ArrayRun = false;
589+
EndStrs.push_front(">");
541590
break;
542591
}
543592
LLVM_FALLTHROUGH;
@@ -548,23 +597,21 @@ PointerVariableConstraint::mkString(EnvironmentMap &E,
548597
// be [] instead of *, IF, the original type was an array.
549598
// And, if the original type was a sized array of size K.
550599
// we should substitute [K].
551-
if (emitArraySize(Pss, TypeIdx, EmittedName,
552-
EmittedCheckedAnnotation, false))
600+
if (emitArraySize(CheckedArrs, TypeIdx, AllArrays, ArrayRun, false))
553601
break;
554602
// We need to check and see if this level of variable
555603
// is constrained by a bounds safe interface. If it is,
556604
// then we shouldn't re-write it.
557605
if (hasItype() == false) {
558606
EmittedBase = false;
559607
Ss << "_Array_ptr<";
560-
CaratsToAdd++;
608+
EndStrs.push_front(">");
561609
break;
562610
}
563611
LLVM_FALLTHROUGH;
564612
case Atom::A_NTArr:
565613

566-
if (emitArraySize(Pss, TypeIdx, EmittedName,
567-
EmittedCheckedAnnotation, true))
614+
if (emitArraySize(CheckedArrs, TypeIdx, AllArrays, ArrayRun, true))
568615
break;
569616
// This additional check is to prevent fall-through from the array.
570617
if (K == Atom::A_NTArr) {
@@ -577,14 +624,18 @@ PointerVariableConstraint::mkString(EnvironmentMap &E,
577624
if (hasItype() == false) {
578625
EmittedBase = false;
579626
Ss << "_Nt_array_ptr<";
580-
CaratsToAdd++;
627+
EndStrs.push_front(">");
581628
break;
582629
}
583630
}
584631
LLVM_FALLTHROUGH;
585632
// If there is no array in the original program, then we fall through to
586633
// the case where we write a pointer value.
587634
case Atom::A_Wild:
635+
AllArrays = false;
636+
if (ArrayRun)
637+
addArrayAnnotations(CheckedArrs, EndStrs);
638+
ArrayRun = false;
588639
if (EmittedBase) {
589640
Ss << "*";
590641
} else {
@@ -607,6 +658,22 @@ PointerVariableConstraint::mkString(EnvironmentMap &E,
607658
TypeIdx++;
608659
}
609660

661+
// If the previous variable was an array or
662+
// if we are leaving an array run, we need to emit the
663+
// annotation for a stack-array
664+
if ((PrevArr || ArrayRun) && !CheckedArrs.empty())
665+
addArrayAnnotations(CheckedArrs, EndStrs);
666+
667+
// If the whole type is an array so far, and we haven't emitted
668+
// a name yet, then emit the name so that it appears before
669+
// the the stack array type.
670+
if (PrevArr && !EmittedName && AllArrays) {
671+
EmittedName = true;
672+
EndStrs.push_front(" " + getName());
673+
}
674+
675+
676+
610677
if (EmittedBase == false) {
611678
// If we have a FV pointer, then our "base" type is a function pointer.
612679
// type.
@@ -617,25 +684,24 @@ PointerVariableConstraint::mkString(EnvironmentMap &E,
617684
}
618685
}
619686

620-
// Push carats onto the end of the string.
621-
for (unsigned i = 0; i < CaratsToAdd; i++) {
622-
Ss << ">";
687+
// Add closing elements to type
688+
for (std::string Str : EndStrs) {
689+
Ss << Str;
623690
}
624691

625692
// No space after itype.
626-
if (!ForItype)
627-
Ss << " ";
693+
if (!EmittedName)
694+
Ss << " " << getName();
628695

629-
std::string FinalDec;
630-
if (EmittedName == false) {
631-
if (getName() != RETVAR)
632-
Ss << getName();
633-
FinalDec = Ss.str();
634-
} else {
635-
FinalDec = Ss.str() + Pss.str();
636-
}
696+
// Final array dropping
697+
if(!CheckedArrs.empty())
698+
addArrayAnnotations(CheckedArrs, EndStrs);
699+
700+
//TODO remove comparison to RETVAR
701+
if (getName() == RETVAR && !ForItype)
702+
Ss << " ";
637703

638-
return FinalDec;
704+
return Ss.str();
639705
}
640706

641707
bool PVConstraint::addArgumentConstraint(ConstraintVariable *DstCons,

clang/lib/CConv/DeclRewriter.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,7 @@ void DeclRewriter::rewriteMultiDecl(DeclReplacementTempl<DT, DK> *N,
198198
if (VD->hasInit()) {
199199
SourceLocation EqLoc = VD->getInitializerStartLoc();
200200
TR.setEnd(EqLoc);
201-
SRewrite = SRewrite + " = ";
201+
SRewrite = SRewrite + " =";
202202
} else {
203203
// There is no initializer, lets add it.
204204
if (isPointerType(VD) &&
@@ -527,7 +527,7 @@ bool FunctionDeclBuilder::VisitFunctionDecl(FunctionDecl *FD) {
527527
} else {
528528
// One of the argument is WILD, emit an itype.
529529
std::string Itype =
530-
Defn->mkString(Info.getConstraints().getVariables(), true, true);
530+
Defn->mkString(Info.getConstraints().getVariables(), false, true);
531531
ReturnVar = Defn->getRewritableOriginalTy();
532532
ItypeStr = " : itype(" + Itype + ")";
533533
}

clang/test/CheckedCRewriter/alloc_type_param.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,11 @@ void foo() {
2222
/* Explicit casts work fine also */
2323

2424
int *d = (int*) malloc(sizeof(int));
25-
//CHECK: _Ptr<int> d = (_Ptr<int> ) malloc<int>(sizeof(int));
25+
//CHECK: _Ptr<int> d = (_Ptr<int>) malloc<int>(sizeof(int));
2626
int *e = (int*) calloc(1, sizeof(int));
27-
//CHECK: _Ptr<int> e = (_Ptr<int> ) calloc<int>(1, sizeof(int));
27+
//CHECK: _Ptr<int> e = (_Ptr<int>) calloc<int>(1, sizeof(int));
2828
int *f = (int*) realloc(d, sizeof(int));
29-
//CHECK: _Ptr<int> f = (_Ptr<int> ) realloc<int>(d, sizeof(int));
29+
//CHECK: _Ptr<int> f = (_Ptr<int>) realloc<int>(d, sizeof(int));
3030
}
3131

3232
/* Allocating pointers to pointers */

clang/test/CheckedCRewriter/allocator.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ void foo(void) {
2828
return;
2929
}
3030
//CHECK: void foo(void) {
31-
//CHECK-NEXT: _Ptr<int> a = (_Ptr<int> ) malloc<int>(sizeof(int));
31+
//CHECK-NEXT: _Ptr<int> a = (_Ptr<int>) malloc<int>(sizeof(int));
3232

3333
typedef struct _listelt {
3434
struct _listelt *next;
@@ -51,4 +51,4 @@ void add_some_stuff(listhead *hd) {
5151
return;
5252
}
5353
//CHECK: void add_some_stuff(_Ptr<listhead> hd) {
54-
//CHECK-NEXT: _Ptr<listelt> l1 = (_Ptr<listelt> ) malloc<listelt>(sizeof(listelt));
54+
//CHECK-NEXT: _Ptr<listelt> l1 = (_Ptr<listelt>) malloc<listelt>(sizeof(listelt));

clang/test/CheckedCRewriter/b10_allsafepointerstruct.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ struct p *foo() {
5454
x->y = &ex2;
5555
y->y = &ex1;
5656
struct p *z = (struct p *) sus(x, y);
57-
//CHECK: _Ptr<struct p> z = (_Ptr<struct p> ) sus(x, y);
57+
//CHECK: _Ptr<struct p> z = (_Ptr<struct p>) sus(x, y);
5858
return z;
5959
}
6060

@@ -70,6 +70,6 @@ struct p *bar() {
7070
x->y = &ex2;
7171
y->y = &ex1;
7272
struct p *z = (struct p *) sus(x, y);
73-
//CHECK: _Ptr<struct p> z = (_Ptr<struct p> ) sus(x, y);
73+
//CHECK: _Ptr<struct p> z = (_Ptr<struct p>) sus(x, y);
7474
return z;
75-
}
75+
}

clang/test/CheckedCRewriter/b16_callerpointerstruct.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ struct p *foo() {
5757
x->y = &ex2;
5858
y->y = &ex1;
5959
struct p *z = (struct p *) sus(x, y);
60-
//CHECK_NOALL: _Ptr<struct p> z = (_Ptr<struct p> ) sus(x, y);
60+
//CHECK_NOALL: _Ptr<struct p> z = (_Ptr<struct p>) sus(x, y);
6161
//CHECK_ALL: struct p *z = (struct p *) sus(x, y);
6262
return z;
6363
}
@@ -77,4 +77,4 @@ struct p *bar() {
7777
//CHECK: struct p *z = (struct p *) sus(x, y);
7878
z += 2;
7979
return z;
80-
}
80+
}

0 commit comments

Comments
 (0)