Improve robustness for symbol downcasts by moving to a "getAs" infrastructure and doing more error checking.
git-svn-id: https://cvs.khronos.org/svn/repos/ogl/trunk/ecosystem/public/sdk/tools/glslang@20609 e7fa87d3-cd2b-0410-9028-fcbf551c1848
This commit is contained in:
parent
e25cd0447d
commit
fb5f7eadfa
@ -70,7 +70,7 @@ void TParseContext::setVersion(int newVersion)
|
|||||||
defaultPrecision[EbtFloat] = EpqHigh;
|
defaultPrecision[EbtFloat] = EpqHigh;
|
||||||
defaultPrecision[EbtSampler2D] = EpqLow;
|
defaultPrecision[EbtSampler2D] = EpqLow;
|
||||||
defaultPrecision[EbtSamplerCube] = EpqLow;
|
defaultPrecision[EbtSamplerCube] = EpqLow;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (language == EShLangFragment) {
|
if (language == EShLangFragment) {
|
||||||
defaultPrecision[EbtInt] = EpqMedium;
|
defaultPrecision[EbtInt] = EpqMedium;
|
||||||
@ -728,7 +728,6 @@ bool TParseContext::structQualifierErrorCheck(int line, const TPublicType& pType
|
|||||||
|
|
||||||
void TParseContext::setDefaultPrecision(int line, TBasicType type, TPrecisionQualifier qualifier)
|
void TParseContext::setDefaultPrecision(int line, TBasicType type, TPrecisionQualifier qualifier)
|
||||||
{
|
{
|
||||||
// TODO: push and pop for nested scopes
|
|
||||||
if (IsSampler(type) || type == EbtInt || type == EbtFloat) {
|
if (IsSampler(type) || type == EbtInt || type == EbtFloat) {
|
||||||
defaultPrecision[type] = qualifier;
|
defaultPrecision[type] = qualifier;
|
||||||
} else {
|
} else {
|
||||||
@ -772,7 +771,12 @@ bool TParseContext::insertBuiltInArrayAtGlobalLevel()
|
|||||||
error(0, "INTERNAL ERROR finding symbol", name->c_str(), "");
|
error(0, "INTERNAL ERROR finding symbol", name->c_str(), "");
|
||||||
return true;
|
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());
|
TVariable* newVariable = new TVariable(name, variable->getType());
|
||||||
|
|
||||||
@ -785,8 +789,6 @@ bool TParseContext::insertBuiltInArrayAtGlobalLevel()
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Do size checking for an array type's size.
|
// Do size checking for an array type's size.
|
||||||
//
|
//
|
||||||
@ -877,12 +879,13 @@ bool TParseContext::arrayErrorCheck(int line, TString& identifier, TPublicType t
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (! symbol->isVariable()) {
|
variable = symbol->getAsVariable();
|
||||||
error(line, "variable expected", identifier.c_str(), "");
|
|
||||||
|
if (! variable) {
|
||||||
|
error(line, "array variable name expected", identifier.c_str(), "");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
variable = static_cast<TVariable*>(symbol);
|
|
||||||
if (! variable->getType().isArray()) {
|
if (! variable->getType().isArray()) {
|
||||||
error(line, "redeclaring non-array as array", identifier.c_str(), "");
|
error(line, "redeclaring non-array as array", identifier.c_str(), "");
|
||||||
return true;
|
return true;
|
||||||
@ -924,7 +927,12 @@ bool TParseContext::arraySetMaxSize(TIntermSymbol *node, TType* type, int size,
|
|||||||
error(line, " undeclared identifier", node->getSymbol().c_str(), "");
|
error(line, " undeclared identifier", node->getSymbol().c_str(), "");
|
||||||
return true;
|
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());
|
type->setArrayInformationType(variable->getArrayInformationType());
|
||||||
variable->updateArrayInformationType(type);
|
variable->updateArrayInformationType(type);
|
||||||
@ -933,12 +941,12 @@ bool TParseContext::arraySetMaxSize(TIntermSymbol *node, TType* type, int size,
|
|||||||
// its an error
|
// its an error
|
||||||
if (node->getSymbol() == "gl_TexCoord") {
|
if (node->getSymbol() == "gl_TexCoord") {
|
||||||
TSymbol* texCoord = symbolTable.find("gl_MaxTextureCoords", &builtIn);
|
TSymbol* texCoord = symbolTable.find("gl_MaxTextureCoords", &builtIn);
|
||||||
if (texCoord == 0) {
|
if (! texCoord || ! texCoord->getAsVariable()) {
|
||||||
infoSink.info.message(EPrefixInternalError, "gl_MaxTextureCoords not defined", line);
|
infoSink.info.message(EPrefixInternalError, "gl_MaxTextureCoords not defined", line);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int texCoordValue = static_cast<TVariable*>(texCoord)->getConstPointer()[0].getIConst();
|
int texCoordValue = texCoord->getAsVariable()->getConstUnionPointer()[0].getIConst();
|
||||||
if (texCoordValue <= size) {
|
if (texCoordValue <= size) {
|
||||||
error(line, "", "[", "gl_TexCoord can only have a max array size of up to gl_MaxTextureCoords", "");
|
error(line, "", "[", "gl_TexCoord can only have a max array size of up to gl_MaxTextureCoords", "");
|
||||||
return true;
|
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 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) {
|
if (symbol == 0) {
|
||||||
error(line, "no matching overloaded function found", call->getName().c_str(), "");
|
error(line, "no matching overloaded function found", call->getName().c_str(), "");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (! symbol->isFunction()) {
|
const TFunction* function = symbol->getAsFunction();
|
||||||
|
if (! function) {
|
||||||
error(line, "function name expected", call->getName().c_str(), "");
|
error(line, "function name expected", call->getName().c_str(), "");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const TFunction* function = static_cast<const TFunction*>(symbol);
|
|
||||||
|
|
||||||
return function;
|
return function;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1117,7 +1126,7 @@ bool TParseContext::executeInitializer(TSourceLoc line, TString& identifier, TPu
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (initializer->getAsConstantUnion()) {
|
if (initializer->getAsConstantUnion()) {
|
||||||
constUnion* unionArray = variable->getConstPointer();
|
constUnion* unionArray = variable->getConstUnionPointer();
|
||||||
|
|
||||||
if (type.getObjectSize() == 1 && type.getBasicType() != EbtStruct) {
|
if (type.getObjectSize() == 1 && type.getBasicType() != EbtStruct) {
|
||||||
*unionArray = (initializer->getAsConstantUnion()->getUnionArrayPointer())[0];
|
*unionArray = (initializer->getAsConstantUnion()->getUnionArrayPointer())[0];
|
||||||
@ -1125,11 +1134,14 @@ bool TParseContext::executeInitializer(TSourceLoc line, TString& identifier, TPu
|
|||||||
variable->shareConstPointer(initializer->getAsConstantUnion()->getUnionArrayPointer());
|
variable->shareConstPointer(initializer->getAsConstantUnion()->getUnionArrayPointer());
|
||||||
}
|
}
|
||||||
} else if (initializer->getAsSymbolNode()) {
|
} else if (initializer->getAsSymbolNode()) {
|
||||||
const TSymbol* symbol = symbolTable.find(initializer->getAsSymbolNode()->getSymbol());
|
TSymbol* symbol = symbolTable.find(initializer->getAsSymbolNode()->getSymbol());
|
||||||
const TVariable* tVar = static_cast<const TVariable*>(symbol);
|
if (TVariable* tVar = symbol->getAsVariable()) {
|
||||||
|
constUnion* constArray = tVar->getConstUnionPointer();
|
||||||
constUnion* constArray = tVar->getConstPointer();
|
|
||||||
variable->shareConstPointer(constArray);
|
variable->shareConstPointer(constArray);
|
||||||
|
} else {
|
||||||
|
error(line, "expected variable", initializer->getAsSymbolNode()->getSymbol().c_str(), "");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
error(line, " cannot assign to", "=", "'%s'", variable->getType().getCompleteString().c_str());
|
error(line, " cannot assign to", "=", "'%s'", variable->getType().getCompleteString().c_str());
|
||||||
variable->getType().getQualifier().storage = EvqTemporary;
|
variable->getType().getQualifier().storage = EvqTemporary;
|
||||||
|
@ -174,15 +174,14 @@ void TSymbolTableLevel::relateToOperator(const char* name, TOperator op)
|
|||||||
{
|
{
|
||||||
tLevel::iterator it;
|
tLevel::iterator it;
|
||||||
for (it = level.begin(); it != level.end(); ++it) {
|
for (it = level.begin(); it != level.end(); ++it) {
|
||||||
if ((*it).second->isFunction()) {
|
TFunction* function = (*it).second->getAsFunction();
|
||||||
TFunction* function = static_cast<TFunction*>((*it).second);
|
if (function) {
|
||||||
if (function->getName() == name)
|
if (function->getName() == name)
|
||||||
function->relateToOperator(op);
|
function->relateToOperator(op);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
TSymbol::TSymbol(const TSymbol& copyOf)
|
TSymbol::TSymbol(const TSymbol& copyOf)
|
||||||
{
|
{
|
||||||
name = NewPoolTString(copyOf.name->c_str());
|
name = NewPoolTString(copyOf.name->c_str());
|
||||||
|
@ -65,6 +65,8 @@
|
|||||||
//
|
//
|
||||||
// Symbol base class. (Can build functions or variables out of these...)
|
// Symbol base class. (Can build functions or variables out of these...)
|
||||||
//
|
//
|
||||||
|
class TVariable;
|
||||||
|
class TFunction;
|
||||||
class TSymbol {
|
class TSymbol {
|
||||||
public:
|
public:
|
||||||
POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator)
|
POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator)
|
||||||
@ -72,8 +74,8 @@ public:
|
|||||||
virtual ~TSymbol() { /* don't delete name, it's from the pool */ }
|
virtual ~TSymbol() { /* don't delete name, it's from the pool */ }
|
||||||
const TString& getName() const { return *name; }
|
const TString& getName() const { return *name; }
|
||||||
virtual const TString& getMangledName() const { return getName(); }
|
virtual const TString& getMangledName() const { return getName(); }
|
||||||
virtual bool isFunction() const { return false; }
|
virtual TFunction* getAsFunction() { return 0; }
|
||||||
virtual bool isVariable() const { return false; }
|
virtual TVariable* getAsVariable() { return 0; }
|
||||||
void setUniqueId(int id) { uniqueId = id; }
|
void setUniqueId(int id) { uniqueId = id; }
|
||||||
int getUniqueId() const { return uniqueId; }
|
int getUniqueId() const { return uniqueId; }
|
||||||
virtual void dump(TInfoSink &infoSink) const = 0;
|
virtual void dump(TInfoSink &infoSink) const = 0;
|
||||||
@ -99,7 +101,7 @@ class TVariable : public TSymbol {
|
|||||||
public:
|
public:
|
||||||
TVariable(const TString *name, const TType& t, bool uT = false ) : TSymbol(name), type(t), userType(uT), unionArray(0), arrayInformationType(0) { }
|
TVariable(const TString *name, const TType& t, bool uT = false ) : TSymbol(name), type(t), userType(uT), unionArray(0), arrayInformationType(0) { }
|
||||||
virtual ~TVariable() { }
|
virtual ~TVariable() { }
|
||||||
virtual bool isVariable() const { return true; }
|
virtual TVariable* getAsVariable() { return this; }
|
||||||
TType& getType() { return type; }
|
TType& getType() { return type; }
|
||||||
const TType& getType() const { return type; }
|
const TType& getType() const { return type; }
|
||||||
bool isUserType() const { return userType; }
|
bool isUserType() const { return userType; }
|
||||||
@ -109,14 +111,14 @@ public:
|
|||||||
|
|
||||||
virtual void dump(TInfoSink &infoSink) const;
|
virtual void dump(TInfoSink &infoSink) const;
|
||||||
|
|
||||||
constUnion* getConstPointer() {
|
constUnion* getConstUnionPointer() {
|
||||||
if (!unionArray)
|
if (!unionArray)
|
||||||
unionArray = new constUnion[type.getObjectSize()];
|
unionArray = new constUnion[type.getObjectSize()];
|
||||||
|
|
||||||
return unionArray;
|
return unionArray;
|
||||||
}
|
}
|
||||||
|
|
||||||
constUnion* getConstPointer() const { return unionArray; }
|
constUnion* getConstUnionPointer() const { return unionArray; }
|
||||||
|
|
||||||
void shareConstPointer( constUnion *constArray)
|
void shareConstPointer( constUnion *constArray)
|
||||||
{
|
{
|
||||||
@ -166,7 +168,7 @@ public:
|
|||||||
defined(false) { }
|
defined(false) { }
|
||||||
TFunction(const TFunction&, const TStructureMap& remapper);
|
TFunction(const TFunction&, const TStructureMap& remapper);
|
||||||
virtual ~TFunction();
|
virtual ~TFunction();
|
||||||
virtual bool isFunction() const { return true; }
|
virtual TFunction* getAsFunction() { return this; }
|
||||||
|
|
||||||
void addParameter(TParameter& p)
|
void addParameter(TParameter& p)
|
||||||
{
|
{
|
||||||
|
@ -541,13 +541,14 @@ int PaReservedWord()
|
|||||||
int PaIdentOrType(TString& id, TParseContext& parseContextLocal, TSymbol*& symbol)
|
int PaIdentOrType(TString& id, TParseContext& parseContextLocal, TSymbol*& symbol)
|
||||||
{
|
{
|
||||||
symbol = parseContextLocal.symbolTable.find(id);
|
symbol = parseContextLocal.symbolTable.find(id);
|
||||||
if (parseContextLocal.lexAfterType == false && symbol && symbol->isVariable()) {
|
if (parseContextLocal.lexAfterType == false && symbol) {
|
||||||
TVariable* variable = static_cast<TVariable*>(symbol);
|
if (TVariable* variable = symbol->getAsVariable()) {
|
||||||
if (variable->isUserType()) {
|
if (variable->isUserType()) {
|
||||||
parseContextLocal.lexAfterType = true;
|
parseContextLocal.lexAfterType = true;
|
||||||
return TYPE_NAME;
|
return TYPE_NAME;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return IDENTIFIER;
|
return IDENTIFIER;
|
||||||
}
|
}
|
||||||
|
@ -217,26 +217,24 @@ Jutta Degener, 1995
|
|||||||
|
|
||||||
variable_identifier
|
variable_identifier
|
||||||
: IDENTIFIER {
|
: IDENTIFIER {
|
||||||
// The symbol table search was done in the lexical phase
|
// The symbol table search was done in the lexical phase, but
|
||||||
const TSymbol* symbol = $1.symbol;
|
// if this is a new symbol, it won't find it, which is okay at this
|
||||||
const TVariable* variable;
|
// point in the grammar.
|
||||||
if (symbol == 0) {
|
TSymbol* symbol = $1.symbol;
|
||||||
TVariable* fakeVariable = new TVariable($1.string, TType(EbtVoid));
|
const TVariable* variable = symbol ? symbol->getAsVariable() : 0;
|
||||||
variable = fakeVariable;
|
if (symbol && ! variable) {
|
||||||
} else {
|
parseContext.error($1.line, "variable name expected", $1.string->c_str(), "");
|
||||||
// This identifier can only be a variable type symbol
|
|
||||||
if (! symbol->isVariable()) {
|
|
||||||
parseContext.error($1.line, "variable expected", $1.string->c_str(), "");
|
|
||||||
parseContext.recover();
|
parseContext.recover();
|
||||||
}
|
}
|
||||||
variable = static_cast<const TVariable*>(symbol);
|
|
||||||
}
|
if (! variable)
|
||||||
|
variable = new TVariable($1.string, TType(EbtVoid));
|
||||||
|
|
||||||
// don't delete $1.string, it's used by error recovery, and the pool
|
// don't delete $1.string, it's used by error recovery, and the pool
|
||||||
// pop will reclaim the memory
|
// pop will reclaim the memory
|
||||||
|
|
||||||
if (variable->getType().getQualifier().storage == EvqConst ) {
|
if (variable->getType().getQualifier().storage == EvqConst ) {
|
||||||
constUnion* constArray = variable->getConstPointer();
|
constUnion* constArray = variable->getConstUnionPointer();
|
||||||
TType t(variable->getType());
|
TType t(variable->getType());
|
||||||
$$ = parseContext.intermediate.addConstantUnion(constArray, t, $1.line);
|
$$ = parseContext.intermediate.addConstantUnion(constArray, t, $1.line);
|
||||||
} else
|
} else
|
||||||
@ -1201,7 +1199,8 @@ function_prototype
|
|||||||
//
|
//
|
||||||
// Redeclarations are allowed. But, return types and parameter qualifiers must match.
|
// 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) {
|
||||||
if (prevDec->getReturnType() != $1->getReturnType()) {
|
if (prevDec->getReturnType() != $1->getReturnType()) {
|
||||||
parseContext.error($2.line, "overloaded functions must have the same return type", $1->getReturnType().getBasicString(), "");
|
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
|
// This is for user defined type names. The lexical phase looked up the
|
||||||
// type.
|
// type.
|
||||||
//
|
//
|
||||||
const TType& structure = static_cast<const TVariable*>($1.symbol)->getType();
|
if (TVariable* variable = ($1.symbol)->getAsVariable()) {
|
||||||
|
const TType& structure = variable->getType();
|
||||||
$$.init($1.line, parseContext.symbolTable.atGlobalLevel());
|
$$.init($1.line, parseContext.symbolTable.atGlobalLevel());
|
||||||
$$.type = EbtStruct;
|
$$.type = EbtStruct;
|
||||||
$$.userDef = &structure;
|
$$.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_definition
|
||||||
: function_prototype {
|
: function_prototype {
|
||||||
TFunction& function = *($1.function);
|
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
|
// 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
|
// as it would have just been put in the symbol table. Otherwise, we're looking up
|
||||||
// an earlier occurance.
|
// an earlier occurance.
|
||||||
//
|
//
|
||||||
if (prevDec->isDefined()) {
|
if (prevDec && prevDec->isDefined()) {
|
||||||
//
|
//
|
||||||
// Then this function already has a body.
|
// Then this function already has a body.
|
||||||
//
|
//
|
||||||
parseContext.error($1.line, "function already has a body", function.getName().c_str(), "");
|
parseContext.error($1.line, "function already has a body", function.getName().c_str(), "");
|
||||||
parseContext.recover();
|
parseContext.recover();
|
||||||
}
|
}
|
||||||
|
if (prevDec) {
|
||||||
prevDec->setDefined();
|
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
|
// Raise error message if main function takes any parameters or return anything other than void
|
||||||
@ -2910,12 +2929,6 @@ function_definition
|
|||||||
//
|
//
|
||||||
parseContext.symbolTable.push();
|
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.
|
// Insert parameters into the symbol table.
|
||||||
// If the parameter has no name, it's not an error, just don't insert it
|
// If the parameter has no name, it's not an error, just don't insert it
|
||||||
|
Loading…
x
Reference in New Issue
Block a user