Skip to content

Commit 7162656

Browse files
authored
Refactor to include generic types info in VCs (#372)
* upgrade IsGeneric to GenericIndex * don't deref null * refactor to use cached indexes * allow get constraint from decl * add generic indexes to constructed PVCs * force generic indexes earlier * merge GenericIndex * set typeparam count in fvcs
1 parent 198fcca commit 7162656

10 files changed

+118
-86
lines changed

clang/include/clang/3C/ConstraintVariables.h

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -268,11 +268,11 @@ class PointerVariableConstraint : public ConstraintVariable {
268268
// String representing declared bounds expression.
269269
std::string BoundsAnnotationStr;
270270

271-
// Does this variable represent a generic type?
271+
// Does this variable represent a generic type? Which one (or -1 for none)?
272272
// Generic types can be used with fewer restrictions, so this field is used
273-
// stop assignments wth generic variables from forcing constraint variables
273+
// stop assignments with generic variables from forcing constraint variables
274274
// to be wild.
275-
bool IsGeneric;
275+
int GenericIndex;
276276

277277
// Empty array pointers are represented the same as standard pointers. This
278278
// lets pointers be passed to functions expecting a zero width array. This
@@ -296,11 +296,11 @@ class PointerVariableConstraint : public ConstraintVariable {
296296
// Constructor for when we know a CVars and a type string.
297297
PointerVariableConstraint(CAtoms V, std::string T, std::string Name,
298298
FunctionVariableConstraint *F, bool IsArr,
299-
bool IsItype, std::string Is, bool Generic = false)
299+
bool IsItype, std::string Is, int Generic = -1)
300300
: ConstraintVariable(PointerVariable, "" /*not used*/, Name), BaseType(T),
301301
Vars(V), FV(F), ArrPresent(IsArr), ItypeStr(Is),
302302
PartOfFuncPrototype(false), Parent(nullptr), BoundsAnnotationStr(""),
303-
IsGeneric(Generic), IsZeroWidthArray(false) {}
303+
GenericIndex(Generic), IsZeroWidthArray(false) {}
304304

305305
std::string getTy() const { return BaseType; }
306306
bool getArrPresent() const { return ArrPresent; }
@@ -321,7 +321,8 @@ class PointerVariableConstraint : public ConstraintVariable {
321321
// Get bounds annotation.
322322
std::string getBoundsStr() const { return BoundsAnnotationStr; }
323323

324-
bool getIsGeneric() const { return IsGeneric; }
324+
bool getIsGeneric() const { return GenericIndex >= 0; }
325+
int getGenericIndex() const { return GenericIndex; }
325326

326327
bool getIsOriginallyChecked() const override {
327328
return llvm::any_of(Vars, [](Atom *A) { return isa<ConstAtom>(A); });
@@ -348,14 +349,14 @@ class PointerVariableConstraint : public ConstraintVariable {
348349
// that all constructor calls will take the same global objects here.
349350
// inFunc: If this variable is part of a function prototype, this string is
350351
// the name of the function. nullptr otherwise.
351-
// IsGeneric: CheckedC supports generic types (_Itype_for_any) which need less
352-
// restrictive constraints. Set to true to indicate that this
353-
// variable is generic.
352+
// ForceGenericIndex: CheckedC supports generic types (_Itype_for_any) which
353+
// need less restrictive constraints. Set >= 0 to indicate
354+
// that this variable should be considered generic.
354355
PointerVariableConstraint(const clang::QualType &QT, clang::DeclaratorDecl *D,
355356
std::string N, ProgramInfo &I,
356357
const clang::ASTContext &C,
357358
std::string *InFunc = nullptr,
358-
bool IsGeneric = false);
359+
int ForceGenericIndex = -1);
359360

360361
const CAtoms &getCvars() const { return Vars; }
361362

@@ -437,6 +438,9 @@ class FunctionVariableConstraint : public ConstraintVariable {
437438
// Flag to indicate whether this is a function pointer or not.
438439
bool IsFunctionPtr;
439440

441+
// Count of type parameters from `_Itype_for_any(...)`
442+
int TypeParams;
443+
440444
void equateFVConstraintVars(ConstraintVariable *CV, ProgramInfo &Info) const;
441445

442446
public:
@@ -479,6 +483,9 @@ class FunctionVariableConstraint : public ConstraintVariable {
479483
}
480484

481485
bool hasItype() const override;
486+
487+
int getGenericIndex() const { return ReturnVar->getGenericIndex(); }
488+
482489
bool solutionEqualTo(Constraints &CS,
483490
const ConstraintVariable *CV) const override;
484491

clang/include/clang/3C/TypeVariableAnalysis.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,6 @@ class TypeVarVisitor : public RecursiveASTVisitor<TypeVarVisitor>,
9393
ConstraintResolver CR;
9494
TypeVariableMapT TVMap;
9595

96-
void insertBinding(CallExpr *CE, const TypeVariableType *TyV, QualType Ty,
97-
CVarSet &CVs);
96+
void insertBinding(CallExpr *CE, const int TyIdx, QualType Ty, CVarSet &CVs);
9897
};
9998
#endif

clang/include/clang/3C/Utils.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -164,8 +164,6 @@ std::string getSourceText(const clang::SourceRange &SR,
164164
unsigned longestCommonSubsequence(const char *Str1, const char *Str2,
165165
unsigned long Str1Len, unsigned long Str2Len);
166166

167-
const clang::TypeVariableType *getTypeVariableType(clang::DeclaratorDecl *Decl);
168-
169167
bool isTypeAnonymous(const clang::Type *T);
170168

171169
// Find the index of parameter PV in the parameter list of function FD.

clang/lib/3C/CastPlacement.cpp

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,15 +35,14 @@ bool CastPlacementVisitor::VisitCallExpr(CallExpr *CE) {
3535
TypeVars = Info.getTypeParamBindings(CE, Context);
3636
unsigned PIdx = 0;
3737
for (const auto &A : CE->arguments()) {
38-
if (PIdx < FD->getNumParams()) {
38+
if (PIdx < FV->numParams()) {
3939
// Avoid adding incorrect casts to generic function arguments by
4040
// removing implicit casts when on arguments with a consistently
4141
// used generic type.
4242
Expr *ArgExpr = A;
43-
const TypeVariableType *TyVar =
44-
getTypeVariableType(FD->getParamDecl(PIdx));
45-
if (TyVar && TypeVars.find(TyVar->GetIndex()) != TypeVars.end() &&
46-
TypeVars[TyVar->GetIndex()] != nullptr)
43+
const int TyVarIdx = FV->getParamVar(PIdx)->getGenericIndex();
44+
if (TypeVars.find(TyVarIdx) != TypeVars.end() &&
45+
TypeVars[TyVarIdx] != nullptr)
4746
ArgExpr = ArgExpr->IgnoreImpCasts();
4847

4948
CVarSet ArgumentConstraints = CR.getExprConstraintVars(ArgExpr);

clang/lib/3C/ConstraintBuilder.cpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -266,12 +266,11 @@ class FunctionVisitor : public RecursiveASTVisitor<FunctionVisitor> {
266266
std::vector<CVarSet> Deferred;
267267
for (const auto &A : E->arguments()) {
268268
CVarSet ArgumentConstraints;
269-
if (TFD != nullptr && I < TFD->getNumParams()) {
269+
if (I < TargetFV->numParams()) {
270270
// Remove casts to void* on polymorphic types that are used
271271
// consistently.
272-
const auto *Ty = getTypeVariableType(TFD->getParamDecl(I));
273-
if (Ty != nullptr && ConsistentTypeParams.find(Ty->GetIndex()) !=
274-
ConsistentTypeParams.end())
272+
const int TyIdx = TargetFV->getParamVar(I)->getGenericIndex();
273+
if (ConsistentTypeParams.find(TyIdx) != ConsistentTypeParams.end())
275274
ArgumentConstraints =
276275
CB.getExprConstraintVars(A->IgnoreImpCasts());
277276
else

clang/lib/3C/ConstraintResolver.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -448,7 +448,7 @@ CVarSet ConstraintResolver::getExprConstraintVars(Expr *E) {
448448
N = "&" + N;
449449
ExprType = Context->getPointerType(ArgTy);
450450
PVConstraint *PVC = new PVConstraint(ExprType, nullptr, N, Info,
451-
*Context, nullptr, true);
451+
*Context, nullptr, 0);
452452
PVC->constrainOuterTo(CS, A, true);
453453
ReturnCVs.insert(PVC);
454454
DidInsert = true;
@@ -504,9 +504,10 @@ CVarSet ConstraintResolver::getExprConstraintVars(Expr *E) {
504504
// had a checked type in the input program because the constraint
505505
// variables contain constant atoms that are reused by the copy
506506
// constructor.
507-
NewCV =
507+
auto *NewPCV =
508508
new PVConstraint(CE->getType(), nullptr, PCV->getName(), Info,
509-
*Context, nullptr, PCV->getIsGeneric());
509+
*Context, nullptr, PCV->getGenericIndex());
510+
NewCV = NewPCV;
510511
if (PCV->hasBoundsKey())
511512
NewCV->setBoundsKey(PCV->getBoundsKey());
512513
} else {

clang/lib/3C/ConstraintVariables.cpp

Lines changed: 37 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ PointerVariableConstraint::PointerVariableConstraint(
107107
this->FV = dyn_cast<FVConstraint>(Ot->FV->getCopy(CS));
108108
}
109109
this->Parent = Ot;
110-
this->IsGeneric = Ot->IsGeneric;
110+
this->GenericIndex = Ot->GenericIndex;
111111
this->IsZeroWidthArray = Ot->IsZeroWidthArray;
112112
// We need not initialize other members.
113113
}
@@ -169,11 +169,10 @@ class TypedefLevelFinder : public RecursiveASTVisitor<TypedefLevelFinder> {
169169

170170
PointerVariableConstraint::PointerVariableConstraint(
171171
const QualType &QT, DeclaratorDecl *D, std::string N, ProgramInfo &I,
172-
const ASTContext &C, std::string *InFunc, bool Generic)
172+
const ASTContext &C, std::string *InFunc, int ForceGenericIndex)
173173
: ConstraintVariable(ConstraintVariable::PointerVariable,
174174
tyToStr(QT.getTypePtr()), N),
175-
FV(nullptr), PartOfFuncPrototype(InFunc != nullptr), Parent(nullptr),
176-
IsGeneric(Generic) {
175+
FV(nullptr), PartOfFuncPrototype(InFunc != nullptr), Parent(nullptr) {
177176
QualType QTy = QT;
178177
const Type *Ty = QTy.getTypePtr();
179178
auto &CS = I.getConstraints();
@@ -252,11 +251,28 @@ PointerVariableConstraint::PointerVariableConstraint(
252251
}
253252
}
254253

255-
// At this point `QTy` holds the computed type (and `QT` still holds the
254+
// At this point `QTy`/`Ty` hold the computed type (and `QT` still holds the
256255
// input type). It will be consumed to create atoms, so any code that needs
257256
// to be coordinated with the atoms should access it here first.
257+
258258
typedeflevelinfo = TypedefLevelFinder::find(QTy);
259259

260+
if (ForceGenericIndex >= 0) {
261+
GenericIndex = ForceGenericIndex;
262+
} else {
263+
GenericIndex = -1;
264+
// This makes a lot of assumptions about how the AST will look, and limits
265+
// it to one level.
266+
// TODO: Enhance TypedefLevelFinder to get this info
267+
if (Ty->isPointerType()) {
268+
auto *PtrTy = Ty->getPointeeType().getTypePtr();
269+
if (auto *TypdefTy = dyn_cast_or_null<TypedefType>(PtrTy)) {
270+
const auto *Tv = dyn_cast<TypeVariableType>(TypdefTy->desugar());
271+
if (Tv) GenericIndex = Tv->GetIndex();
272+
}
273+
}
274+
}
275+
260276
bool VarCreated = false;
261277
bool IsArr = false;
262278
bool IsIncompleteArr = false;
@@ -407,7 +423,7 @@ PointerVariableConstraint::PointerVariableConstraint(
407423
// Get a string representing the type without pointer and array indirection.
408424
BaseType = extractBaseType(D, QT, Ty, C);
409425

410-
bool IsWild = !IsGeneric && (isVarArgType(BaseType) || isTypeHasVoid(QT));
426+
bool IsWild = !getIsGeneric() && (isVarArgType(BaseType) || isTypeHasVoid(QT));
411427
if (IsWild) {
412428
std::string Rsn =
413429
isTypeHasVoid(QT) ? "Default void* type" : "Default Var arg list type";
@@ -879,6 +895,7 @@ FunctionVariableConstraint::FunctionVariableConstraint(const Type *Ty,
879895
FileName = "";
880896
HasEqArgumentConstraints = false;
881897
IsFunctionPtr = true;
898+
TypeParams = 0;
882899

883900
// Metadata about function
884901
FunctionDecl *FD = nullptr;
@@ -925,10 +942,11 @@ FunctionVariableConstraint::FunctionVariableConstraint(const Type *Ty,
925942
PName = PVD->getName();
926943
}
927944
}
928-
bool IsGeneric =
929-
ParmVD != nullptr && getTypeVariableType(ParmVD) != nullptr;
930-
ParamVars.push_back(
931-
new PVConstraint(QT, ParmVD, PName, I, Ctx, &N, IsGeneric));
945+
auto *ParamVar = new PVConstraint(QT, ParmVD, PName, I, Ctx, &N);
946+
int GenericIdx = ParamVar->getGenericIndex();
947+
if (GenericIdx >= 0)
948+
TypeParams = std::max(TypeParams, GenericIdx + 1);
949+
ParamVars.push_back(ParamVar);
932950
}
933951

934952
Hasproto = true;
@@ -941,8 +959,11 @@ FunctionVariableConstraint::FunctionVariableConstraint(const Type *Ty,
941959
}
942960

943961
// ConstraintVariable for the return
944-
bool IsGeneric = FD != nullptr && getTypeVariableType(FD) != nullptr;
945-
ReturnVar = new PVConstraint(RT, D, RETVAR, I, Ctx, &N, IsGeneric);
962+
auto *ReturnVC = new PVConstraint(RT, D, RETVAR, I, Ctx, &N);
963+
int GenericIdx = ReturnVC->getGenericIndex();
964+
if (GenericIdx >= 0)
965+
TypeParams = std::max(TypeParams, GenericIdx + 1);
966+
ReturnVar = ReturnVC;
946967
}
947968

948969
void FunctionVariableConstraint::constrainToWild(Constraints &CS,
@@ -1214,7 +1235,7 @@ bool PointerVariableConstraint::solutionEqualTo(
12141235
if (CV != nullptr) {
12151236
if (const auto *PV = dyn_cast<PVConstraint>(CV)) {
12161237
auto &OthCVars = PV->Vars;
1217-
if (IsGeneric || PV->IsGeneric || Vars.size() == OthCVars.size()) {
1238+
if (getIsGeneric() || PV->getIsGeneric() || Vars.size() == OthCVars.size()) {
12181239
Ret = true;
12191240

12201241
auto I = Vars.begin();
@@ -1683,6 +1704,8 @@ void PointerVariableConstraint::mergeDeclaration(ConstraintVariable *FromCV,
16831704
Vars = NewVatoms;
16841705
if (!From->ItypeStr.empty())
16851706
ItypeStr = From->ItypeStr;
1707+
if (From->GenericIndex >= 0)
1708+
GenericIndex = From->GenericIndex;
16861709
if (FV) {
16871710
assert(From->FV);
16881711
FV->mergeDeclaration(From->FV, Info, ReasonFailed);
@@ -1694,7 +1717,7 @@ Atom *PointerVariableConstraint::getAtom(unsigned AtomIdx, Constraints &CS) {
16941717
// If index is in bounds, just return the atom.
16951718
return Vars[AtomIdx];
16961719
}
1697-
if (IsGeneric && AtomIdx == Vars.size()) {
1720+
if (getIsGeneric() && AtomIdx == Vars.size()) {
16981721
// Polymorphic types don't know how "deep" their pointers are beforehand so,
16991722
// we need to create new atoms for new pointer levels on the fly.
17001723
std::string Stars(Vars.size(), '*');

clang/lib/3C/ProgramInfo.cpp

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -496,21 +496,25 @@ bool ProgramInfo::insertNewFVConstraint(FunctionDecl *FD, FVConstraint *FVCon,
496496
void ProgramInfo::specialCaseVarIntros(ValueDecl *D, ASTContext *Context) {
497497
// Special-case for va_list, constrain to wild.
498498
bool IsGeneric = false;
499-
if (auto *PVD = dyn_cast<ParmVarDecl>(D))
500-
IsGeneric = getTypeVariableType(PVD) != nullptr;
499+
PVConstraint *PVC = nullptr;
500+
501+
CVarOption CVOpt = getVariable(D, Context);
502+
if (CVOpt.hasValue()) {
503+
ConstraintVariable &CV = CVOpt.getValue();
504+
PVC = dyn_cast<PVConstraint>(&CV);
505+
}
506+
507+
if (isa<ParmVarDecl>(D))
508+
IsGeneric = PVC && PVC->getIsGeneric();
501509
if (isVarArgType(D->getType().getAsString()) ||
502510
(hasVoidType(D) && !IsGeneric)) {
503511
// set the reason for making this variable WILD.
504512
std::string Rsn = "Variable type void.";
505513
PersistentSourceLoc PL = PersistentSourceLoc::mkPSL(D, *Context);
506514
if (!D->getType()->isVoidType())
507515
Rsn = "Variable type is va_list.";
508-
CVarOption CVOpt = getVariable(D, Context);
509-
if (CVOpt.hasValue()) {
510-
ConstraintVariable &CV = CVOpt.getValue();
511-
if (PVConstraint *PVC = dyn_cast<PVConstraint>(&CV))
512-
PVC->constrainToWild(CS, Rsn, &PL);
513-
}
516+
if (PVC != nullptr)
517+
PVC->constrainToWild(CS, Rsn, &PL);
514518
}
515519
}
516520

0 commit comments

Comments
 (0)