diff --git a/clang/include/clang/CConv/ConstraintVariables.h b/clang/include/clang/CConv/ConstraintVariables.h index d3be60ccdaee..23fde5a28d4c 100644 --- a/clang/include/clang/CConv/ConstraintVariables.h +++ b/clang/include/clang/CConv/ConstraintVariables.h @@ -297,6 +297,8 @@ class PointerVariableConstraint : public ConstraintVariable { bool getArrPresent() const { return ArrPresent; } // Check if the outermost pointer is an unsized array. bool isTopCvarUnsizedArr() const; + // Check if any of the pointers is either a sized or unsized arr. + bool hasSomeSizedArr() const; // Is an itype present for this constraint? If yes, // what is the text of that itype? diff --git a/clang/lib/CConv/AVarBoundsInfo.cpp b/clang/lib/CConv/AVarBoundsInfo.cpp index 2aa18423968e..8a1d7e8e817c 100644 --- a/clang/lib/CConv/AVarBoundsInfo.cpp +++ b/clang/lib/CConv/AVarBoundsInfo.cpp @@ -692,15 +692,14 @@ bool AvarBoundsInference::inferPossibleBounds(BoundsKey K, ABounds *SB, auto *SBVar = BI->getProgramVar(SBKey); if (SBVar->IsNumConstant()) { PotentialB.insert(SBVar); - } else { - // Find all the in scope variables reachable from the current - // bounds variable. - ScopeVisitor TV(Kvar->getScope(), PotentialB, BI->PVarInfo, - BI->PointerBoundsKey); - BKGraph.visitBreadthFirst(SBKey, [&TV](BoundsKey BK) { - TV.visitBoundsKey(BK); - }); } + // Find all the in scope variables reachable from the current + // bounds variable. + ScopeVisitor TV(Kvar->getScope(), PotentialB, BI->PVarInfo, + BI->PointerBoundsKey); + BKGraph.visitBreadthFirst(SBKey, [&TV](BoundsKey BK) { + TV.visitBoundsKey(BK); + }); if (*Kvar->getScope() == *SBVar->getScope()) { PotentialB.insert(SBVar); diff --git a/clang/lib/CConv/ConstraintVariables.cpp b/clang/lib/CConv/ConstraintVariables.cpp index 9210c399e746..437ada21d802 100644 --- a/clang/lib/CConv/ConstraintVariables.cpp +++ b/clang/lib/CConv/ConstraintVariables.cpp @@ -151,8 +151,9 @@ PointerVariableConstraint::PointerVariableConstraint(const QualType &QT, ArrPresent = false; bool IsDeclTy = false; + + auto &ABInfo = I.getABoundsInfo(); if (D != nullptr) { - auto &ABInfo = I.getABoundsInfo(); if (ABInfo.tryGetVariable(D, BKey)) { ValidBoundsKey = true; } @@ -210,6 +211,7 @@ PointerVariableConstraint::PointerVariableConstraint(const QualType &QT, bool VarCreated = false; bool IsArr = false; bool IsIncompleteArr = false; + bool IsTopMost = true; OriginallyChecked = false; uint32_t TypeIdx = 0; std::string Npre = inFunc ? ((*inFunc)+":") : ""; @@ -268,7 +270,14 @@ PointerVariableConstraint::PointerVariableConstraint(const QualType &QT, // See if there is a constant size to this array type at this position. if (const ConstantArrayType *CAT = dyn_cast(Ty)) { arrSizes[TypeIdx] = std::pair( - O_SizedArray,CAT->getSize().getZExtValue()); + O_SizedArray, CAT->getSize().getZExtValue()); + + // If this is the top-most pointer variable? + if (hasBoundsKey() && IsTopMost) { + BoundsKey CBKey = ABInfo.getConstKey(CAT->getSize().getZExtValue()); + ABounds *NB = new CountBound(CBKey); + ABInfo.insertDeclaredBounds(D, NB); + } } else { arrSizes[TypeIdx] = std::pair( O_UnSizedArray,0); @@ -316,6 +325,7 @@ PointerVariableConstraint::PointerVariableConstraint(const QualType &QT, TypeIdx++; Npre = Npre + "*"; VK = VarAtom::V_Other; // only the outermost pointer considered a param/return + IsTopMost = false; } insertQualType(TypeIdx, QTy); @@ -1148,6 +1158,16 @@ bool PointerVariableConstraint::isTopCvarUnsizedArr() const { return true; } +bool PointerVariableConstraint::hasSomeSizedArr() const { + for (auto &AS : arrSizes) { + if (AS.second.first == O_SizedArray || + AS.second.second == O_UnSizedArray) { + return true; + } + } + return false; +} + bool PointerVariableConstraint:: solutionEqualTo(Constraints &CS, const ConstraintVariable *CV) const { bool Ret = false; diff --git a/clang/lib/CConv/RewriteUtils.cpp b/clang/lib/CConv/RewriteUtils.cpp index 35698eae51a2..5dc6cc801361 100644 --- a/clang/lib/CConv/RewriteUtils.cpp +++ b/clang/lib/CConv/RewriteUtils.cpp @@ -342,7 +342,7 @@ std::string ArrayBoundsRewriter::getBoundsString(PVConstraint *PV, // For itype we do not want to add a second ":". std::string Pfix = Isitype ? " " : " : "; - if (ValidBKey) { + if (ValidBKey && !PV->hasSomeSizedArr()) { ABounds *ArrB = ABInfo.getBounds(DK); // Only we we have bounds and no pointer arithmetic on the variable. if (ArrB != nullptr && !ABInfo.hasPointerArithmetic(DK)) { diff --git a/clang/test/CheckedCRewriter/basic_checks.c b/clang/test/CheckedCRewriter/basic_checks.c index 10bd98b5a9e4..4b5e2453b668 100644 --- a/clang/test/CheckedCRewriter/basic_checks.c +++ b/clang/test/CheckedCRewriter/basic_checks.c @@ -27,7 +27,7 @@ void typd_driver(void) { //CHECK_ALL: wchar_t buf _Checked[10]; //CHECK_ALL: _Ptr a = &buf[0]; -//CHECK_ALL: _Array_ptr b = &buf[0]; +//CHECK_ALL: _Array_ptr b : count(10) = &buf[0]; typedef struct _A { diff --git a/clang/test/CheckedCRewriter/simple_locals.c b/clang/test/CheckedCRewriter/simple_locals.c index 20c1699129f2..73694541993d 100644 --- a/clang/test/CheckedCRewriter/simple_locals.c +++ b/clang/test/CheckedCRewriter/simple_locals.c @@ -151,7 +151,7 @@ void pullit(char *base, char *out, int *index) { return; } -//CHECK_ALL: void pullit(_Array_ptr base, _Ptr out, _Ptr index) _Checked { +//CHECK_ALL: void pullit(_Array_ptr base : count(10), _Ptr out, _Ptr index) _Checked { //CHECK_NOALL: void pullit(char *base, _Ptr out, _Ptr index) { void driver() {