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[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,19 +1050,20 @@ 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()) {
|
||||
error(line, "function name expected", call->getName().c_str(), "");
|
||||
return 0;
|
||||
}
|
||||
|
||||
const TFunction* function = static_cast<const TFunction*>(symbol);
|
||||
const TFunction* function = symbol->getAsFunction();
|
||||
if (! function) {
|
||||
error(line, "function name expected", call->getName().c_str(), "");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
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;
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user