Commit 2d88e9bc by Olli Etuaho Committed by Commit Bot

Guarantee that symbol nodes get unique ids

The code is refactored so that symbol nodes can only be initialized with an unique id object. This prevents accidentally forgetting to create an id for a symbol node. This opens up possibilities for future optimization: For example the names and types of symbols could be stored in a central location inside the SymbolTable, and TIntermSymbol nodes would only need to store the symbol id. The symbol id could be used to look up the name and type of the node. BUG=angleproject:1490 TEST=angle_unittests Change-Id: Ib8c8675d31493037a5a28c7b36bb9d1113cc10f6 Reviewed-on: https://chromium-review.googlesource.com/580955Reviewed-by: 's avatarCorentin Wallez <cwallez@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Commit-Queue: Jamie Madill <jmadill@chromium.org> Commit-Queue: Olli Etuaho <oetuaho@nvidia.com>
parent bf90b603
......@@ -140,6 +140,8 @@
'compiler/translator/SplitSequenceOperator.h',
'compiler/translator/SymbolTable.cpp',
'compiler/translator/SymbolTable.h',
'compiler/translator/SymbolUniqueId.cpp',
'compiler/translator/SymbolUniqueId.h',
'compiler/translator/Types.cpp',
'compiler/translator/Types.h',
'compiler/translator/UnfoldShortCircuitAST.cpp',
......
......@@ -30,7 +30,7 @@ void CopyAggregateChildren(TIntermAggregateBase *from, TIntermAggregateBase *to)
TIntermSymbol *CreateReturnValueSymbol(const TSymbolUniqueId &id, const TType &type)
{
TIntermSymbol *node = new TIntermSymbol(id.get(), "angle_return", type);
TIntermSymbol *node = new TIntermSymbol(id, "angle_return", type);
node->setInternal(true);
node->getTypePointer()->setQualifier(EvqOut);
return node;
......
......@@ -132,7 +132,7 @@ void SelectViewIndexInVertexShader(TIntermTyped *viewIDSymbol,
new TIntermBinary(EOpAssign, viewportIndexSymbol, viewIDAsInt));
// Create a gl_Layer node.
TIntermSymbol *layerSymbol = new TIntermSymbol(0, "gl_Layer", TType(EbtInt, EbpHigh, EvqLayer));
TIntermSymbol *layerSymbol = ReferenceBuiltInVariable("gl_Layer", symbolTable, 0);
// Create an int(ViewID_OVR) + multiviewBaseViewLayerIndex node
TIntermBinary *sumOfViewIDAndBaseViewIndex =
......
......@@ -964,6 +964,8 @@ void IdentifyBuiltIns(sh::GLenum type,
// For internal use by ANGLE - not exposed to the parser.
symbolTable.insertVariable(GLSL_BUILTINS, "gl_ViewportIndex",
TType(EbtInt, EbpHigh, EvqViewportIndex));
// gl_Layer exists in other shader stages in ESSL, but not in vertex shader so far.
symbolTable.insertVariable(GLSL_BUILTINS, "gl_Layer", TType(EbtInt, EbpHigh, EvqLayer));
break;
}
case GL_COMPUTE_SHADER:
......
......@@ -25,6 +25,7 @@
#include "compiler/translator/Common.h"
#include "compiler/translator/ConstantUnion.h"
#include "compiler/translator/Operator.h"
#include "compiler/translator/SymbolUniqueId.h"
#include "compiler/translator/Types.h"
namespace sh
......@@ -56,7 +57,6 @@ class TIntermRaw;
class TIntermBranch;
class TSymbolTable;
class TSymbolUniqueId;
class TFunction;
// Encapsulate an identifier string and track whether it is coming from the original shader code
......@@ -257,7 +257,7 @@ class TIntermSymbol : public TIntermTyped
// if symbol is initialized as symbol(sym), the memory comes from the poolallocator of sym.
// If sym comes from per process globalpoolallocator, then it causes increased memory usage
// per compile it is essential to use "symbol = sym" to assign to symbol
TIntermSymbol(int id, const TString &symbol, const TType &type)
TIntermSymbol(const TSymbolUniqueId &id, const TString &symbol, const TType &type)
: TIntermTyped(type), mId(id), mSymbol(symbol)
{
}
......@@ -266,7 +266,7 @@ class TIntermSymbol : public TIntermTyped
bool hasSideEffects() const override { return false; }
int getId() const { return mId; }
int getId() const { return mId.get(); }
const TString &getSymbol() const { return mSymbol.getString(); }
const TName &getName() const { return mSymbol; }
TName &getName() { return mSymbol; }
......@@ -278,7 +278,7 @@ class TIntermSymbol : public TIntermTyped
bool replaceChildNode(TIntermNode *, TIntermNode *) override { return false; }
protected:
const int mId;
const TSymbolUniqueId mId;
TName mSymbol;
private:
......
......@@ -178,7 +178,7 @@ TIntermSymbol *CreateTempSymbolNode(const TSymbolUniqueId &id,
symbolNameOut << "s" << id.get();
TString symbolName = symbolNameOut.c_str();
TIntermSymbol *node = new TIntermSymbol(id.get(), symbolName, type);
TIntermSymbol *node = new TIntermSymbol(id, symbolName, type);
node->setInternal(true);
ASSERT(qualifier == EvqTemporary || qualifier == EvqConst || qualifier == EvqGlobal);
......
......@@ -119,8 +119,9 @@ OutputHLSL::OutputHLSL(sh::GLenum shaderType,
ShShaderOutput outputType,
int numRenderTargets,
const std::vector<Uniform> &uniforms,
ShCompileOptions compileOptions)
: TIntermTraverser(true, true, true),
ShCompileOptions compileOptions,
TSymbolTable *symbolTable)
: TIntermTraverser(true, true, true, symbolTable),
mShaderType(shaderType),
mShaderVersion(shaderVersion),
mExtensionBehavior(extensionBehavior),
......@@ -375,7 +376,7 @@ void OutputHLSL::header(TInfoSinkBase &out, const BuiltInFunctionEmulator *built
out << mStructureHLSL->structsHeader();
mUniformHLSL->uniformsHeader(out, mOutputType, mReferencedUniforms);
mUniformHLSL->uniformsHeader(out, mOutputType, mReferencedUniforms, mSymbolTable);
out << mUniformHLSL->uniformBlocksHeader(mReferencedUniformBlocks);
if (!mEqualityFunctions.empty())
......@@ -1895,8 +1896,8 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node)
const TType &argType = typedArg->getType();
TVector<TIntermSymbol *> samplerSymbols;
TString structName = samplerNamePrefixFromStruct(typedArg);
argType.createSamplerSymbols("angle_" + structName, "",
&samplerSymbols, nullptr);
argType.createSamplerSymbols("angle_" + structName, "", &samplerSymbols,
nullptr, mSymbolTable);
for (const TIntermSymbol *sampler : samplerSymbols)
{
if (mOutputType == SH_HLSL_4_0_FL9_3_OUTPUT)
......@@ -2626,7 +2627,7 @@ TString OutputHLSL::argumentString(const TIntermSymbol *symbol)
{
ASSERT(qualifier != EvqOut && qualifier != EvqInOut);
TVector<TIntermSymbol *> samplerSymbols;
type.createSamplerSymbols("angle" + nameStr, "", &samplerSymbols, nullptr);
type.createSamplerSymbols("angle" + nameStr, "", &samplerSymbols, nullptr, mSymbolTable);
for (const TIntermSymbol *sampler : samplerSymbols)
{
const TType &samplerType = sampler->getType();
......
......@@ -22,6 +22,7 @@ namespace sh
{
class StructureHLSL;
class TextureFunctionHLSL;
class TSymbolTable;
class UnfoldShortCircuit;
class UniformHLSL;
......@@ -37,7 +38,8 @@ class OutputHLSL : public TIntermTraverser
ShShaderOutput outputType,
int numRenderTargets,
const std::vector<Uniform> &uniforms,
ShCompileOptions compileOptions);
ShCompileOptions compileOptions,
TSymbolTable *symbolTable);
~OutputHLSL();
......
......@@ -2311,7 +2311,7 @@ TIntermDeclaration *TParseContext::parseSingleDeclaration(
// But if the empty declaration is declaring a struct type, the symbol node will store that.
if (type.getBasicType() == EbtStruct)
{
symbol = new TIntermSymbol(0, "", type);
symbol = new TIntermSymbol(symbolTable.getEmptySymbolId(), "", type);
}
else if (IsAtomicCounter(publicType.getBasicType()))
{
......@@ -3075,7 +3075,7 @@ TIntermFunctionPrototype *TParseContext::createPrototypeNodeFromFunction(
{
// The parameter had no name or declaring the symbol failed - either way, add a nameless
// symbol.
symbol = new TIntermSymbol(0, "", *param.type);
symbol = new TIntermSymbol(symbolTable.getEmptySymbolId(), "", *param.type);
}
symbol->setLine(location);
prototype->appendParameter(symbol);
......@@ -3637,7 +3637,7 @@ TIntermDeclaration *TParseContext::addInterfaceBlock(
}
TString symbolName = "";
int symbolId = 0;
const TSymbolUniqueId *symbolId = nullptr;
if (!instanceName)
{
......@@ -3662,6 +3662,7 @@ TIntermDeclaration *TParseContext::addInterfaceBlock(
field->name().c_str());
}
}
symbolId = &symbolTable.getEmptySymbolId();
}
else
{
......@@ -3672,7 +3673,7 @@ TIntermDeclaration *TParseContext::addInterfaceBlock(
if (instanceTypeDef)
{
instanceTypeDef->setQualifier(typeQualifier.qualifier);
symbolId = instanceTypeDef->getUniqueId();
symbolId = &instanceTypeDef->getUniqueId();
}
else
{
......@@ -3682,11 +3683,16 @@ TIntermDeclaration *TParseContext::addInterfaceBlock(
symbolName = *instanceName;
}
TIntermSymbol *blockSymbol = new TIntermSymbol(symbolId, symbolName, interfaceBlockType);
blockSymbol->setLine(typeQualifier.line);
TIntermDeclaration *declaration = new TIntermDeclaration();
declaration->appendDeclarator(blockSymbol);
declaration->setLine(nameLine);
TIntermDeclaration *declaration = nullptr;
if (symbolId)
{
TIntermSymbol *blockSymbol = new TIntermSymbol(*symbolId, symbolName, interfaceBlockType);
blockSymbol->setLine(typeQualifier.line);
declaration = new TIntermDeclaration();
declaration->appendDeclarator(blockSymbol);
declaration->setLine(nameLine);
}
exitStructDeclaration();
return declaration;
......
......@@ -29,19 +29,6 @@ static const char kFunctionMangledNameSeparator = '(';
} // anonymous namespace
TSymbolUniqueId::TSymbolUniqueId(TSymbolTable *symbolTable) : mId(symbolTable->nextUniqueId())
{
}
TSymbolUniqueId::TSymbolUniqueId(const TSymbol &symbol) : mId(symbol.getUniqueId())
{
}
int TSymbolUniqueId::get() const
{
return mId;
}
TSymbol::TSymbol(TSymbolTable *symbolTable, const TString *n)
: uniqueId(symbolTable->nextUniqueId()), name(n), extension(TExtension::UNDEFINED)
{
......
......@@ -38,26 +38,11 @@
#include "compiler/translator/ExtensionBehavior.h"
#include "compiler/translator/InfoSink.h"
#include "compiler/translator/IntermNode.h"
#include "compiler/translator/SymbolUniqueId.h"
namespace sh
{
// Encapsulates a unique id for a symbol.
class TSymbolUniqueId
{
public:
POOL_ALLOCATOR_NEW_DELETE();
TSymbolUniqueId(TSymbolTable *symbolTable);
TSymbolUniqueId(const TSymbol &symbol);
TSymbolUniqueId(const TSymbolUniqueId &) = default;
TSymbolUniqueId &operator=(const TSymbolUniqueId &) = default;
int get() const;
private:
int mId;
};
// Symbol base class. (Can build functions or variables out of these...)
class TSymbol : angle::NonCopyable
{
......@@ -74,12 +59,12 @@ class TSymbol : angle::NonCopyable
virtual const TString &getMangledName() const { return getName(); }
virtual bool isFunction() const { return false; }
virtual bool isVariable() const { return false; }
int getUniqueId() const { return uniqueId; }
const TSymbolUniqueId &getUniqueId() const { return uniqueId; }
void relateToExtension(TExtension ext) { extension = ext; }
TExtension getExtension() const { return extension; }
private:
const int uniqueId;
const TSymbolUniqueId uniqueId;
const TString *name;
TExtension extension;
};
......@@ -302,7 +287,7 @@ const int GLOBAL_LEVEL = 5;
class TSymbolTable : angle::NonCopyable
{
public:
TSymbolTable() : mUniqueIdCounter(0)
TSymbolTable() : mUniqueIdCounter(0), mEmptySymbolId(this)
{
// The symbol table cannot be used until push() is called, but
// the lack of an initial call to push() can be used to detect
......@@ -514,12 +499,20 @@ class TSymbolTable : angle::NonCopyable
table[currentLevel()]->setGlobalInvariant(invariant);
}
int nextUniqueId() { return ++mUniqueIdCounter; }
const TSymbolUniqueId nextUniqueId() { return TSymbolUniqueId(this); }
// The empty symbol id is shared between all empty string ("") symbols. They are used in the
// AST for unused function parameters and struct type declarations that don't declare a
// variable, for example.
const TSymbolUniqueId &getEmptySymbolId() { return mEmptySymbolId; }
// Checks whether there is a built-in accessible by a shader with the specified version.
bool hasUnmangledBuiltInForShaderVersion(const char *name, int shaderVersion);
private:
friend class TSymbolUniqueId;
int nextUniqueIdValue() { return ++mUniqueIdCounter; }
ESymbolLevel currentLevel() const { return static_cast<ESymbolLevel>(table.size() - 1); }
TVariable *insertVariable(ESymbolLevel level, const TString *name, const TType &type);
......@@ -543,6 +536,8 @@ class TSymbolTable : angle::NonCopyable
std::vector<PrecisionStackLevel *> precisionStack;
int mUniqueIdCounter;
const TSymbolUniqueId mEmptySymbolId;
};
} // namespace sh
......
//
// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// SymbolUniqueId.cpp: Encapsulates a unique id for a symbol.
#include "compiler/translator/SymbolUniqueId.h"
#include "compiler/translator/SymbolTable.h"
namespace sh
{
TSymbolUniqueId::TSymbolUniqueId(TSymbolTable *symbolTable) : mId(symbolTable->nextUniqueIdValue())
{
}
TSymbolUniqueId::TSymbolUniqueId(const TSymbol &symbol) : mId(symbol.getUniqueId().get())
{
}
int TSymbolUniqueId::get() const
{
return mId;
}
} // namespace sh
//
// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// SymbolUniqueId.h: Encapsulates a unique id for a symbol.
#ifndef COMPILER_TRANSLATOR_SYMBOLUNIQUEID_H_
#define COMPILER_TRANSLATOR_SYMBOLUNIQUEID_H_
#include "compiler/translator/Common.h"
namespace sh
{
class TSymbolTable;
class TSymbol;
class TSymbolUniqueId
{
public:
POOL_ALLOCATOR_NEW_DELETE();
explicit TSymbolUniqueId(TSymbolTable *symbolTable);
explicit TSymbolUniqueId(const TSymbol &symbol);
TSymbolUniqueId(const TSymbolUniqueId &) = default;
TSymbolUniqueId &operator=(const TSymbolUniqueId &) = default;
int get() const;
private:
int mId;
};
} // namespace sh
#endif // COMPILER_TRANSLATOR_SYMBOLUNIQUEID_H_
......@@ -126,7 +126,7 @@ void TranslatorHLSL::translate(TIntermBlock *root, ShCompileOptions compileOptio
sh::OutputHLSL outputHLSL(getShaderType(), getShaderVersion(), getExtensionBehavior(),
getSourcePath(), getOutputType(), numRenderTargets, getUniforms(),
compileOptions);
compileOptions, &getSymbolTable());
outputHLSL.output(root, getInfoSink().obj);
......
......@@ -621,7 +621,8 @@ bool TStructure::containsSamplers() const
void TType::createSamplerSymbols(const TString &namePrefix,
const TString &apiNamePrefix,
TVector<TIntermSymbol *> *outputSymbols,
TMap<TIntermSymbol *, TString> *outputSymbolsToAPINames) const
TMap<TIntermSymbol *, TString> *outputSymbolsToAPINames,
TSymbolTable *symbolTable) const
{
if (isStructureContainingSamplers())
{
......@@ -636,18 +637,20 @@ void TType::createSamplerSymbols(const TString &namePrefix,
TStringStream elementApiName;
elementApiName << apiNamePrefix << "[" << arrayIndex << "]";
elementType.createSamplerSymbols(elementName.str(), elementApiName.str(),
outputSymbols, outputSymbolsToAPINames);
outputSymbols, outputSymbolsToAPINames,
symbolTable);
}
}
else
{
structure->createSamplerSymbols(namePrefix, apiNamePrefix, outputSymbols,
outputSymbolsToAPINames);
outputSymbolsToAPINames, symbolTable);
}
return;
}
ASSERT(IsSampler(type));
TIntermSymbol *symbol = new TIntermSymbol(0, namePrefix, *this);
TIntermSymbol *symbol = new TIntermSymbol(symbolTable->nextUniqueId(), namePrefix, *this);
outputSymbols->push_back(symbol);
if (outputSymbolsToAPINames)
{
......@@ -658,7 +661,8 @@ void TType::createSamplerSymbols(const TString &namePrefix,
void TStructure::createSamplerSymbols(const TString &namePrefix,
const TString &apiNamePrefix,
TVector<TIntermSymbol *> *outputSymbols,
TMap<TIntermSymbol *, TString> *outputSymbolsToAPINames) const
TMap<TIntermSymbol *, TString> *outputSymbolsToAPINames,
TSymbolTable *symbolTable) const
{
ASSERT(containsSamplers());
for (auto &field : *mFields)
......@@ -669,7 +673,7 @@ void TStructure::createSamplerSymbols(const TString &namePrefix,
TString fieldName = namePrefix + "_" + field->name();
TString fieldApiName = apiNamePrefix + "." + field->name();
fieldType->createSamplerSymbols(fieldName, fieldApiName, outputSymbols,
outputSymbolsToAPINames);
outputSymbolsToAPINames, symbolTable);
}
}
}
......
......@@ -12,6 +12,7 @@
#include "compiler/translator/BaseTypes.h"
#include "compiler/translator/Common.h"
#include "compiler/translator/SymbolUniqueId.h"
namespace sh
{
......@@ -103,15 +104,12 @@ class TStructure : public TFieldListCollection
void createSamplerSymbols(const TString &namePrefix,
const TString &apiNamePrefix,
TVector<TIntermSymbol *> *outputSymbols,
TMap<TIntermSymbol *, TString> *outputSymbolsToAPINames) const;
TMap<TIntermSymbol *, TString> *outputSymbolsToAPINames,
TSymbolTable *symbolTable) const;
bool equals(const TStructure &other) const;
int uniqueId() const
{
ASSERT(mUniqueId != 0);
return mUniqueId;
}
int uniqueId() const { return mUniqueId.get(); }
void setAtGlobalScope(bool atGlobalScope) { mAtGlobalScope = atGlobalScope; }
......@@ -138,7 +136,7 @@ class TStructure : public TFieldListCollection
int calculateDeepestNesting() const;
mutable int mDeepestNesting;
const int mUniqueId;
const TSymbolUniqueId mUniqueId;
bool mAtGlobalScope;
};
......@@ -478,7 +476,8 @@ class TType
void createSamplerSymbols(const TString &namePrefix,
const TString &apiNamePrefix,
TVector<TIntermSymbol *> *outputSymbols,
TMap<TIntermSymbol *, TString> *outputSymbolsToAPINames) const;
TMap<TIntermSymbol *, TString> *outputSymbolsToAPINames,
TSymbolTable *symbolTable) const;
// Initializes all lazily-initialized members.
void realize() { getMangledName(); }
......
......@@ -278,7 +278,8 @@ void UniformHLSL::outputUniform(TInfoSinkBase &out,
void UniformHLSL::uniformsHeader(TInfoSinkBase &out,
ShShaderOutput outputType,
const ReferencedSymbols &referencedUniforms)
const ReferencedSymbols &referencedUniforms,
TSymbolTable *symbolTable)
{
if (!referencedUniforms.empty())
{
......@@ -313,7 +314,7 @@ void UniformHLSL::uniformsHeader(TInfoSinkBase &out,
TVector<TIntermSymbol *> samplerSymbols;
TMap<TIntermSymbol *, TString> symbolsToAPINames;
type.createSamplerSymbols("angle_" + name.getString(), name.getString(),
&samplerSymbols, &symbolsToAPINames);
&samplerSymbols, &symbolsToAPINames, symbolTable);
for (TIntermSymbol *sampler : samplerSymbols)
{
const TType &samplerType = sampler->getType();
......
......@@ -16,6 +16,7 @@
namespace sh
{
class StructureHLSL;
class TSymbolTable;
class UniformHLSL : angle::NonCopyable
{
......@@ -28,7 +29,8 @@ class UniformHLSL : angle::NonCopyable
void reserveUniformBlockRegisters(unsigned int registerCount);
void uniformsHeader(TInfoSinkBase &out,
ShShaderOutput outputType,
const ReferencedSymbols &referencedUniforms);
const ReferencedSymbols &referencedUniforms,
TSymbolTable *symbolTable);
// Must be called after uniformsHeader
void samplerMetadataUniforms(TInfoSinkBase &out, const char *reg);
......
......@@ -12,6 +12,7 @@
#include "compiler/translator/FindMain.h"
#include "compiler/translator/IntermNode_util.h"
#include "compiler/translator/IntermTraverse.h"
#include "compiler/translator/SymbolTable.h"
#include "tests/test_utils/ShaderCompileTreeTest.h"
#include <algorithm>
......@@ -63,7 +64,9 @@ bool AreLValuesTheSame(TIntermTyped *expected, TIntermTyped *candidate)
TIntermTyped *CreateLValueNode(const TString &lValueName, const TType &type)
{
return new TIntermSymbol(0, lValueName, type);
// We're using a dummy symbol table here, don't need to assign proper symbol ids to these nodes.
TSymbolTable symbolTable;
return new TIntermSymbol(symbolTable.nextUniqueId(), lValueName, type);
}
ExpectedLValues CreateIndexedLValueNodeList(const TString &lValueName,
......@@ -73,12 +76,16 @@ ExpectedLValues CreateIndexedLValueNodeList(const TString &lValueName,
ASSERT(elementType.isArray() == false);
elementType.makeArray(arraySize);
// We're using a dummy symbol table here, don't need to assign proper symbol ids to these nodes.
TSymbolTable symbolTable;
TIntermSymbol *arraySymbol =
new TIntermSymbol(symbolTable.nextUniqueId(), lValueName, elementType);
ExpectedLValues expected(arraySize);
for (unsigned index = 0u; index < arraySize; ++index)
{
expected[index] =
new TIntermBinary(EOpIndexDirect, new TIntermSymbol(0, lValueName, elementType),
CreateIndexNode(static_cast<int>(index)));
expected[index] = new TIntermBinary(EOpIndexDirect, arraySymbol->deepCopy(),
CreateIndexNode(static_cast<int>(index)));
}
return expected;
}
......
......@@ -7,11 +7,12 @@
// Unit tests for the AST node classes.
//
#include "compiler/translator/IntermNode.h"
#include "angle_gl.h"
#include "gtest/gtest.h"
#include "compiler/translator/InfoSink.h"
#include "compiler/translator/IntermNode.h"
#include "compiler/translator/PoolAlloc.h"
#include "compiler/translator/SymbolTable.h"
#include "gtest/gtest.h"
using namespace sh;
......@@ -40,7 +41,11 @@ class IntermNodeTest : public testing::Test
TString symbolName = symbolNameOut.c_str();
++mUniqueIndex;
TIntermSymbol *node = new TIntermSymbol(0, symbolName, type);
// We're using a dummy symbol table here, don't need to assign proper symbol ids to these
// nodes.
TSymbolTable symbolTable;
TIntermSymbol *node = new TIntermSymbol(symbolTable.nextUniqueId(), symbolName, type);
node->setLine(createUniqueSourceLoc());
node->setInternal(true);
node->getTypePointer()->setQualifier(EvqTemporary);
......@@ -117,7 +122,11 @@ class IntermNodeTest : public testing::Test
TEST_F(IntermNodeTest, DeepCopySymbolNode)
{
TType type(EbtInt, EbpHigh);
TIntermSymbol *original = new TIntermSymbol(0, TString("name"), type);
// We're using a dummy symbol table here, don't need to assign proper symbol ids to these nodes.
TSymbolTable symbolTable;
TIntermSymbol *original = new TIntermSymbol(symbolTable.nextUniqueId(), TString("name"), type);
original->setLine(getTestSourceLoc());
original->setInternal(true);
TIntermTyped *copy = original->deepCopy();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment