Flutter Engine
The Flutter Engine
SkSLSwitchCaseContainsExit.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2021 Google LLC
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
9
13
14namespace SkSL {
15
16class Expression;
17
18namespace {
19
20class SwitchCaseContainsExit : public ProgramVisitor {
21public:
22 SwitchCaseContainsExit(bool conditionalExits) : fConditionalExits(conditionalExits) {}
23
24 bool visitExpression(const Expression& expr) override {
25 // We can avoid processing expressions entirely.
26 return false;
27 }
28
29 bool visitStatement(const Statement& stmt) override {
30 switch (stmt.kind()) {
31 case Statement::Kind::kBlock:
32 case Statement::Kind::kSwitchCase:
33 return INHERITED::visitStatement(stmt);
34
35 case Statement::Kind::kReturn:
36 // Returns are an early exit regardless of the surrounding control structures.
37 return fConditionalExits ? fInConditional : !fInConditional;
38
40 // Continues are an early exit from switches, but not loops.
41 return !fInLoop &&
42 (fConditionalExits ? fInConditional : !fInConditional);
43
44 case Statement::Kind::kBreak:
45 // Breaks cannot escape from switches or loops.
46 return !fInLoop && !fInSwitch &&
47 (fConditionalExits ? fInConditional : !fInConditional);
48
49 case Statement::Kind::kIf: {
50 ++fInConditional;
51 bool result = INHERITED::visitStatement(stmt);
52 --fInConditional;
53 return result;
54 }
55
56 case Statement::Kind::kFor:
57 case Statement::Kind::kDo: {
58 // Loops are treated as conditionals because a loop could potentially execute zero
59 // times. We don't have a straightforward way to determine that a loop definitely
60 // executes at least once.
61 ++fInConditional;
62 ++fInLoop;
63 bool result = INHERITED::visitStatement(stmt);
64 --fInLoop;
65 --fInConditional;
66 return result;
67 }
68
69 case Statement::Kind::kSwitch: {
70 ++fInSwitch;
71 bool result = INHERITED::visitStatement(stmt);
72 --fInSwitch;
73 return result;
74 }
75
76 default:
77 return false;
78 }
79 }
80
81 bool fConditionalExits = false;
82 int fInConditional = 0;
83 int fInLoop = 0;
84 int fInSwitch = 0;
85 using INHERITED = ProgramVisitor;
86};
87
88} // namespace
89
91 return SwitchCaseContainsExit{/*conditionalExits=*/false}.visitStatement(stmt);
92}
93
95 return SwitchCaseContainsExit{/*conditionalExits=*/true}.visitStatement(stmt);
96}
97
98} // namespace SkSL
#define INHERITED(method,...)
Definition: SkRecorder.cpp:128
Expression(Position pos, Kind kind, const Type *type)
GAsyncResult * result
bool SwitchCaseContainsUnconditionalExit(const Statement &stmt)
bool SwitchCaseContainsConditionalExit(const Statement &stmt)