mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Add -debug-constraints-on-line flag
This commit is contained in:
@@ -166,6 +166,10 @@ namespace swift {
|
|||||||
/// solver should be debugged.
|
/// solver should be debugged.
|
||||||
unsigned DebugConstraintSolverAttempt = 0;
|
unsigned DebugConstraintSolverAttempt = 0;
|
||||||
|
|
||||||
|
/// Line numbers to activate the constraint solver debugger.
|
||||||
|
/// Should be stored sorted.
|
||||||
|
llvm::SmallVector<unsigned, 4> DebugConstraintSolverOnLines;
|
||||||
|
|
||||||
/// Enable named lazy member loading.
|
/// Enable named lazy member loading.
|
||||||
bool NamedLazyMemberLoading = true;
|
bool NamedLazyMemberLoading = true;
|
||||||
|
|
||||||
|
|||||||
@@ -189,6 +189,12 @@ def debug_constraints : Flag<["-"], "debug-constraints">,
|
|||||||
def debug_constraints_attempt : Separate<["-"], "debug-constraints-attempt">,
|
def debug_constraints_attempt : Separate<["-"], "debug-constraints-attempt">,
|
||||||
HelpText<"Debug the constraint solver at a given attempt">;
|
HelpText<"Debug the constraint solver at a given attempt">;
|
||||||
|
|
||||||
|
def debug_constraints_on_line : Separate<["-"], "debug-constraints-on-line">,
|
||||||
|
HelpText<"Debug the constraint solver for expressions on <line>">,
|
||||||
|
MetaVarName<"<line>">;
|
||||||
|
def debug_constraints_on_line_EQ : Joined<["-"], "debug-constraints-on-line=">,
|
||||||
|
Alias<debug_constraints_on_line>;
|
||||||
|
|
||||||
def disable_named_lazy_member_loading : Flag<["-"], "disable-named-lazy-member-loading">,
|
def disable_named_lazy_member_loading : Flag<["-"], "disable-named-lazy-member-loading">,
|
||||||
HelpText<"Disable per-name lazy member loading">;
|
HelpText<"Disable per-name lazy member loading">;
|
||||||
|
|
||||||
|
|||||||
@@ -339,6 +339,17 @@ static bool ParseLangArgs(LangOptions &Opts, ArgList &Args,
|
|||||||
|
|
||||||
Opts.DebugConstraintSolverAttempt = attempt;
|
Opts.DebugConstraintSolverAttempt = attempt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (const Arg *A : Args.filtered(OPT_debug_constraints_on_line)) {
|
||||||
|
unsigned line;
|
||||||
|
if (StringRef(A->getValue()).getAsInteger(10, line)) {
|
||||||
|
Diags.diagnose(SourceLoc(), diag::error_invalid_arg_value,
|
||||||
|
A->getAsString(Args), A->getValue());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
Opts.DebugConstraintSolverOnLines.push_back(line);
|
||||||
|
}
|
||||||
|
llvm::sort(Opts.DebugConstraintSolverOnLines);
|
||||||
|
|
||||||
if (const Arg *A = Args.getLastArg(OPT_debug_forbid_typecheck_prefix)) {
|
if (const Arg *A = Args.getLastArg(OPT_debug_forbid_typecheck_prefix)) {
|
||||||
Opts.DebugForbidTypecheckPrefix = A->getValue();
|
Opts.DebugForbidTypecheckPrefix = A->getValue();
|
||||||
|
|||||||
@@ -1020,11 +1020,48 @@ void ConstraintSystem::shrink(Expr *expr) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool debugConstraintSolverForExpr(ASTContext &C, Expr *expr) {
|
||||||
|
if (C.LangOpts.DebugConstraintSolver)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (C.LangOpts.DebugConstraintSolverOnLines.empty())
|
||||||
|
// No need to compute the line number to find out it's not present.
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Get the lines on which the expression starts and ends.
|
||||||
|
unsigned startLine = 0, endLine = 0;
|
||||||
|
if (expr->getSourceRange().isValid()) {
|
||||||
|
auto range =
|
||||||
|
Lexer::getCharSourceRangeFromSourceRange(C.SourceMgr,
|
||||||
|
expr->getSourceRange());
|
||||||
|
startLine = C.SourceMgr.getLineNumber(range.getStart());
|
||||||
|
endLine = C.SourceMgr.getLineNumber(range.getEnd());
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(startLine <= endLine && "expr ends before it starts?");
|
||||||
|
|
||||||
|
auto &lines = C.LangOpts.DebugConstraintSolverOnLines;
|
||||||
|
assert(std::is_sorted(lines.begin(), lines.end()) &&
|
||||||
|
"DebugConstraintSolverOnLines sorting invariant violated");
|
||||||
|
|
||||||
|
// Check if `lines` contains at least one line `L` where
|
||||||
|
// `startLine <= L <= endLine`. If it does, `lower_bound(startLine)` and
|
||||||
|
// `upper_bound(endLine)` will be different.
|
||||||
|
auto startBound = llvm::lower_bound(lines, startLine);
|
||||||
|
auto endBound = std::upper_bound(startBound, lines.end(), endLine);
|
||||||
|
|
||||||
|
return startBound != endBound;
|
||||||
|
}
|
||||||
|
|
||||||
bool ConstraintSystem::solve(Expr *&expr,
|
bool ConstraintSystem::solve(Expr *&expr,
|
||||||
Type convertType,
|
Type convertType,
|
||||||
ExprTypeCheckListener *listener,
|
ExprTypeCheckListener *listener,
|
||||||
SmallVectorImpl<Solution> &solutions,
|
SmallVectorImpl<Solution> &solutions,
|
||||||
FreeTypeVariableBinding allowFreeTypeVariables) {
|
FreeTypeVariableBinding allowFreeTypeVariables) {
|
||||||
|
llvm::SaveAndRestore<bool>
|
||||||
|
debugForExpr(TC.getLangOpts().DebugConstraintSolver,
|
||||||
|
debugConstraintSolverForExpr(TC.Context, expr));
|
||||||
|
|
||||||
// Attempt to solve the constraint system.
|
// Attempt to solve the constraint system.
|
||||||
auto solution = solveImpl(expr,
|
auto solution = solveImpl(expr,
|
||||||
convertType,
|
convertType,
|
||||||
|
|||||||
Reference in New Issue
Block a user