Flutter Engine
The Flutter Engine
SkSLCheckSymbolTableCorrectness.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2024 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#include "src/core/SkTHash.h"
19
20#include <memory>
21#include <string>
22#include <string_view>
23#include <vector>
24
25using namespace skia_private;
26
27namespace SkSL {
28
29class Expression;
30class ProgramElement;
31class Symbol;
32
34 const Context& context = *program.fContext;
35
36 class SymbolTableCorrectnessVisitor : public ProgramVisitor {
37 public:
38 SymbolTableCorrectnessVisitor(const Context& c, SymbolTable* sym)
39 : fContext(c)
40 , fSymbolTableStack({sym}) {}
41
43
44 bool visitStatement(const Statement& stmt) override {
45 Analysis::SymbolTableStackBuilder symbolTableStackBuilder(&stmt, &fSymbolTableStack);
46 if (stmt.is<VarDeclaration>()) {
47 // Check the top of the symbol table stack to see if it contains this exact symbol.
48 const VarDeclaration& vardecl = stmt.as<VarDeclaration>();
49 bool containsSymbol = false;
50
51 // We want to do an exact Symbol* comparison in just one symbol table; we don't want
52 // to look up by name, and we don't want to walk the symbol table tree. This makes
53 // SymbolTable::find() an inappropriate tool for the job. Instead, we can iterate
54 // the symbol table's contents directly and check for a pointer match.
55 fSymbolTableStack.back()->foreach([&](std::string_view, const Symbol* symbol) {
56 if (symbol == vardecl.var()) {
57 containsSymbol = true;
58 }
59 });
60 if (!containsSymbol) {
61 fContext.fErrors->error(vardecl.position(), "internal error (variable '" +
62 std::string(vardecl.var()->name()) +
63 "' is incorrectly scoped)");
64 }
65 }
66 return INHERITED::visitStatement(stmt);
67 }
68
69 bool visitExpression(const Expression&) override {
70 return false;
71 }
72
73 private:
75
76 const Context& fContext;
77 std::vector<SymbolTable*> fSymbolTableStack;
78 };
79
80 SymbolTableCorrectnessVisitor visitor{context, program.fSymbols.get()};
81 for (const std::unique_ptr<ProgramElement>& pe : program.fOwnedElements) {
82 visitor.visitProgramElement(*pe);
83 }
84}
85
86} // namespace SkSL
#define INHERITED(method,...)
Definition: SkRecorder.cpp:128
const Context & fContext
Position position() const
Definition: SkSLIRNode.h:111
bool is() const
Definition: SkSLIRNode.h:124
const T & as() const
Definition: SkSLIRNode.h:133
std::string_view name() const
Definition: SkSLSymbol.h:51
virtual bool visitProgramElement(typename T::ProgramElement &programElement)
Variable * var() const
void CheckSymbolTableCorrectness(const Program &program)
std::vector< std::unique_ptr< ProgramElement > > fOwnedElements
Definition: SkSLProgram.h:161
std::shared_ptr< Context > fContext
Definition: SkSLProgram.h:154
std::unique_ptr< SymbolTable > fSymbols
Definition: SkSLProgram.h:158