blob: 466740f5b510c4c1aaaf843d3460058d84c92c88 [file] [log] [blame]
/*
* Copyright 2023 Google LLC
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "src/sksl/SkSLAnalysis.h"
#include "include/private/SkSLIRNode.h"
#include "include/private/SkSLStatement.h"
#include "src/sksl/analysis/SkSLProgramVisitor.h"
namespace SkSL {
class Expression;
namespace Analysis {
namespace {
class HasContinueOrBreakVisitor : public ProgramVisitor {
public:
HasContinueOrBreakVisitor() {}
bool visitExpression(const Expression& expr) override {
// We can avoid processing expressions entirely.
return false;
}
bool visitStatement(const Statement& stmt) override {
switch (stmt.kind()) {
case Statement::Kind::kContinue:
fResult.fHasContinue = true;
return fResult.fHasContinue && fResult.fHasBreak;
case Statement::Kind::kBreak:
fResult.fHasBreak = true;
return fResult.fHasContinue && fResult.fHasBreak;
case Statement::Kind::kFor:
case Statement::Kind::kDo:
case Statement::Kind::kSwitch: {
// A continue or break inside of a for-statement or do-statement would not affect
// the control flow of the outer statement; they would affect the inner loop
// instead. A break inside of a switch-case statement escapes the switch, and SkSL
// does not allow continues inside of a switch at all, so we don't need to visit
// switches either.
return false;
}
default:
return ProgramVisitor::visitStatement(stmt);
}
}
ContinueOrBreakInfo fResult;
};
} // namespace
ContinueOrBreakInfo HasContinueOrBreak(const Statement& stmt) {
HasContinueOrBreakVisitor visitor;
visitor.visitStatement(stmt);
return visitor.fResult;
}
} // namespace Analysis
} // namespace SkSL