Skip to content

Commit 888dd78

Browse files
committed
Swift: fix SequenceExpr extraction
Before we extracted all the subexpressions from the `SequenceExpr` while we should've only extracted the expressions at odd indices: ``` ... /// SequenceExpr - A list of binary operations which has not yet been /// folded into a tree. The operands all have even indices, while the /// subexpressions with odd indices are all (potentially overloaded) /// references to binary operators. class SequenceExpr final : public Expr, ... ``` The AST for a `SequenceExpr` looks like this: ``` sequence_expr: unresolved_dot_expr: ... assign_expr: member_ref_expr: ... dot_syntax_call_expr: ... unresolved_member_chain_expr: ... ``` however, what's is not visible with the "final" AST is that `unresolved_dot_expr` is the unresolved version of `assign_expr.member_ref_expr` and the `unresolved_member_chain_expr` is the unresolved version of `assign_expr.dot_syntax_call_expr`. This becomes visible when I enable typechecker debugging: ```c++ auto &typeCheckerOptions = invocation.getTypeCheckerOptions(); typeCheckerOptions.DebugConstraintSolver = true; ``` Which prints the following snippets: ``` ---Initial constraints for the given expression--- (assign_expr type='()' location=foo.swift:25:54 range=[foo.swift:25:13 - line:25:57] (unresolved_dot_expr type='$T2' location=foo.swift:25:29 range=[foo.swift:25:13 - line:25:29] field 'preferredDatePickerStyle' function_ref=unapplied (unresolved_dot_expr type='$T1' location=foo.swift:25:18 range=[foo.swift:25:13 - line:25:18] field 'datePicker' function_ref=unapplied (declref_expr type='DatePickerCell' location=foo.swift:25:13 range=[foo.swift:25:13 - line:25:13] decl=foo.(file).DatePickerRowProtocol extension.configurePickerStyle(_:_:)[email protected]:15:33 function_ref=unapplied))) (unresolved_member_chain_expr implicit type='$T5' location=foo.swift:25:57 range=[foo.swift:25:56 - line:25:57] (unresolved_member_expr type='$T4' location=foo.swift:25:57 range=[foo.swift:25:56 - line:25:57] name='wheels' function_ref=unapplied))) // ... ---Type-checked expression--- (assign_expr type='()' location=foo.swift:25:54 range=[foo.swift:25:13 - line:25:57] (member_ref_expr type='@lvalue UIDatePickerStyle' location=foo.swift:25:29 range=[foo.swift:25:13 - line:25:29] decl=UIKit.(file).UIDatePicker.preferredDatePickerStyle (force_value_expr implicit type='UIDatePicker' location=foo.swift:25:18 range=[foo.swift:25:13 - line:25:18] implicit_iuo_unwrap (load_expr implicit type='UIDatePicker?' location=foo.swift:25:18 range=[foo.swift:25:13 - line:25:18] (member_ref_expr type='@lvalue UIDatePicker?' location=foo.swift:25:18 range=[foo.swift:25:13 - line:25:18] decl=foo.(file)[email protected]:10:29 (declref_expr type='DatePickerCell' location=foo.swift:25:13 range=[foo.swift:25:13 - line:25:13] decl=foo.(file).DatePickerRowProtocol extension.configurePickerStyle(_:_:)[email protected]:15:33 function_ref=unapplied))))) (dot_syntax_call_expr type='UIDatePickerStyle' location=foo.swift:25:57 range=[foo.swift:25:56 - line:25:57] (declref_expr type='(UIDatePickerStyle.Type) -> UIDatePickerStyle' location=foo.swift:25:57 range=[foo.swift:25:57 - line:25:57] decl=UIKit.(file).UIDatePickerStyle.wheels function_ref=unapplied) (argument_list implicit (argument (type_expr implicit type='UIDatePickerStyle.Type' location=foo.swift:25:56 range=[foo.swift:25:56 - line:25:56] typerepr='UIDatePickerStyle'))))) ``` The proposed solution is to only extract subexpressions at indices from `SequenceExpr` thus ignoring all the unresolved leftovers. Note: I'm not entirely sure about the case when there is only child (`elements.size() == 1`) so I'm always extracting it. This patch fixes the last source of unresolved expressions.
1 parent 284ca5e commit 888dd78

File tree

1 file changed

+11
-1
lines changed

1 file changed

+11
-1
lines changed

swift/extractor/translators/ExprTranslator.cpp

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -460,7 +460,17 @@ codeql::UnresolvedMemberExpr ExprTranslator::translateUnresolvedMemberExpr(
460460

461461
codeql::SequenceExpr ExprTranslator::translateSequenceExpr(const swift::SequenceExpr& expr) {
462462
auto entry = createExprEntry(expr);
463-
entry.elements = dispatcher.fetchRepeatedLabels(expr.getElements());
463+
// SequenceExpr represents a flat tree of expressions with elements at odd indices being the
464+
// parents of the elements with even indices, so we only extract the "parent" elements here. In
465+
// case there is a single child, we extract it as a parent. See
466+
// https://github.com/github/codeql/pull/14119 and commit message for more details.
467+
if (expr.getNumElements() == 1) {
468+
entry.elements = dispatcher.fetchRepeatedLabels(expr.getElements());
469+
} else {
470+
for (int i = 1; i < expr.getNumElements(); i += 2) {
471+
entry.elements.emplace_back(dispatcher.fetchLabel(expr.getElement(i)));
472+
}
473+
}
464474
return entry;
465475
}
466476

0 commit comments

Comments
 (0)