Wrap built-in symbol tables when an IRNode is cloned.

After an IRNode is cloned, callers expect to be able to safely mutate
its SymbolTable, so it can't be left with a built-in one.

Change-Id: If658fd11ad580da552f9d689edeeed4c842b38c9
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/328384
Commit-Queue: John Stiles <johnstiles@google.com>
Reviewed-by: Brian Osman <brianosman@google.com>
Auto-Submit: John Stiles <johnstiles@google.com>
diff --git a/src/sksl/SkSLInliner.cpp b/src/sksl/SkSLInliner.cpp
index e901143..cd4baec 100644
--- a/src/sksl/SkSLInliner.cpp
+++ b/src/sksl/SkSLInliner.cpp
@@ -607,11 +607,12 @@
                                                        /*isScope=*/false);
 
     Block& inlinedBody = *inlinedCall.fInlinedBody;
-    inlinedBody.children().reserve_back(1 +                // Inline marker
-                                   1 +                // Result variable
-                                   arguments.size() + // Function arguments (passing in)
-                                   arguments.size() + // Function arguments (copy out-params back)
-                                   1);                // Inlined code (Block or do-while loop)
+    inlinedBody.children().reserve_back(
+            1 +                 // Inline marker
+            1 +                 // Result variable
+            arguments.size() +  // Function arguments (passing in)
+            arguments.size() +  // Function arguments (copy out-params back)
+            1);                 // Inlined code (Block or do-while loop)
 
     inlinedBody.children().push_back(std::make_unique<InlineMarker>(&call->function()));
 
diff --git a/src/sksl/ir/SkSLBlock.h b/src/sksl/ir/SkSLBlock.h
index 9312396..2dd1aec 100644
--- a/src/sksl/ir/SkSLBlock.h
+++ b/src/sksl/ir/SkSLBlock.h
@@ -60,9 +60,9 @@
         for (const std::unique_ptr<Statement>& stmt : this->children()) {
             cloned.push_back(stmt->clone());
         }
-        const BlockData& data = this->blockData();
-        return std::make_unique<Block>(fOffset, std::move(cloned), data.fSymbolTable,
-                                       data.fIsScope);
+        return std::make_unique<Block>(fOffset, std::move(cloned),
+                                       SymbolTable::WrapIfBuiltin(this->symbolTable()),
+                                       this->isScope());
     }
 
     String description() const override {
diff --git a/src/sksl/ir/SkSLEnum.h b/src/sksl/ir/SkSLEnum.h
index 0422fb5..22a2a79 100644
--- a/src/sksl/ir/SkSLEnum.h
+++ b/src/sksl/ir/SkSLEnum.h
@@ -45,7 +45,8 @@
     }
 
     std::unique_ptr<ProgramElement> clone() const override {
-        return std::make_unique<Enum>(fOffset, this->typeName(), this->symbols(),
+        return std::make_unique<Enum>(fOffset, this->typeName(),
+                                      SymbolTable::WrapIfBuiltin(this->symbols()),
                                       this->isSharedWithCpp(), /*isBuiltin=*/false);
     }
 
diff --git a/src/sksl/ir/SkSLForStatement.h b/src/sksl/ir/SkSLForStatement.h
index d12a9f5..27b618d 100644
--- a/src/sksl/ir/SkSLForStatement.h
+++ b/src/sksl/ir/SkSLForStatement.h
@@ -70,13 +70,13 @@
     }
 
     std::unique_ptr<Statement> clone() const override {
-        return std::unique_ptr<Statement>(new ForStatement(
-                                       fOffset,
-                                       this->initializer() ? this->initializer()->clone() : nullptr,
-                                       this->test() ? this->test()->clone() : nullptr,
-                                       this->next() ? this->next()->clone() : nullptr,
-                                       this->statement()->clone(),
-                                       this->symbols()));
+        return std::make_unique<ForStatement>(
+                fOffset,
+                this->initializer() ? this->initializer()->clone() : nullptr,
+                this->test() ? this->test()->clone() : nullptr,
+                this->next() ? this->next()->clone() : nullptr,
+                this->statement()->clone(),
+                SymbolTable::WrapIfBuiltin(this->symbols()));
     }
 
     String description() const override {
diff --git a/src/sksl/ir/SkSLInterfaceBlock.h b/src/sksl/ir/SkSLInterfaceBlock.h
index 707f5df..672e3b3 100644
--- a/src/sksl/ir/SkSLInterfaceBlock.h
+++ b/src/sksl/ir/SkSLInterfaceBlock.h
@@ -70,7 +70,7 @@
         }
         return std::make_unique<InterfaceBlock>(fOffset, &this->variable(), this->typeName(),
                                                 this->instanceName(), std::move(sizesClone),
-                                                this->typeOwner());
+                                                SymbolTable::WrapIfBuiltin(this->typeOwner()));
     }
 
     String description() const override {
diff --git a/src/sksl/ir/SkSLSymbolTable.h b/src/sksl/ir/SkSLSymbolTable.h
index aae872e..9f2b173 100644
--- a/src/sksl/ir/SkSLSymbolTable.h
+++ b/src/sksl/ir/SkSLSymbolTable.h
@@ -34,6 +34,16 @@
     , fBuiltin(builtin)
     , fErrorReporter(parent->fErrorReporter) {}
 
+    static std::shared_ptr<SymbolTable> WrapIfBuiltin(std::shared_ptr<SymbolTable> symbolTable) {
+        if (!symbolTable) {
+            return nullptr;
+        }
+        if (!symbolTable->isBuiltin()) {
+            return symbolTable;
+        }
+        return std::make_shared<SymbolTable>(std::move(symbolTable), /*builtin=*/false);
+    }
+
     const Symbol* operator[](StringFragment name);
 
     void addAlias(StringFragment name, const Symbol* symbol);