Commit 0f68463f by Olli Etuaho Committed by Commit Bot

Clean up inserting variables to symbol table

This makes the TSymbolTable interface cleaner and prepares for making unique id counting thread-safe. BUG=angleproject:624 TEST=angle_unittests Change-Id: Ief99c9fc777603de28ba1517e351bc8a00633590 Reviewed-on: https://chromium-review.googlesource.com/570418 Commit-Queue: Olli Etuaho <oetuaho@nvidia.com> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarCorentin Wallez <cwallez@chromium.org>
parent daaff1cc
...@@ -32,21 +32,29 @@ namespace ...@@ -32,21 +32,29 @@ namespace
const int kWebGLMaxStructNesting = 4; const int kWebGLMaxStructNesting = 4;
bool ContainsSampler(const TStructure *structType);
bool ContainsSampler(const TType &type) bool ContainsSampler(const TType &type)
{ {
if (IsSampler(type.getBasicType())) if (IsSampler(type.getBasicType()))
{
return true; return true;
}
if (type.getBasicType() == EbtStruct) if (type.getBasicType() == EbtStruct)
{ {
const TFieldList &fields = type.getStruct()->fields(); return ContainsSampler(type.getStruct());
for (unsigned int i = 0; i < fields.size(); ++i) }
return false;
}
bool ContainsSampler(const TStructure *structType)
{
for (const auto &field : structType->fields())
{ {
if (ContainsSampler(*fields[i]->type())) if (ContainsSampler(*field->type()))
return true; return true;
} }
}
return false; return false;
} }
...@@ -802,7 +810,7 @@ bool TParseContext::checkIsNotOpaqueType(const TSourceLoc &line, ...@@ -802,7 +810,7 @@ bool TParseContext::checkIsNotOpaqueType(const TSourceLoc &line,
{ {
if (pType.type == EbtStruct) if (pType.type == EbtStruct)
{ {
if (ContainsSampler(*pType.userDef)) if (ContainsSampler(pType.userDef))
{ {
std::stringstream reasonStream; std::stringstream reasonStream;
reasonStream << reason << " (structure contains a sampler)"; reasonStream << reason << " (structure contains a sampler)";
...@@ -1036,11 +1044,10 @@ bool TParseContext::declareVariable(const TSourceLoc &line, ...@@ -1036,11 +1044,10 @@ bool TParseContext::declareVariable(const TSourceLoc &line,
if (needsReservedCheck && !checkIsNotReserved(line, identifier)) if (needsReservedCheck && !checkIsNotReserved(line, identifier))
return false; return false;
(*variable) = new TVariable(&identifier, type); (*variable) = symbolTable.declareVariable(&identifier, type);
if (!symbolTable.declare(*variable)) if (!(*variable))
{ {
error(line, "redefinition", identifier.c_str()); error(line, "redefinition", identifier.c_str());
*variable = nullptr;
return false; return false;
} }
...@@ -1626,19 +1633,19 @@ const TVariable *TParseContext::getNamedVariable(const TSourceLoc &location, ...@@ -1626,19 +1633,19 @@ const TVariable *TParseContext::getNamedVariable(const TSourceLoc &location,
const TString *name, const TString *name,
const TSymbol *symbol) const TSymbol *symbol)
{ {
const TVariable *variable = nullptr;
if (!symbol) if (!symbol)
{ {
error(location, "undeclared identifier", name->c_str()); error(location, "undeclared identifier", name->c_str());
return nullptr;
} }
else if (!symbol->isVariable())
if (!symbol->isVariable())
{ {
error(location, "variable expected", name->c_str()); error(location, "variable expected", name->c_str());
return nullptr;
} }
else
{ const TVariable *variable = static_cast<const TVariable *>(symbol);
variable = static_cast<const TVariable *>(symbol);
if (symbolTable.findBuiltIn(variable->getName(), mShaderVersion) && if (symbolTable.findBuiltIn(variable->getName(), mShaderVersion) &&
!variable->getExtension().empty()) !variable->getExtension().empty())
...@@ -1685,16 +1692,6 @@ const TVariable *TParseContext::getNamedVariable(const TSourceLoc &location, ...@@ -1685,16 +1692,6 @@ const TVariable *TParseContext::getNamedVariable(const TSourceLoc &location,
"It is an error to use gl_WorkGroupSize before declaring the local group size", "It is an error to use gl_WorkGroupSize before declaring the local group size",
"gl_WorkGroupSize"); "gl_WorkGroupSize");
} }
}
if (!variable)
{
TType type(EbtFloat, EbpUndefined);
TVariable *fakeVariable = new TVariable(name, type);
symbolTable.declare(fakeVariable);
variable = fakeVariable;
}
return variable; return variable;
} }
...@@ -1704,6 +1701,13 @@ TIntermTyped *TParseContext::parseVariableIdentifier(const TSourceLoc &location, ...@@ -1704,6 +1701,13 @@ TIntermTyped *TParseContext::parseVariableIdentifier(const TSourceLoc &location,
{ {
const TVariable *variable = getNamedVariable(location, name, symbol); const TVariable *variable = getNamedVariable(location, name, symbol);
if (!variable)
{
TIntermTyped *node = CreateZeroNode(TType(EbtFloat, EbpHigh, EvqConst));
node->setLine(location);
return node;
}
if (variable->getType().getQualifier() == EvqViewIDOVR && IsWebGLBasedSpec(mShaderSpec) && if (variable->getType().getQualifier() == EvqViewIDOVR && IsWebGLBasedSpec(mShaderSpec) &&
mShaderType == GL_FRAGMENT_SHADER && !isExtensionEnabled("GL_OVR_multiview2")) mShaderType == GL_FRAGMENT_SHADER && !isExtensionEnabled("GL_OVR_multiview2"))
{ {
...@@ -2447,7 +2451,10 @@ TIntermInvariantDeclaration *TParseContext::parseInvariantDeclaration( ...@@ -2447,7 +2451,10 @@ TIntermInvariantDeclaration *TParseContext::parseInvariantDeclaration(
} }
const TVariable *variable = getNamedVariable(identifierLoc, identifier, symbol); const TVariable *variable = getNamedVariable(identifierLoc, identifier, symbol);
ASSERT(variable); if (!variable)
{
return nullptr;
}
const TType &type = variable->getType(); const TType &type = variable->getType();
checkInvariantVariableQualifier(typeQualifier.invariant, type.getQualifier(), checkInvariantVariableQualifier(typeQualifier.invariant, type.getQualifier(),
...@@ -2827,12 +2834,11 @@ TIntermFunctionPrototype *TParseContext::createPrototypeNodeFromFunction( ...@@ -2827,12 +2834,11 @@ TIntermFunctionPrototype *TParseContext::createPrototypeNodeFromFunction(
// be used for unused args). // be used for unused args).
if (param.name != nullptr) if (param.name != nullptr)
{ {
TVariable *variable = new TVariable(param.name, *param.type);
// Insert the parameter in the symbol table. // Insert the parameter in the symbol table.
if (insertParametersToSymbolTable) if (insertParametersToSymbolTable)
{ {
if (symbolTable.declare(variable)) TVariable *variable = symbolTable.declareVariable(param.name, *param.type);
if (variable)
{ {
symbol = new TIntermSymbol(variable->getUniqueId(), variable->getName(), symbol = new TIntermSymbol(variable->getUniqueId(), variable->getName(),
variable->getType()); variable->getType());
...@@ -3259,8 +3265,7 @@ TIntermDeclaration *TParseContext::addInterfaceBlock( ...@@ -3259,8 +3265,7 @@ TIntermDeclaration *TParseContext::addInterfaceBlock(
checkInternalFormatIsNotSpecified(nameLine, blockLayoutQualifier.imageInternalFormat); checkInternalFormatIsNotSpecified(nameLine, blockLayoutQualifier.imageInternalFormat);
TSymbol *blockNameSymbol = new TInterfaceBlockName(&blockName); if (!symbolTable.declareInterfaceBlockName(&blockName))
if (!symbolTable.declare(blockNameSymbol))
{ {
error(nameLine, "redefinition of an interface block name", blockName.c_str()); error(nameLine, "redefinition of an interface block name", blockName.c_str());
} }
...@@ -3370,10 +3375,13 @@ TIntermDeclaration *TParseContext::addInterfaceBlock( ...@@ -3370,10 +3375,13 @@ TIntermDeclaration *TParseContext::addInterfaceBlock(
// set parent pointer of the field variable // set parent pointer of the field variable
fieldType->setInterfaceBlock(interfaceBlock); fieldType->setInterfaceBlock(interfaceBlock);
TVariable *fieldVariable = new TVariable(&field->name(), *fieldType); TVariable *fieldVariable = symbolTable.declareVariable(&field->name(), *fieldType);
fieldVariable->setQualifier(typeQualifier.qualifier);
if (!symbolTable.declare(fieldVariable)) if (fieldVariable)
{
fieldVariable->setQualifier(typeQualifier.qualifier);
}
else
{ {
error(field->line(), "redefinition of an interface block member name", error(field->line(), "redefinition of an interface block member name",
field->name().c_str()); field->name().c_str());
...@@ -3385,17 +3393,18 @@ TIntermDeclaration *TParseContext::addInterfaceBlock( ...@@ -3385,17 +3393,18 @@ TIntermDeclaration *TParseContext::addInterfaceBlock(
checkIsNotReserved(instanceLine, *instanceName); checkIsNotReserved(instanceLine, *instanceName);
// add a symbol for this interface block // add a symbol for this interface block
TVariable *instanceTypeDef = new TVariable(instanceName, interfaceBlockType, false); TVariable *instanceTypeDef = symbolTable.declareVariable(instanceName, interfaceBlockType);
if (instanceTypeDef)
{
instanceTypeDef->setQualifier(typeQualifier.qualifier); instanceTypeDef->setQualifier(typeQualifier.qualifier);
symbolId = instanceTypeDef->getUniqueId();
if (!symbolTable.declare(instanceTypeDef)) }
else
{ {
error(instanceLine, "redefinition of an interface block instance name", error(instanceLine, "redefinition of an interface block instance name",
instanceName->c_str()); instanceName->c_str());
} }
symbolName = *instanceName;
symbolId = instanceTypeDef->getUniqueId();
symbolName = instanceTypeDef->getName();
} }
TIntermSymbol *blockSymbol = new TIntermSymbol(symbolId, symbolName, interfaceBlockType); TIntermSymbol *blockSymbol = new TIntermSymbol(symbolId, symbolName, interfaceBlockType);
...@@ -4120,7 +4129,7 @@ TFieldList *TParseContext::addStructDeclaratorList(const TPublicType &typeSpecif ...@@ -4120,7 +4129,7 @@ TFieldList *TParseContext::addStructDeclaratorList(const TPublicType &typeSpecif
type->setArraySize(static_cast<unsigned int>(typeSpecifier.arraySize)); type->setArraySize(static_cast<unsigned int>(typeSpecifier.arraySize));
if (typeSpecifier.getUserDef()) if (typeSpecifier.getUserDef())
{ {
type->setStruct(typeSpecifier.getUserDef()->getStruct()); type->setStruct(typeSpecifier.getUserDef());
} }
checkIsBelowStructNestingLimit(typeSpecifier.getLine(), *(*fieldList)[i]); checkIsBelowStructNestingLimit(typeSpecifier.getLine(), *(*fieldList)[i]);
...@@ -4135,7 +4144,6 @@ TTypeSpecifierNonArray TParseContext::addStructure(const TSourceLoc &structLine, ...@@ -4135,7 +4144,6 @@ TTypeSpecifierNonArray TParseContext::addStructure(const TSourceLoc &structLine,
TFieldList *fieldList) TFieldList *fieldList)
{ {
TStructure *structure = new TStructure(structName, fieldList); TStructure *structure = new TStructure(structName, fieldList);
TType *structureType = new TType(structure);
// Store a bool in the struct if we're at global scope, to allow us to // Store a bool in the struct if we're at global scope, to allow us to
// skip the local struct scoping workaround in HLSL. // skip the local struct scoping workaround in HLSL.
...@@ -4144,8 +4152,7 @@ TTypeSpecifierNonArray TParseContext::addStructure(const TSourceLoc &structLine, ...@@ -4144,8 +4152,7 @@ TTypeSpecifierNonArray TParseContext::addStructure(const TSourceLoc &structLine,
if (!structName->empty()) if (!structName->empty())
{ {
checkIsNotReserved(nameLine, *structName); checkIsNotReserved(nameLine, *structName);
TVariable *userTypeDef = new TVariable(structName, *structureType, true); if (!symbolTable.declareStructType(structure))
if (!symbolTable.declare(userTypeDef))
{ {
error(nameLine, "redefinition of a struct", structName->c_str()); error(nameLine, "redefinition of a struct", structName->c_str());
} }
...@@ -4184,7 +4191,7 @@ TTypeSpecifierNonArray TParseContext::addStructure(const TSourceLoc &structLine, ...@@ -4184,7 +4191,7 @@ TTypeSpecifierNonArray TParseContext::addStructure(const TSourceLoc &structLine,
} }
TTypeSpecifierNonArray typeSpecifierNonArray; TTypeSpecifierNonArray typeSpecifierNonArray;
typeSpecifierNonArray.initializeStruct(structureType, true, structLine); typeSpecifierNonArray.initializeStruct(structure, true, structLine);
exitStructDeclaration(); exitStructDeclaration();
return typeSpecifierNonArray; return typeSpecifierNonArray;
......
...@@ -3,10 +3,8 @@ ...@@ -3,10 +3,8 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
// //
// Symbol table for parsing. The design principles and most of the functionality are documented in
// // the header file.
// Symbol table for parsing. Most functionaliy and main ideas
// are documented in the header file.
// //
#if defined(_MSC_VER) #if defined(_MSC_VER)
...@@ -271,6 +269,74 @@ const TType *VectorType(const TType *type, int size) ...@@ -271,6 +269,74 @@ const TType *VectorType(const TType *type, int size)
} }
} }
TVariable *TSymbolTable::declareVariable(const TString *name, const TType &type)
{
return insertVariable(currentLevel(), name, type);
}
TVariable *TSymbolTable::declareStructType(TStructure *str)
{
return insertStructType(currentLevel(), str);
}
TInterfaceBlockName *TSymbolTable::declareInterfaceBlockName(const TString *name)
{
TInterfaceBlockName *blockNameSymbol = new TInterfaceBlockName(name);
if (insert(currentLevel(), blockNameSymbol))
{
return blockNameSymbol;
}
return nullptr;
}
TVariable *TSymbolTable::insertVariable(ESymbolLevel level, const char *name, const TType &type)
{
return insertVariable(level, NewPoolTString(name), type);
}
TVariable *TSymbolTable::insertVariable(ESymbolLevel level, const TString *name, const TType &type)
{
TVariable *var = new TVariable(name, type);
if (insert(level, var))
{
// Do lazy initialization for struct types, so we allocate to the current scope.
if (var->getType().getBasicType() == EbtStruct)
{
var->getType().realize();
}
return var;
}
return nullptr;
}
TVariable *TSymbolTable::insertVariableExt(ESymbolLevel level,
const char *ext,
const char *name,
const TType &type)
{
TVariable *var = new TVariable(NewPoolTString(name), type);
if (insert(level, ext, var))
{
if (var->getType().getBasicType() == EbtStruct)
{
var->getType().realize();
}
return var;
}
return nullptr;
}
TVariable *TSymbolTable::insertStructType(ESymbolLevel level, TStructure *str)
{
TVariable *var = new TVariable(&str->name(), TType(str), true);
if (insert(level, var))
{
var->getType().realize();
return var;
}
return nullptr;
}
void TSymbolTable::insertBuiltIn(ESymbolLevel level, void TSymbolTable::insertBuiltIn(ESymbolLevel level,
TOperator op, TOperator op,
const char *ext, const char *ext,
......
...@@ -83,21 +83,12 @@ class TSymbol : angle::NonCopyable ...@@ -83,21 +83,12 @@ class TSymbol : angle::NonCopyable
TString extension; TString extension;
}; };
// Variable class, meaning a symbol that's not a function. // Variable, meaning a symbol that's not a function.
// //
// There could be a separate class heirarchy for Constant variables; // May store the value of a constant variable of any type (float, int, bool or struct).
// Only one of int, bool, or float, (or none) is correct for
// any particular use, but it's easy to do this way, and doesn't
// seem worth having separate classes, and "getConst" can't simply return
// different values for different types polymorphically, so this is
// just simple and pragmatic.
class TVariable : public TSymbol class TVariable : public TSymbol
{ {
public: public:
TVariable(const TString *name, const TType &t, bool uT = false)
: TSymbol(name), type(t), userType(uT), unionArray(0)
{
}
~TVariable() override {} ~TVariable() override {}
bool isVariable() const override { return true; } bool isVariable() const override { return true; }
TType &getType() { return type; } TType &getType() { return type; }
...@@ -110,8 +101,18 @@ class TVariable : public TSymbol ...@@ -110,8 +101,18 @@ class TVariable : public TSymbol
void shareConstPointer(const TConstantUnion *constArray) { unionArray = constArray; } void shareConstPointer(const TConstantUnion *constArray) { unionArray = constArray; }
private: private:
friend class TSymbolTable;
TVariable(const TString *name, const TType &t, bool isUserTypeDefinition = false)
: TSymbol(name), type(t), userType(isUserTypeDefinition), unionArray(0)
{
}
TType type; TType type;
// Set to true if this represents a struct type, as opposed to a variable.
bool userType; bool userType;
// we are assuming that Pool Allocator will free the memory // we are assuming that Pool Allocator will free the memory
// allocated to unionArray when this object is destroyed. // allocated to unionArray when this object is destroyed.
const TConstantUnion *unionArray; const TConstantUnion *unionArray;
...@@ -224,9 +225,11 @@ class TFunction : public TSymbol ...@@ -224,9 +225,11 @@ class TFunction : public TSymbol
class TInterfaceBlockName : public TSymbol class TInterfaceBlockName : public TSymbol
{ {
public: public:
TInterfaceBlockName(const TString *name) : TSymbol(name) {}
virtual ~TInterfaceBlockName() {} virtual ~TInterfaceBlockName() {}
private:
friend class TSymbolTable;
TInterfaceBlockName(const TString *name) : TSymbol(name) {}
}; };
class TSymbolTableLevel class TSymbolTableLevel
...@@ -319,15 +322,22 @@ class TSymbolTable : angle::NonCopyable ...@@ -319,15 +322,22 @@ class TSymbolTable : angle::NonCopyable
precisionStack.pop_back(); precisionStack.pop_back();
} }
bool declare(TSymbol *symbol) { return insert(currentLevel(), symbol); } // The declare* entry points are used when parsing and declare symbols at the current scope.
// They return the created symbol in case the declaration was successful, and nullptr if the
bool insert(ESymbolLevel level, TSymbol *symbol) { return table[level]->insert(symbol); } // declaration failed due to redefinition.
TVariable *declareVariable(const TString *name, const TType &type);
bool insert(ESymbolLevel level, const char *ext, TSymbol *symbol) TVariable *declareStructType(TStructure *str);
{ TInterfaceBlockName *declareInterfaceBlockName(const TString *name);
symbol->relateToExtension(ext);
return table[level]->insert(symbol); // The insert* entry points are used when initializing the symbol table with built-ins.
} // They return the created symbol in case the declaration was successful, and nullptr if the
// declaration failed due to redefinition.
TVariable *insertVariable(ESymbolLevel level, const char *name, const TType &type);
TVariable *insertVariableExt(ESymbolLevel level,
const char *ext,
const char *name,
const TType &type);
TVariable *insertStructType(ESymbolLevel level, TStructure *str);
bool insertConstInt(ESymbolLevel level, const char *name, int value, TPrecision precision) bool insertConstInt(ESymbolLevel level, const char *name, int value, TPrecision precision)
{ {
...@@ -444,8 +454,6 @@ class TSymbolTable : angle::NonCopyable ...@@ -444,8 +454,6 @@ class TSymbolTable : angle::NonCopyable
return table[currentLevel() - 1]; return table[currentLevel() - 1];
} }
void dump(TInfoSink &infoSink) const;
void setDefaultPrecision(TBasicType type, TPrecision prec) void setDefaultPrecision(TBasicType type, TPrecision prec)
{ {
int indexOfLastElement = static_cast<int>(precisionStack.size()) - 1; int indexOfLastElement = static_cast<int>(precisionStack.size()) - 1;
...@@ -488,6 +496,16 @@ class TSymbolTable : angle::NonCopyable ...@@ -488,6 +496,16 @@ class TSymbolTable : angle::NonCopyable
private: private:
ESymbolLevel currentLevel() const { return static_cast<ESymbolLevel>(table.size() - 1); } ESymbolLevel currentLevel() const { return static_cast<ESymbolLevel>(table.size() - 1); }
TVariable *insertVariable(ESymbolLevel level, const TString *name, const TType &type);
bool insert(ESymbolLevel level, TSymbol *symbol) { return table[level]->insert(symbol); }
bool insert(ESymbolLevel level, const char *ext, TSymbol *symbol)
{
symbol->relateToExtension(ext);
return table[level]->insert(symbol);
}
// Used to insert unmangled functions to check redeclaration of built-ins in ESSL 3.00 and // Used to insert unmangled functions to check redeclaration of built-ins in ESSL 3.00 and
// above. // above.
void insertUnmangledBuiltInName(const char *name, ESymbolLevel level); void insertUnmangledBuiltInName(const char *name, ESymbolLevel level);
......
...@@ -130,7 +130,7 @@ TType::TType(const TPublicType &p) ...@@ -130,7 +130,7 @@ TType::TType(const TPublicType &p)
ASSERT(primarySize <= 4); ASSERT(primarySize <= 4);
ASSERT(secondarySize <= 4); ASSERT(secondarySize <= 4);
if (p.getUserDef()) if (p.getUserDef())
structure = p.getUserDef()->getStruct(); structure = p.getUserDef();
} }
bool TStructure::equals(const TStructure &other) const bool TStructure::equals(const TStructure &other) const
......
...@@ -517,7 +517,7 @@ struct TTypeSpecifierNonArray ...@@ -517,7 +517,7 @@ struct TTypeSpecifierNonArray
TBasicType type; TBasicType type;
unsigned char primarySize; // size of vector or cols of matrix unsigned char primarySize; // size of vector or cols of matrix
unsigned char secondarySize; // rows of matrix unsigned char secondarySize; // rows of matrix
TType *userDef; TStructure *userDef;
TSourceLoc line; TSourceLoc line;
// true if the type was defined by a struct specifier rather than a reference to a type name. // true if the type was defined by a struct specifier rather than a reference to a type name.
...@@ -534,7 +534,7 @@ struct TTypeSpecifierNonArray ...@@ -534,7 +534,7 @@ struct TTypeSpecifierNonArray
isStructSpecifier = false; isStructSpecifier = false;
} }
void initializeStruct(TType *aUserDef, bool aIsStructSpecifier, const TSourceLoc &aLine) void initializeStruct(TStructure *aUserDef, bool aIsStructSpecifier, const TSourceLoc &aLine)
{ {
type = EbtStruct; type = EbtStruct;
primarySize = 1; primarySize = 1;
...@@ -610,7 +610,7 @@ struct TPublicType ...@@ -610,7 +610,7 @@ struct TPublicType
unsigned char getPrimarySize() const { return typeSpecifierNonArray.primarySize; } unsigned char getPrimarySize() const { return typeSpecifierNonArray.primarySize; }
unsigned char getSecondarySize() const { return typeSpecifierNonArray.secondarySize; } unsigned char getSecondarySize() const { return typeSpecifierNonArray.secondarySize; }
const TType *getUserDef() const { return typeSpecifierNonArray.userDef; } TStructure *getUserDef() const { return typeSpecifierNonArray.userDef; }
const TSourceLoc &getLine() const { return typeSpecifierNonArray.line; } const TSourceLoc &getLine() const { return typeSpecifierNonArray.line; }
bool isStructSpecifier() const { return typeSpecifierNonArray.isStructSpecifier; } bool isStructSpecifier() const { return typeSpecifierNonArray.isStructSpecifier; }
...@@ -622,7 +622,7 @@ struct TPublicType ...@@ -622,7 +622,7 @@ struct TPublicType
return false; return false;
} }
return typeSpecifierNonArray.userDef->isStructureContainingArrays(); return typeSpecifierNonArray.userDef->containsArrays();
} }
bool isStructureContainingType(TBasicType t) const bool isStructureContainingType(TBasicType t) const
...@@ -632,7 +632,7 @@ struct TPublicType ...@@ -632,7 +632,7 @@ struct TPublicType
return false; return false;
} }
return typeSpecifierNonArray.userDef->isStructureContainingType(t); return typeSpecifierNonArray.userDef->containsType(t);
} }
bool isUnsizedArray() const { return array && arraySize == 0; } bool isUnsizedArray() const { return array && arraySize == 0; }
......
...@@ -1175,7 +1175,7 @@ type_specifier_nonarray ...@@ -1175,7 +1175,7 @@ type_specifier_nonarray
| TYPE_NAME { | TYPE_NAME {
// This is for user defined type names. The lexical phase looked up the type. // This is for user defined type names. The lexical phase looked up the type.
TType& structure = static_cast<TVariable*>($1.symbol)->getType(); TType& structure = static_cast<TVariable*>($1.symbol)->getType();
$$.initializeStruct(&structure, false, @1); $$.initializeStruct(structure.getStruct(), false, @1);
} }
; ;
......
...@@ -4395,7 +4395,7 @@ yyreduce: ...@@ -4395,7 +4395,7 @@ yyreduce:
{ {
// This is for user defined type names. The lexical phase looked up the type. // This is for user defined type names. The lexical phase looked up the type.
TType& structure = static_cast<TVariable*>((yyvsp[0].lex).symbol)->getType(); TType& structure = static_cast<TVariable*>((yyvsp[0].lex).symbol)->getType();
(yyval.interm.typeSpecifierNonArray).initializeStruct(&structure, false, (yylsp[0])); (yyval.interm.typeSpecifierNonArray).initializeStruct(structure.getStruct(), false, (yylsp[0]));
} }
break; break;
......
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