Skip to content

Commit 2a0df40

Browse files
kyleheadleymattmccutchen-ccijohn-h-kastner
authored
Improve user feedback about conflicting constraints (#708)
Co-authored-by: Matt McCutchen (Correct Computation) <[email protected]> Co-authored-by: John Kastner <[email protected]>
1 parent d37e5ca commit 2a0df40

23 files changed

+593
-473
lines changed

clang/include/clang/3C/3CInteractiveData.h

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,18 +16,26 @@
1616
#include "clang/3C/ConstraintVariables.h"
1717
#include "clang/3C/PersistentSourceLoc.h"
1818

19-
// Source info and reason for each wild pointer.
20-
class WildPointerInferenceInfo {
19+
// Source info and reason
20+
class RootCauseDiagnostic {
2121
public:
22-
WildPointerInferenceInfo(std::string Reason, const PersistentSourceLoc PSL)
23-
: WildPtrReason(Reason), Location(PSL) {}
22+
RootCauseDiagnostic() = default;
23+
explicit RootCauseDiagnostic(ReasonLoc &Rsn) : Main(Rsn) {}
2424

25-
const std::string &getWildPtrReason() const { return WildPtrReason; }
26-
const PersistentSourceLoc &getLocation() const { return Location; }
25+
const std::string &getReason() { return Main.Reason; }
26+
void setReason(const std::string &Rsn) { Main.Reason = Rsn; }
27+
28+
const PersistentSourceLoc &getLocation() const { return Main.Location; }
29+
30+
void addReason(const ReasonLoc &Rsn) {
31+
Supplemental.push_back(Rsn);
32+
}
33+
34+
std::vector<ReasonLoc> &additionalNotes() { return Supplemental; }
2735

2836
private:
29-
std::string WildPtrReason = "";
30-
PersistentSourceLoc Location;
37+
ReasonLoc Main;
38+
std::vector<ReasonLoc> Supplemental;
3139
};
3240

3341
// Constraints information.
@@ -44,7 +52,7 @@ class ConstraintsInfo {
4452
void printRootCauseStats(raw_ostream &O, Constraints &CS);
4553
int getNumPtrsAffected(ConstraintKey CK);
4654

47-
std::map<ConstraintKey, WildPointerInferenceInfo> RootWildAtomsWithReason;
55+
std::map<ConstraintKey, RootCauseDiagnostic> RootWildAtomsWithReason;
4856
CVars AllWildAtoms;
4957
CVars InSrcWildAtoms;
5058
CVars TotalNonDirectWildAtoms;

clang/include/clang/3C/CheckedRegions.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,15 +81,15 @@ class CheckedRegionFinder
8181
bool containsUncheckedPtr(clang::QualType Qt);
8282
bool containsUncheckedPtrAcc(clang::QualType Qt, std::set<std::string> &Seen);
8383
bool isUncheckedStruct(clang::QualType Qt, std::set<std::string> &Seen);
84-
void emitCauseDiagnostic(PersistentSourceLoc *);
84+
void emitCauseDiagnostic(PersistentSourceLoc);
8585
bool isWild(CVarOption CVar);
8686

8787
clang::ASTContext *Context;
8888
clang::Rewriter &Writer;
8989
ProgramInfo &Info;
9090
std::set<llvm::FoldingSetNodeID> &Seen;
9191
std::map<llvm::FoldingSetNodeID, AnnotationNeeded> &Map;
92-
std::set<PersistentSourceLoc *> Emitted;
92+
std::set<PersistentSourceLoc> Emitted;
9393
bool EmitWarnings;
9494
};
9595

clang/include/clang/3C/ConstraintResolver.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,8 @@ class ConstraintResolver {
7171

7272
CVarSet getInvalidCastPVCons(CastExpr *E);
7373

74-
CVarSet addAtomAll(CVarSet CVS, ConstAtom *PtrTyp, Constraints &CS);
74+
CVarSet addAtomAll(CVarSet CVS, ConstAtom *PtrTyp,
75+
ReasonLoc &Rsn, Constraints &CS);
7576
CVarSet pvConstraintFromType(QualType TypE);
7677

7778
CSetBkeyPair getAllSubExprConstraintVars(std::vector<Expr *> &Exprs);

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

Lines changed: 41 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -142,10 +142,7 @@ class ConstraintVariable {
142142
virtual bool solutionEqualTo(Constraints &, const ConstraintVariable *,
143143
bool ComparePtyp = true) const = 0;
144144

145-
virtual void constrainToWild(Constraints &CS,
146-
const std::string &Rsn) const = 0;
147-
virtual void constrainToWild(Constraints &CS, const std::string &Rsn,
148-
PersistentSourceLoc *PL) const = 0;
145+
virtual void constrainToWild(Constraints &CS, const ReasonLoc &Rsn) const = 0;
149146

150147
// Return true if this variable was checked in the input. Checked variables
151148
// might solve to WILD, and unchecked variables might solve to checked. Use
@@ -177,7 +174,7 @@ class ConstraintVariable {
177174
virtual bool hasNtArr(const EnvironmentMap &E, int AIdx = -1) const = 0;
178175

179176
// Force use of equality constraints in function calls for this CV
180-
virtual void equateArgumentConstraints(ProgramInfo &I) = 0;
177+
virtual void equateArgumentConstraints(ProgramInfo &I, ReasonLoc &Rsn) = 0;
181178

182179
// Internally combine the constraints and other data from the first parameter
183180
// with this constraint variable. Used with redeclarations, especially of
@@ -208,17 +205,25 @@ class ConstraintVariable {
208205
// achieve that, we additionally constrain the internal variables to not
209206
// change.
210207
//
211-
// Some cases in which the itype must not change at all are indicated by
212-
// passing a reason for the "root cause of wildness" as ReasonUnchangeable.
213-
// Otherwise ReasonUnchangeable should be set to the empty string.
208+
// Some cases in which the itype needs to be constrained not change at all are
209+
// indicated by passing a non-default reason for the "root cause of wildness"
210+
// in ReasonUnchangeable. If the reason is DEFAULT_REASON, this is a sentinel
211+
// meaning that the caller is not requesting such a constraint. Other cases
212+
// that need the constraint are detected within equateWithItype itself, and
213+
// the appropriate reason is attached there.
214+
//
215+
// TODO: It looks like there may be some unusual cases in which
216+
// equateWithType generates constraints using the reason from
217+
// ReasonUnchangeable even if it is the DEFAULT_REASON sentinel. Rethink the
218+
// equateWithItype design to figure out what reason should actually be used or
219+
// if those constraints should be generated at all.
214220
virtual void equateWithItype(ProgramInfo &CS,
215-
const std::string &ReasonUnchangeable,
216-
PersistentSourceLoc *PSL) = 0;
221+
const ReasonLoc &ReasonUnchangeable) = 0;
217222

218223
// Copy this variable and replace all VarAtoms with fresh VarAtoms. Using
219224
// fresh atoms allows the new variable to solve to different types than the
220225
// original.
221-
virtual ConstraintVariable *getCopy(Constraints &CS) = 0;
226+
virtual ConstraintVariable *getCopy(ReasonLoc &Rsn, Constraints &CS) = 0;
222227

223228
virtual ~ConstraintVariable(){};
224229
};
@@ -230,15 +235,15 @@ enum ConsAction { Safe_to_Wild, Wild_to_Safe, Same_to_Same };
230235

231236
void constrainConsVarGeq(const std::set<ConstraintVariable *> &LHS,
232237
const std::set<ConstraintVariable *> &RHS,
233-
Constraints &CS, PersistentSourceLoc *PL,
238+
Constraints &CS, const ReasonLoc &Rsn,
234239
ConsAction CA, bool DoEqType, ProgramInfo *Info,
235240
bool HandleBoundsKey = true);
236241
void constrainConsVarGeq(ConstraintVariable *LHS, const CVarSet &RHS,
237-
Constraints &CS, PersistentSourceLoc *PL,
242+
Constraints &CS, const ReasonLoc &Rsn,
238243
ConsAction CA, bool DoEqType, ProgramInfo *Info,
239244
bool HandleBoundsKey = true);
240245
void constrainConsVarGeq(ConstraintVariable *LHS, ConstraintVariable *RHS,
241-
Constraints &CS, PersistentSourceLoc *PL,
246+
Constraints &CS, const ReasonLoc &Rsn,
242247
ConsAction CA, bool DoEqType, ProgramInfo *Info,
243248
bool HandleBoundsKey = true);
244249

@@ -276,8 +281,7 @@ class PointerVariableConstraint : public ConstraintVariable {
276281
// This causes problems if the variable is later used as a deeper
277282
// pointer type. See correctcomputation/checkedc-clang#673.
278283
static PointerVariableConstraint *
279-
getWildPVConstraint(Constraints &CS, const std::string &Rsn,
280-
PersistentSourceLoc *PSL = nullptr);
284+
getWildPVConstraint(Constraints &CS, const ReasonLoc &Rsn);
281285

282286
// Get constraint variables representing values that are not pointers. If a
283287
// meaningful name can be assigned to the value, the second method should be
@@ -292,7 +296,7 @@ class PointerVariableConstraint : public ConstraintVariable {
292296
// by the original constraint variable.
293297
static PointerVariableConstraint *
294298
addAtomPVConstraint(PointerVariableConstraint *PVC, ConstAtom *PtrTyp,
295-
Constraints &CS);
299+
ReasonLoc &Rsn, Constraints &CS);
296300

297301
// Return a new constraint variable representing the result of dereferencing
298302
// the input constraint variable. This is accomplished by first copying the
@@ -518,12 +522,11 @@ class PointerVariableConstraint : public ConstraintVariable {
518522
void dump() const override { print(llvm::errs()); }
519523
void dumpJson(llvm::raw_ostream &O) const override;
520524

521-
void constrainToWild(Constraints &CS, const std::string &Rsn) const override;
522-
void constrainToWild(Constraints &CS, const std::string &Rsn,
523-
PersistentSourceLoc *PL) const override;
524-
void constrainOuterTo(Constraints &CS, ConstAtom *C, bool DoLB = false,
525-
bool Soft = false);
525+
void constrainToWild(Constraints &CS, const ReasonLoc &Rsn) const override;
526+
void constrainOuterTo(Constraints &CS, ConstAtom *C, const ReasonLoc &Rsn,
527+
bool DoLB = false, bool Soft = false);
526528
void constrainIdxTo(Constraints &CS, ConstAtom *C, unsigned int Idx,
529+
const ReasonLoc &Rsn,
527530
bool DoLB = false, bool Soft = false);
528531
bool anyChanges(const EnvironmentMap &E) const override;
529532
bool anyArgumentIsWild(const EnvironmentMap &E);
@@ -535,15 +538,16 @@ class PointerVariableConstraint : public ConstraintVariable {
535538
bool isConstantArr() const;
536539
unsigned long getConstantArrSize() const;
537540

538-
void equateArgumentConstraints(ProgramInfo &I) override;
541+
void equateArgumentConstraints(ProgramInfo &I, ReasonLoc &Rsn) override;
539542

540543
bool isPartOfFunctionPrototype() const { return PartOfFuncPrototype; }
541544
// Add the provided constraint variable as an argument constraint.
542-
bool addArgumentConstraint(ConstraintVariable *DstCons, ProgramInfo &Info);
545+
bool addArgumentConstraint(ConstraintVariable *DstCons,
546+
ReasonLoc &Rsn, ProgramInfo &Info);
543547
// Get the set of constraint variables corresponding to the arguments.
544548
const std::set<ConstraintVariable *> &getArgumentConstraints() const;
545549

546-
PointerVariableConstraint *getCopy(Constraints &CS) override;
550+
PointerVariableConstraint *getCopy(ReasonLoc &Rsn, Constraints &CS) override;
547551

548552
// Retrieve the atom at the specified index. This function includes special
549553
// handling for generic constraint variables to create deeper pointers as
@@ -552,8 +556,8 @@ class PointerVariableConstraint : public ConstraintVariable {
552556

553557
~PointerVariableConstraint() override{};
554558

555-
void equateWithItype(ProgramInfo &CS, const std::string &ReasonUnchangeable,
556-
PersistentSourceLoc *PSL) override;
559+
void equateWithItype(ProgramInfo &CS,
560+
const ReasonLoc &ReasonUnchangeable) override;
557561
};
558562

559563
typedef PointerVariableConstraint PVConstraint;
@@ -582,7 +586,7 @@ class FVComponentVariable {
582586
: InternalConstraint(nullptr), ExternalConstraint(nullptr),
583587
SourceDeclaration("") {}
584588

585-
FVComponentVariable(FVComponentVariable *Ot, Constraints &CS);
589+
FVComponentVariable(FVComponentVariable *Ot, ReasonLoc &Rsn, Constraints &CS);
586590

587591
FVComponentVariable(const clang::QualType &QT, const clang::QualType &ITypeT,
588592
clang::DeclaratorDecl *D, std::string N, ProgramInfo &I,
@@ -609,8 +613,8 @@ class FVComponentVariable {
609613
InternalConstraint->setGenericIndex(idx);
610614
}
611615

612-
void equateWithItype(ProgramInfo &CS, const std::string &ReasonUnchangeable,
613-
PersistentSourceLoc *PSL) const;
616+
void equateWithItype(ProgramInfo &CS,
617+
const ReasonLoc &ReasonUnchangeable) const;
614618

615619
bool solutionEqualTo(Constraints &CS, const FVComponentVariable *CV,
616620
bool ComparePtyp) const;
@@ -640,7 +644,8 @@ class FunctionVariableConstraint : public ConstraintVariable {
640644
// Count of type parameters (originally from `_Itype_for_any(...)`).
641645
int TypeParams;
642646

643-
void equateFVConstraintVars(ConstraintVariable *CV, ProgramInfo &Info) const;
647+
void equateFVConstraintVars(ConstraintVariable *CV, ProgramInfo &Info,
648+
ReasonLoc &Rsn) const;
644649

645650
public:
646651
FunctionVariableConstraint(clang::DeclaratorDecl *D, ProgramInfo &I,
@@ -723,24 +728,22 @@ class FunctionVariableConstraint : public ConstraintVariable {
723728
void dump() const override { print(llvm::errs()); }
724729
void dumpJson(llvm::raw_ostream &O) const override;
725730

726-
void constrainToWild(Constraints &CS, const std::string &Rsn) const override;
727-
void constrainToWild(Constraints &CS, const std::string &Rsn,
728-
PersistentSourceLoc *PL) const override;
731+
void constrainToWild(Constraints &CS, const ReasonLoc &Rsn) const override;
729732
bool anyChanges(const EnvironmentMap &E) const override;
730733
bool hasWild(const EnvironmentMap &E, int AIdx = -1) const override;
731734
bool hasArr(const EnvironmentMap &E, int AIdx = -1) const override;
732735
bool hasNtArr(const EnvironmentMap &E, int AIdx = -1) const override;
733736

734-
void equateArgumentConstraints(ProgramInfo &P) override;
737+
void equateArgumentConstraints(ProgramInfo &P, ReasonLoc &Rsn) override;
735738

736-
FunctionVariableConstraint *getCopy(Constraints &CS) override;
739+
FunctionVariableConstraint *getCopy(ReasonLoc &Rsn, Constraints &CS) override;
737740

738741
bool isOriginallyChecked() const override;
739742
bool isSolutionChecked(const EnvironmentMap &E) const override;
740743
bool isSolutionFullyChecked(const EnvironmentMap &E) const override;
741744

742-
void equateWithItype(ProgramInfo &CS, const std::string &ReasonUnchangeable,
743-
PersistentSourceLoc *PSL) override;
745+
void equateWithItype(ProgramInfo &CS,
746+
const ReasonLoc &ReasonUnchangeable) override;
744747

745748
~FunctionVariableConstraint() override {}
746749
};

0 commit comments

Comments
 (0)