diff --git a/glslang/MachineIndependent/ParseHelper.cpp b/glslang/MachineIndependent/ParseHelper.cpp index 9ead5dcabaa26f6e907f36a645ac2e1dc02adbff..3b0bc4e34267ef75a606354af10976b490451ead 100644 --- a/glslang/MachineIndependent/ParseHelper.cpp +++ b/glslang/MachineIndependent/ParseHelper.cpp @@ -70,7 +70,7 @@ void TParseContext::setVersion(int newVersion) defaultPrecision[EbtFloat] = EpqHigh; defaultPrecision[EbtSampler2D] = EpqLow; defaultPrecision[EbtSamplerCube] = EpqLow; - } +} if (language == EShLangFragment) { defaultPrecision[EbtInt] = EpqMedium; @@ -728,7 +728,6 @@ bool TParseContext::structQualifierErrorCheck(int line, const TPublicType& pType void TParseContext::setDefaultPrecision(int line, TBasicType type, TPrecisionQualifier qualifier) { - // TODO: push and pop for nested scopes if (IsSampler(type) || type == EbtInt || type == EbtFloat) { defaultPrecision[type] = qualifier; } else { @@ -772,7 +771,12 @@ bool TParseContext::insertBuiltInArrayAtGlobalLevel() error(0, "INTERNAL ERROR finding symbol", name->c_str(), ""); return true; } - TVariable* variable = static_cast<TVariable*>(symbol); + TVariable* variable = symbol->getAsVariable(); + + if (! variable) { + error(0, "INTERNAL ERROR, variable expected", name->c_str(), ""); + return true; + } TVariable* newVariable = new TVariable(name, variable->getType()); @@ -785,8 +789,6 @@ bool TParseContext::insertBuiltInArrayAtGlobalLevel() return false; } - - // // Do size checking for an array type's size. // @@ -877,12 +879,13 @@ bool TParseContext::arrayErrorCheck(int line, TString& identifier, TPublicType t return true; } } else { - if (! symbol->isVariable()) { - error(line, "variable expected", identifier.c_str(), ""); + variable = symbol->getAsVariable(); + + if (! variable) { + error(line, "array variable name expected", identifier.c_str(), ""); return true; } - variable = static_cast<TVariable*>(symbol); if (! variable->getType().isArray()) { error(line, "redeclaring non-array as array", identifier.c_str(), ""); return true; @@ -924,7 +927,12 @@ bool TParseContext::arraySetMaxSize(TIntermSymbol *node, TType* type, int size, error(line, " undeclared identifier", node->getSymbol().c_str(), ""); return true; } - TVariable* variable = static_cast<TVariable*>(symbol); + + TVariable* variable = symbol->getAsVariable(); + if (! variable) { + error(0, "array variable name expected", node->getSymbol().c_str(), ""); + return true; + } type->setArrayInformationType(variable->getArrayInformationType()); variable->updateArrayInformationType(type); @@ -933,12 +941,12 @@ bool TParseContext::arraySetMaxSize(TIntermSymbol *node, TType* type, int size, // its an error if (node->getSymbol() == "gl_TexCoord") { TSymbol* texCoord = symbolTable.find("gl_MaxTextureCoords", &builtIn); - if (texCoord == 0) { + if (! texCoord || ! texCoord->getAsVariable()) { infoSink.info.message(EPrefixInternalError, "gl_MaxTextureCoords not defined", line); return true; } - int texCoordValue = static_cast<TVariable*>(texCoord)->getConstPointer()[0].getIConst(); + int texCoordValue = texCoord->getAsVariable()->getConstUnionPointer()[0].getIConst(); if (texCoordValue <= size) { error(line, "", "[", "gl_TexCoord can only have a max array size of up to gl_MaxTextureCoords", ""); return true; @@ -1042,20 +1050,21 @@ bool TParseContext::paramErrorCheck(int line, TStorageQualifier qualifier, TType // const TFunction* TParseContext::findFunction(int line, TFunction* call, bool *builtIn) { - const TSymbol* symbol = symbolTable.find(call->getMangledName(), builtIn); + TSymbol* symbol = symbolTable.find(call->getMangledName(), builtIn); if (symbol == 0) { error(line, "no matching overloaded function found", call->getName().c_str(), ""); + return 0; } - - if (! symbol->isFunction()) { + + const TFunction* function = symbol->getAsFunction(); + if (! function) { error(line, "function name expected", call->getName().c_str(), ""); + return 0; } - const TFunction* function = static_cast<const TFunction*>(symbol); - return function; } @@ -1117,7 +1126,7 @@ bool TParseContext::executeInitializer(TSourceLoc line, TString& identifier, TPu return true; } if (initializer->getAsConstantUnion()) { - constUnion* unionArray = variable->getConstPointer(); + constUnion* unionArray = variable->getConstUnionPointer(); if (type.getObjectSize() == 1 && type.getBasicType() != EbtStruct) { *unionArray = (initializer->getAsConstantUnion()->getUnionArrayPointer())[0]; @@ -1125,11 +1134,14 @@ bool TParseContext::executeInitializer(TSourceLoc line, TString& identifier, TPu variable->shareConstPointer(initializer->getAsConstantUnion()->getUnionArrayPointer()); } } else if (initializer->getAsSymbolNode()) { - const TSymbol* symbol = symbolTable.find(initializer->getAsSymbolNode()->getSymbol()); - const TVariable* tVar = static_cast<const TVariable*>(symbol); - - constUnion* constArray = tVar->getConstPointer(); - variable->shareConstPointer(constArray); + TSymbol* symbol = symbolTable.find(initializer->getAsSymbolNode()->getSymbol()); + if (TVariable* tVar = symbol->getAsVariable()) { + constUnion* constArray = tVar->getConstUnionPointer(); + variable->shareConstPointer(constArray); + } else { + error(line, "expected variable", initializer->getAsSymbolNode()->getSymbol().c_str(), ""); + return true; + } } else { error(line, " cannot assign to", "=", "'%s'", variable->getType().getCompleteString().c_str()); variable->getType().getQualifier().storage = EvqTemporary; diff --git a/glslang/MachineIndependent/SymbolTable.cpp b/glslang/MachineIndependent/SymbolTable.cpp index 280881faf874569fcfcfe3a6b5dd1174aba08295..6e731c6d7e87e83d4c6c9820bf246f61ea4b8395 100644 --- a/glslang/MachineIndependent/SymbolTable.cpp +++ b/glslang/MachineIndependent/SymbolTable.cpp @@ -35,7 +35,7 @@ // // -// Symbol table for parsing. Most functionaliy and main ideas +// Symbol table for parsing. Most functionaliy and main ideas // are documented in the header file. // @@ -76,7 +76,7 @@ void TType::buildMangledName(TString& mangledName) mangledName += '-'; (*structure)[i].type->buildMangledName(mangledName); } - default: + default: break; } @@ -98,7 +98,7 @@ void TType::buildMangledName(TString& mangledName) } int TType::getStructSize() const -{ +{ if (!getStruct()) { assert(false && "Not a struct"); return 0; @@ -107,7 +107,7 @@ int TType::getStructSize() const if (structureSize == 0) for (TTypeList::iterator tl = getStruct()->begin(); tl != getStruct()->end(); tl++) structureSize += ((*tl).type)->getObjectSize(); - + return structureSize; } @@ -115,7 +115,7 @@ int TType::getStructSize() const // Dump functions. // -void TVariable::dump(TInfoSink& infoSink) const +void TVariable::dump(TInfoSink& infoSink) const { infoSink.debug << getName().c_str() << ": " << type.getStorageQualifierString() << " " << type.getBasicString(); if (type.isArray()) { @@ -129,7 +129,7 @@ void TFunction::dump(TInfoSink &infoSink) const infoSink.debug << getName().c_str() << ": " << returnType.getBasicString() << " " << getMangledName().c_str() << "\n"; } -void TSymbolTableLevel::dump(TInfoSink &infoSink) const +void TSymbolTableLevel::dump(TInfoSink &infoSink) const { tLevel::const_iterator it; for (it = level.begin(); it != level.end(); ++it) @@ -170,18 +170,17 @@ TSymbolTableLevel::~TSymbolTableLevel() // performance operation, and only intended for symbol tables that // live across a large number of compiles. // -void TSymbolTableLevel::relateToOperator(const char* name, TOperator op) +void TSymbolTableLevel::relateToOperator(const char* name, TOperator op) { tLevel::iterator it; for (it = level.begin(); it != level.end(); ++it) { - if ((*it).second->isFunction()) { - TFunction* function = static_cast<TFunction*>((*it).second); + TFunction* function = (*it).second->getAsFunction(); + if (function) { if (function->getName() == name) function->relateToOperator(op); } } -} - +} TSymbol::TSymbol(const TSymbol& copyOf) { @@ -194,11 +193,11 @@ TVariable::TVariable(const TVariable& copyOf, TStructureMap& remapper) : TSymbol type.copyType(copyOf.type, remapper); userType = copyOf.userType; // for builtIn symbol table level, unionArray and arrayInformation pointers should be NULL - assert(copyOf.arrayInformationType == 0); + assert(copyOf.arrayInformationType == 0); arrayInformationType = 0; if (copyOf.unionArray) { - assert(!copyOf.type.getStruct()); + assert(!copyOf.type.getStruct()); assert(copyOf.type.getObjectSize() == 1); unionArray = new constUnion[1]; unionArray[0] = copyOf.unionArray[0]; @@ -206,7 +205,7 @@ TVariable::TVariable(const TVariable& copyOf, TStructureMap& remapper) : TSymbol unionArray = 0; } -TVariable* TVariable::clone(TStructureMap& remapper) +TVariable* TVariable::clone(TStructureMap& remapper) { TVariable *variable = new TVariable(*this, remapper); @@ -227,7 +226,7 @@ TFunction::TFunction(const TFunction& copyOf, const TStructureMap& remapper) : T defined = copyOf.defined; } -TFunction* TFunction::clone(TStructureMap& remapper) +TFunction* TFunction::clone(TStructureMap& remapper) { TFunction *function = new TFunction(*this, remapper); diff --git a/glslang/MachineIndependent/SymbolTable.h b/glslang/MachineIndependent/SymbolTable.h index efad7b41be3abb381b4aa4e05838ba994da09c17..de956a59ce694d42564d7ec1c7a131c1ed5f22a0 100644 --- a/glslang/MachineIndependent/SymbolTable.h +++ b/glslang/MachineIndependent/SymbolTable.h @@ -65,6 +65,8 @@ // // Symbol base class. (Can build functions or variables out of these...) // +class TVariable; +class TFunction; class TSymbol { public: POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator) @@ -72,8 +74,8 @@ public: virtual ~TSymbol() { /* don't delete name, it's from the pool */ } const TString& getName() const { return *name; } virtual const TString& getMangledName() const { return getName(); } - virtual bool isFunction() const { return false; } - virtual bool isVariable() const { return false; } + virtual TFunction* getAsFunction() { return 0; } + virtual TVariable* getAsVariable() { return 0; } void setUniqueId(int id) { uniqueId = id; } int getUniqueId() const { return uniqueId; } virtual void dump(TInfoSink &infoSink) const = 0; @@ -99,7 +101,7 @@ class TVariable : public TSymbol { public: TVariable(const TString *name, const TType& t, bool uT = false ) : TSymbol(name), type(t), userType(uT), unionArray(0), arrayInformationType(0) { } virtual ~TVariable() { } - virtual bool isVariable() const { return true; } + virtual TVariable* getAsVariable() { return this; } TType& getType() { return type; } const TType& getType() const { return type; } bool isUserType() const { return userType; } @@ -109,14 +111,14 @@ public: virtual void dump(TInfoSink &infoSink) const; - constUnion* getConstPointer() { + constUnion* getConstUnionPointer() { if (!unionArray) unionArray = new constUnion[type.getObjectSize()]; return unionArray; } - constUnion* getConstPointer() const { return unionArray; } + constUnion* getConstUnionPointer() const { return unionArray; } void shareConstPointer( constUnion *constArray) { @@ -166,7 +168,7 @@ public: defined(false) { } TFunction(const TFunction&, const TStructureMap& remapper); virtual ~TFunction(); - virtual bool isFunction() const { return true; } + virtual TFunction* getAsFunction() { return this; } void addParameter(TParameter& p) { diff --git a/glslang/MachineIndependent/glslang.l b/glslang/MachineIndependent/glslang.l index 351e29f06867402d8f51a5fb004e427dd2106616..8efe677707c026850680aacda0e43269b5d7b9f9 100644 --- a/glslang/MachineIndependent/glslang.l +++ b/glslang/MachineIndependent/glslang.l @@ -541,11 +541,12 @@ int PaReservedWord() int PaIdentOrType(TString& id, TParseContext& parseContextLocal, TSymbol*& symbol) { symbol = parseContextLocal.symbolTable.find(id); - if (parseContextLocal.lexAfterType == false && symbol && symbol->isVariable()) { - TVariable* variable = static_cast<TVariable*>(symbol); - if (variable->isUserType()) { - parseContextLocal.lexAfterType = true; - return TYPE_NAME; + if (parseContextLocal.lexAfterType == false && symbol) { + if (TVariable* variable = symbol->getAsVariable()) { + if (variable->isUserType()) { + parseContextLocal.lexAfterType = true; + return TYPE_NAME; + } } } diff --git a/glslang/MachineIndependent/glslang.y b/glslang/MachineIndependent/glslang.y index 8d3a47f18ad6e5c61ae54bc4776ca3cbbf105517..ecc856b8ac499513e4e1bd5713f54e3f51f9f83d 100644 --- a/glslang/MachineIndependent/glslang.y +++ b/glslang/MachineIndependent/glslang.y @@ -217,26 +217,24 @@ Jutta Degener, 1995 variable_identifier : IDENTIFIER { - // The symbol table search was done in the lexical phase - const TSymbol* symbol = $1.symbol; - const TVariable* variable; - if (symbol == 0) { - TVariable* fakeVariable = new TVariable($1.string, TType(EbtVoid)); - variable = fakeVariable; - } else { - // This identifier can only be a variable type symbol - if (! symbol->isVariable()) { - parseContext.error($1.line, "variable expected", $1.string->c_str(), ""); - parseContext.recover(); - } - variable = static_cast<const TVariable*>(symbol); + // The symbol table search was done in the lexical phase, but + // if this is a new symbol, it won't find it, which is okay at this + // point in the grammar. + TSymbol* symbol = $1.symbol; + const TVariable* variable = symbol ? symbol->getAsVariable() : 0; + if (symbol && ! variable) { + parseContext.error($1.line, "variable name expected", $1.string->c_str(), ""); + parseContext.recover(); } + if (! variable) + variable = new TVariable($1.string, TType(EbtVoid)); + // don't delete $1.string, it's used by error recovery, and the pool // pop will reclaim the memory if (variable->getType().getQualifier().storage == EvqConst ) { - constUnion* constArray = variable->getConstPointer(); + constUnion* constArray = variable->getConstUnionPointer(); TType t(variable->getType()); $$ = parseContext.intermediate.addConstantUnion(constArray, t, $1.line); } else @@ -1201,7 +1199,8 @@ function_prototype // // Redeclarations are allowed. But, return types and parameter qualifiers must match. // - TFunction* prevDec = static_cast<TFunction*>(parseContext.symbolTable.find($1->getMangledName())); + TSymbol* symbol = parseContext.symbolTable.find($1->getMangledName()); + TFunction* prevDec = symbol ? symbol->getAsFunction() : 0; if (prevDec) { if (prevDec->getReturnType() != $1->getReturnType()) { parseContext.error($2.line, "overloaded functions must have the same return type", $1->getReturnType().getBasicString(), ""); @@ -2460,10 +2459,15 @@ type_specifier_nonarray // This is for user defined type names. The lexical phase looked up the // type. // - const TType& structure = static_cast<const TVariable*>($1.symbol)->getType(); - $$.init($1.line, parseContext.symbolTable.atGlobalLevel()); - $$.type = EbtStruct; - $$.userDef = &structure; + if (TVariable* variable = ($1.symbol)->getAsVariable()) { + const TType& structure = variable->getType(); + $$.init($1.line, parseContext.symbolTable.atGlobalLevel()); + $$.type = EbtStruct; + $$.userDef = &structure; + } else { + parseContext.error($1.line, "expected type name", $1.string->c_str(), ""); + parseContext.recover(); + } } ; @@ -2876,20 +2880,35 @@ external_declaration function_definition : function_prototype { TFunction& function = *($1.function); - TFunction* prevDec = static_cast<TFunction*>(parseContext.symbolTable.find(function.getMangledName())); + TSymbol* symbol = parseContext.symbolTable.find(function.getMangledName()); + TFunction* prevDec = symbol ? symbol->getAsFunction() : 0; + + if (! prevDec) { + parseContext.error($1.line, "can't find function name", function.getName().c_str(), ""); + parseContext.recover(); + } + // // Note: 'prevDec' could be 'function' if this is the first time we've seen function // as it would have just been put in the symbol table. Otherwise, we're looking up // an earlier occurance. // - if (prevDec->isDefined()) { + if (prevDec && prevDec->isDefined()) { // // Then this function already has a body. // parseContext.error($1.line, "function already has a body", function.getName().c_str(), ""); parseContext.recover(); } - prevDec->setDefined(); + if (prevDec) { + prevDec->setDefined(); + // + // Remember the return type for later checking for RETURN statements. + // + parseContext.currentFunctionType = &(prevDec->getReturnType()); + } else + parseContext.currentFunctionType = new TType(EbtVoid); + parseContext.functionReturnsValue = false; // // Raise error message if main function takes any parameters or return anything other than void @@ -2910,12 +2929,6 @@ function_definition // parseContext.symbolTable.push(); - // - // Remember the return type for later checking for RETURN statements. - // - parseContext.currentFunctionType = &(prevDec->getReturnType()); - parseContext.functionReturnsValue = false; - // // Insert parameters into the symbol table. // If the parameter has no name, it's not an error, just don't insert it