// Parse shader.
bool success =
(PaParseStrings(numStrings - firstSource, &shaderStrings[firstSource], NULL, &parseContext) == 0) &&
- (parseContext.treeRoot != NULL);
+ (parseContext.getTreeRoot() != NULL);
shaderVersion = parseContext.getShaderVersion();
if (success) {
- TIntermNode* root = parseContext.treeRoot;
+ TIntermNode* root = parseContext.getTreeRoot();
success = intermediate.postProcess(root);
if (success)
bool InitializeParseContextIndex();
void FreeParseContextIndex();
-struct TParseContext;
+class TParseContext;
extern void SetGlobalParseContext(TParseContext* context);
extern TParseContext* GetGlobalParseContext();
{\r
emitScope = scope;\r
currentScope = GLOBAL;\r
- mContext.treeRoot->traverse(this);\r
+ mContext.getTreeRoot()->traverse(this);\r
}\r
\r
void OutputASM::freeTemporary(Temporary *temporary)\r
{
pp::SourceLocation srcLoc;
DecodeSourceLoc(loc, &srcLoc.file, &srcLoc.line);
- diagnostics.writeInfo(pp::Diagnostics::PP_ERROR,
- srcLoc, reason, token, extraInfo);
+ mDiagnostics.writeInfo(pp::Diagnostics::PP_ERROR,
+ srcLoc, reason, token, extraInfo);
}
const char* extraInfo) {
pp::SourceLocation srcLoc;
DecodeSourceLoc(loc, &srcLoc.file, &srcLoc.line);
- diagnostics.writeInfo(pp::Diagnostics::PP_WARNING,
- srcLoc, reason, token, extraInfo);
+ mDiagnostics.writeInfo(pp::Diagnostics::PP_WARNING,
+ srcLoc, reason, token, extraInfo);
}
void TParseContext::trace(const char* str)
{
- diagnostics.writeDebug(str);
+ mDiagnostics.writeDebug(str);
}
//
}
bool TParseContext::precisionErrorCheck(const TSourceLoc &line, TPrecision precision, TBasicType type){
- if (!checksPrecisionErrors)
+ if (!mChecksPrecisionErrors)
return false;
switch( type ){
case EbtFloat:
bool TParseContext::arraySetMaxSize(TIntermSymbol *node, TType* type, int size, bool updateFlag, const TSourceLoc &line)
{
bool builtIn = false;
- TSymbol* symbol = symbolTable.find(node->getSymbol(), shaderVersion, &builtIn);
+ TSymbol* symbol = symbolTable.find(node->getSymbol(), mShaderVersion, &builtIn);
if (symbol == 0) {
error(line, " undeclared identifier", node->getSymbol().c_str());
return true;
// special casing to test index value of gl_FragData. If the accessed index is >= gl_MaxDrawBuffers
// its an error
if (node->getSymbol() == "gl_FragData") {
- TSymbol* fragData = symbolTable.find("gl_MaxDrawBuffers", shaderVersion, &builtIn);
+ TSymbol* fragData = symbolTable.find("gl_MaxDrawBuffers", mShaderVersion, &builtIn);
ASSERT(fragData);
int fragDataValue = static_cast<TVariable*>(fragData)->getConstPointer()[0].getIConst();
// Generate informative error messages for ESSL1.
// In ESSL3 arrays and structures containing arrays can be constant.
- if(shaderVersion < 300 && type.isStructureContainingArrays())
+ if(mShaderVersion < 300 && type.isStructureContainingArrays())
{
error(line,
"structures containing arrays may not be declared constant since they cannot be initialized",
if(type.isArray() && identifier.compare(0, 15, "gl_LastFragData") == 0)
{
const TVariable *maxDrawBuffers =
- static_cast<const TVariable *>(symbolTable.findBuiltIn("gl_MaxDrawBuffers", shaderVersion));
+ static_cast<const TVariable *>(symbolTable.findBuiltIn("gl_MaxDrawBuffers", mShaderVersion));
if(type.getArraySize() != maxDrawBuffers->getConstPointer()->getIConst())
{
error(line, "redeclaration of gl_LastFragData with size != gl_MaxDrawBuffers", identifier.c_str());
{
pp::SourceLocation loc;
DecodeSourceLoc(line, &loc.file, &loc.line);
- directiveHandler.handleExtension(loc, extName, behavior);
+ mDirectiveHandler.handleExtension(loc, extName, behavior);
}
void TParseContext::handlePragmaDirective(const TSourceLoc &line, const char* name, const char* value)
{
pp::SourceLocation loc;
DecodeSourceLoc(line, &loc.file, &loc.line);
- directiveHandler.handlePragma(loc, name, value);
+ mDirectiveHandler.handlePragma(loc, name, value);
}
/////////////////////////////////////////////////////////////////////////////////
{
variable = static_cast<const TVariable*>(symbol);
- if(symbolTable.findBuiltIn(variable->getName(), shaderVersion))
+ if(symbolTable.findBuiltIn(variable->getName(), mShaderVersion))
{
recover();
}
{
// First find by unmangled name to check whether the function name has been
// hidden by a variable name or struct typename.
- const TSymbol* symbol = symbolTable.find(call->getName(), shaderVersion, builtIn);
+ const TSymbol* symbol = symbolTable.find(call->getName(), mShaderVersion, builtIn);
if (symbol == 0) {
- symbol = symbolTable.find(call->getMangledName(), shaderVersion, builtIn);
+ symbol = symbolTable.find(call->getMangledName(), mShaderVersion, builtIn);
}
if (symbol == 0) {
returnType.clearArrayness();
}
- if(shaderVersion < 300)
+ if(mShaderVersion < 300)
{
if(qualifier == EvqAttribute && (typeSpecifier.type == EbtBool || typeSpecifier.type == EbtInt))
{
void TParseContext::parseGlobalLayoutQualifier(const TPublicType &typeQualifier)
{
- if(shaderVersion < 300)
+ if(mShaderVersion < 300)
{
error(typeQualifier.line, "layout qualifiers supported in GLSL ES 3.00 only", "layout");
recover();
if(layoutQualifier.matrixPacking != EmpUnspecified)
{
- defaultMatrixPacking = layoutQualifier.matrixPacking;
+ mDefaultMatrixPacking = layoutQualifier.matrixPacking;
}
if(layoutQualifier.blockStorage != EbsUnspecified)
{
- defaultBlockStorage = layoutQualifier.blockStorage;
+ mDefaultBlockStorage = layoutQualifier.blockStorage;
}
}
if(blockLayoutQualifier.matrixPacking == EmpUnspecified)
{
- blockLayoutQualifier.matrixPacking = defaultMatrixPacking;
+ blockLayoutQualifier.matrixPacking = mDefaultMatrixPacking;
}
if(blockLayoutQualifier.blockStorage == EbsUnspecified)
{
- blockLayoutQualifier.blockStorage = defaultBlockStorage;
+ blockLayoutQualifier.blockStorage = mDefaultBlockStorage;
}
TSymbol* blockNameSymbol = new TSymbol(&blockName);
}
else
{
- if(shaderVersion < 300)
+ if(mShaderVersion < 300)
{
error(dotLocation, " field selection requires structure, vector, or matrix on left hand side",
fieldString.c_str());
bool TParseContext::enterStructDeclaration(const TSourceLoc &line, const TString& identifier)
{
- ++structNestingLevel;
+ ++mStructNestingLevel;
// Embedded structure definitions are not supported per GLSL ES spec.
// They aren't allowed in GLSL either, but we need to detect this here
// so we don't rely on the GLSL compiler to catch it.
- if (structNestingLevel > 1) {
+ if (mStructNestingLevel > 1) {
error(line, "", "Embedded struct definitions are not allowed");
return true;
}
void TParseContext::exitStructDeclaration()
{
- --structNestingLevel;
+ --mStructNestingLevel;
}
bool TParseContext::structNestingErrorCheck(const TSourceLoc &line, const TField &field)
{
if(left->isArray() || right->isArray())
{
- if(shaderVersion < 300)
+ if(mShaderVersion < 300)
{
error(loc, "Invalid operation for arrays", getOperatorString(op));
return false;
case EOpEqual:
case EOpNotEqual:
// ESSL 1.00 sections 5.7, 5.8, 5.9
- if(shaderVersion < 300 && left->getType().isStructureContainingArrays())
+ if(mShaderVersion < 300 && left->getType().isStructureContainingArrays())
{
error(loc, "undefined operation for structs containing arrays", getOperatorString(op));
return false;
// Samplers as l-values are disallowed also in ESSL 3.00, see section 4.1.7,
// we interpret the spec so that this extends to structs containing samplers,
// similarly to ESSL 1.00 spec.
- if((shaderVersion < 300 || op == EOpAssign || op == EOpInitialize) &&
+ if((mShaderVersion < 300 || op == EOpAssign || op == EOpInitialize) &&
left->getType().isStructureContainingSamplers())
{
error(loc, "undefined operation for structs containing samplers", getOperatorString(op));
TIntermCase *TParseContext::addCase(TIntermTyped *condition, const TSourceLoc &loc)
{
- if(switchNestingLevel == 0)
+ if(mSwitchNestingLevel == 0)
{
error(loc, "case labels need to be inside switch statements", "case");
recover();
TIntermCase *TParseContext::addDefault(const TSourceLoc &loc)
{
- if(switchNestingLevel == 0)
+ if(mSwitchNestingLevel == 0)
{
error(loc, "default labels need to be inside switch statements", "default");
recover();
switch(op)
{
case EOpContinue:
- if(loopNestingLevel <= 0)
+ if(mLoopNestingLevel <= 0)
{
error(loc, "continue statement only allowed in loops", "");
recover();
}
break;
case EOpBreak:
- if(loopNestingLevel <= 0 && switchNestingLevel <= 0)
+ if(mLoopNestingLevel <= 0 && mSwitchNestingLevel <= 0)
{
error(loc, "break statement only allowed in loops and switch statements", "");
recover();
}
break;
case EOpReturn:
- if(currentFunctionType->getBasicType() != EbtVoid)
+ if(mCurrentFunctionType->getBasicType() != EbtVoid)
{
error(loc, "non-void function must return a value", "return");
recover();
TIntermBranch *TParseContext::addBranch(TOperator op, TIntermTyped *returnValue, const TSourceLoc &loc)
{
ASSERT(op == EOpReturn);
- functionReturnsValue = true;
- if(currentFunctionType->getBasicType() == EbtVoid)
+ mFunctionReturnsValue = true;
+ if(mCurrentFunctionType->getBasicType() == EbtVoid)
{
error(loc, "void function cannot return a value", "return");
recover();
}
- else if(*currentFunctionType != returnValue->getType())
+ else if(*mCurrentFunctionType != returnValue->getType())
{
error(loc, "function return is not matching type:", "return");
recover();
// The following are extra variables needed during parsing, grouped together so
// they can be passed to the parser without needing a global.
//
-struct TParseContext {
+class TParseContext {
+public:
TParseContext(TSymbolTable& symt, TExtensionBehavior& ext, TIntermediate& interm, GLenum type, int options, bool checksPrecErrors, const char* sourcePath, TInfoSink& is) :
intermediate(interm),
symbolTable(symt),
- shaderType(type),
compileOptions(options),
sourcePath(sourcePath),
- treeRoot(0),
lexAfterType(false),
- loopNestingLevel(0),
- switchNestingLevel(0),
- structNestingLevel(0),
inTypeParen(false),
- currentFunctionType(NULL),
- functionReturnsValue(false),
- checksPrecisionErrors(checksPrecErrors),
- defaultMatrixPacking(EmpColumnMajor),
- defaultBlockStorage(EbsShared),
- diagnostics(is),
- shaderVersion(100),
- directiveHandler(ext, diagnostics, shaderVersion),
- preprocessor(&diagnostics, &directiveHandler),
- scanner(NULL),
- mDeferredSingleDeclarationErrorCheck(false),
+ AfterEOF(false),
+ mDeferredSingleDeclarationErrorCheck(false),\r
+ mShaderType(type),
+ mShaderVersion(100),
+ mTreeRoot(0),
+ mLoopNestingLevel(0),
+ mSwitchNestingLevel(0),
+ mStructNestingLevel(0),
+ mCurrentFunctionType(NULL),
+ mFunctionReturnsValue(false),
+ mChecksPrecisionErrors(checksPrecErrors),\r
+ mDefaultMatrixPacking(EmpColumnMajor),
+ mDefaultBlockStorage(EbsShared),\r
+ mDiagnostics(is),
+ mDirectiveHandler(ext, mDiagnostics, mShaderVersion),
+ mPreprocessor(&mDiagnostics, &mDirectiveHandler),
+ mScanner(NULL),\r
mUsesFragData(false),
mUsesFragColor(false) { }
TIntermediate& intermediate; // to hold and build a parse tree
TSymbolTable& symbolTable; // symbol table that goes with the language currently being parsed
- GLenum shaderType; // vertex or fragment language (future: pack or unpack)
- int shaderVersion;
int compileOptions;
const char* sourcePath; // Path of source file or NULL.
- TIntermNode* treeRoot; // root of parse tree being created
bool lexAfterType; // true if we've recognized a type, so can only be looking for an identifier
- int loopNestingLevel; // 0 if outside all loops
- int switchNestingLevel; // 0 if outside all switch statements
- int structNestingLevel; // incremented while parsing a struct declaration
bool inTypeParen; // true if in parentheses, looking only for an identifier
- const TType* currentFunctionType; // the return type of the function that's currently being parsed
- bool functionReturnsValue; // true if a non-void function has a return
- bool checksPrecisionErrors; // true if an error will be generated when a variable is declared without precision, explicit or implicit.
- TLayoutMatrixPacking defaultMatrixPacking;
- TLayoutBlockStorage defaultBlockStorage;
- TString HashErrMsg;
bool AfterEOF;
- TDiagnostics diagnostics;
- TDirectiveHandler directiveHandler;
- pp::Preprocessor preprocessor;
- void* scanner;
-
- int getShaderVersion() const { return shaderVersion; }
- int numErrors() const { return diagnostics.numErrors(); }
- TInfoSink& infoSink() { return diagnostics.infoSink(); }
+
+ const pp::Preprocessor &getPreprocessor() const { return mPreprocessor; }\r
+ pp::Preprocessor &getPreprocessor() { return mPreprocessor; }\r
+ void *getScanner() const { return mScanner; }\r
+ void setScanner(void *scanner) { mScanner = scanner; }\r
+ int getShaderVersion() const { return mShaderVersion; }\r
+ GLenum getShaderType() const { return mShaderType; }\r
+ int numErrors() const { return mDiagnostics.numErrors(); }\r
+ TInfoSink &infoSink() { return mDiagnostics.infoSink(); }
void error(const TSourceLoc &loc, const char *reason, const char* token,
const char* extraInfo="");
void warning(const TSourceLoc &loc, const char* reason, const char* token,
const char* extraInfo="");
void trace(const char* str);
void recover();
-
- void incrSwitchNestingLevel() { ++switchNestingLevel; }
- void decrSwitchNestingLevel() { --switchNestingLevel; }
+ TIntermNode *getTreeRoot() const { return mTreeRoot; }\r
+ void setTreeRoot(TIntermNode *treeRoot) { mTreeRoot = treeRoot; }\r
+\r
+ bool getFunctionReturnsValue() const { return mFunctionReturnsValue; }\r
+ void setFunctionReturnsValue(bool functionReturnsValue)\r
+ {\r
+ mFunctionReturnsValue = functionReturnsValue;\r
+ }\r
+\r
+ void setLoopNestingLevel(int loopNestintLevel)\r
+ {\r
+ mLoopNestingLevel = loopNestintLevel;\r
+ }\r
+\r
+ const TType *getCurrentFunctionType() const { return mCurrentFunctionType; }\r
+ void setCurrentFunctionType(const TType *currentFunctionType)\r
+ {\r
+ mCurrentFunctionType = currentFunctionType;\r
+ }\r
+\r
+ void incrLoopNestingLevel() { ++mLoopNestingLevel; }\r
+ void decrLoopNestingLevel() { --mLoopNestingLevel; }\r
+\r
+ void incrSwitchNestingLevel() { ++mSwitchNestingLevel; }\r
+ void decrSwitchNestingLevel() { --mSwitchNestingLevel; }
// This method is guaranteed to succeed, even if no variable with 'name' exists.
const TVariable *getNamedVariable(const TSourceLoc &location, const TString *name, const TSymbol *symbol);
bool layoutLocationErrorCheck(const TSourceLoc& location, const TLayoutQualifier &layoutQualifier);
bool functionCallLValueErrorCheck(const TFunction *fnCandidate, TIntermAggregate *);
- const TExtensionBehavior& extensionBehavior() const { return directiveHandler.extensionBehavior(); }
+ const TExtensionBehavior& extensionBehavior() const { return mDirectiveHandler.extensionBehavior(); }
bool supportsExtension(const char* extension);
void handleExtensionDirective(const TSourceLoc &line, const char* extName, const char* behavior);
- const TPragma& pragma() const { return directiveHandler.pragma(); }
+ const TPragma& pragma() const { return mDirectiveHandler.pragma(); }
void handlePragmaDirective(const TSourceLoc &line, const char* name, const char* value);
bool containsSampler(TType& type);
// Return true if the checks pass
bool binaryOpCommonCheck(TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &loc);
- bool mDeferredSingleDeclarationErrorCheck;
- bool mUsesFragData; // track if we are using both gl_FragData and gl_FragColor
+ // Set to true when the last/current declarator list was started with an empty declaration.\r
+ bool mDeferredSingleDeclarationErrorCheck;\r
+\r
+ GLenum mShaderType; // vertex or fragment language (future: pack or unpack)\r
+ int mShaderVersion;\r
+ TIntermNode *mTreeRoot; // root of parse tree being created\r
+ int mLoopNestingLevel; // 0 if outside all loops\r
+ int mSwitchNestingLevel; // 0 if outside all switch statements\r
+ int mStructNestingLevel; // incremented while parsing a struct declaration\r
+ const TType *mCurrentFunctionType; // the return type of the function that's currently being parsed\r
+ bool mFunctionReturnsValue; // true if a non-void function has a return\r
+ bool mChecksPrecisionErrors; // true if an error will be generated when a variable is declared without precision, explicit or implicit.\r
+\r
+ TLayoutMatrixPacking mDefaultMatrixPacking;\r
+ TLayoutBlockStorage mDefaultBlockStorage;\r
+ TDiagnostics mDiagnostics;\r
+ TDirectiveHandler mDirectiveHandler;\r
+ pp::Preprocessor mPreprocessor;\r
+ void *mScanner;\r
+ bool mUsesFragData; // track if we are using both gl_FragData and gl_FragColor\r
bool mUsesFragColor;
};
#define COMPILER_TRANSLATOR_VALIDATEGLOBALINITIALIZER_H_\r
\r
class TIntermTyped;\r
-struct TParseContext;\r
+class TParseContext;\r
\r
// Returns true if the initializer is valid.\r
bool ValidateGlobalInitializer(TIntermTyped *initializer, const TParseContext *context, bool *warning);\r
bool valid = true;
TSymbolTable& symbolTable = GetGlobalParseContext()->symbolTable;
- TSymbol* symbol = symbolTable.find(node->getName(), GetGlobalParseContext()->shaderVersion);
+ TSymbol* symbol = symbolTable.find(node->getName(), GetGlobalParseContext()->getShaderVersion());
ASSERT(symbol && symbol->isFunction());
TFunction* function = static_cast<TFunction*>(symbol);
for (ParamIndex::const_iterator i = pIndex.begin();
#include "intermediate.h"\r
#include <set>\r
\r
-struct TParseContext;\r
+class TParseContext;\r
\r
class ValidateSwitch : public TIntermTraverser\r
{\r
// found in the LICENSE file.
//
-struct TParseContext;
+class TParseContext;
extern int glslang_initialize(TParseContext* context);
extern int glslang_finalize(TParseContext* context);
"sampler2DMSArray" |
"isampler2DMSArray" |
"usampler2DMSArray" {
- if (context->shaderVersion < 300) {
+ if (context->getShaderVersion() < 300) {
yylval->lex.string = NewPoolTString(yytext);
return check_type(yyscanner);
}
/* Reserved keywords in GLSL ES 1.00 that are not reserved in GLSL ES 3.00 */
"packed" {
- if (context->shaderVersion >= 300)
+ if (context->getShaderVersion() >= 300)
{
yylval->lex.string = NewPoolTString(yytext);
return check_type(yyscanner);
yy_size_t string_input(char* buf, yy_size_t max_size, yyscan_t yyscanner) {
pp::Token token;
- yyget_extra(yyscanner)->preprocessor.lex(&token);
+ yyget_extra(yyscanner)->getPreprocessor().lex(&token);
yy_size_t len = token.type == pp::Token::LAST ? 0 : token.text.size();
if (len < max_size)
memcpy(buf, token.text.c_str(), len);
struct yyguts_t* yyg = (struct yyguts_t*) yyscanner;
int token = IDENTIFIER;
- TSymbol* symbol = yyextra->symbolTable.find(yytext, yyextra->shaderVersion);
+ TSymbol* symbol = yyextra->symbolTable.find(yytext, yyextra->getShaderVersion());
if (yyextra->lexAfterType == false && symbol && symbol->isVariable()) {
TVariable* variable = static_cast<TVariable*>(symbol);
if (variable->isUserType()) {
int ES2_reserved_ES3_keyword(TParseContext *context, int token)
{
- yyscan_t yyscanner = (yyscan_t) context->scanner;
+ yyscan_t yyscanner = (yyscan_t) context->getScanner();
- if (context->shaderVersion < 300)
+ if (context->getShaderVersion() < 300)
{
return reserved_word(yyscanner);
}
int ES2_keyword_ES3_reserved(TParseContext *context, int token)
{
- yyscan_t yyscanner = (yyscan_t) context->scanner;
+ yyscan_t yyscanner = (yyscan_t) context->getScanner();
- if (context->shaderVersion >= 300)
+ if (context->getShaderVersion() >= 300)
{
return reserved_word(yyscanner);
}
int ES2_identifier_ES3_keyword(TParseContext *context, int token)
{
- struct yyguts_t* yyg = (struct yyguts_t*) context->scanner;
- yyscan_t yyscanner = (yyscan_t) context->scanner;
+ struct yyguts_t* yyg = (struct yyguts_t*) context->getScanner();
+ yyscan_t yyscanner = (yyscan_t) context->getScanner();
// not a reserved word in GLSL ES 1.00, so could be used as an identifier/type name
- if (context->shaderVersion < 300)
+ if (context->getShaderVersion() < 300)
{
yylval->lex.string = NewPoolTString(yytext);
return check_type(yyscanner);
int uint_constant(TParseContext *context)
{
- struct yyguts_t* yyg = (struct yyguts_t*) context->scanner;
- yyscan_t yyscanner = (yyscan_t) context->scanner;
+ struct yyguts_t* yyg = (struct yyguts_t*) context->getScanner();
+ yyscan_t yyscanner = (yyscan_t) context->getScanner();
- if (context->shaderVersion < 300)
+ if (context->getShaderVersion() < 300)
{
context->error(*yylloc, "Unsigned integers are unsupported prior to GLSL ES 3.00", yytext, "");
context->recover();
int floatsuffix_check(TParseContext* context)
{
- struct yyguts_t* yyg = (struct yyguts_t*) context->scanner;
+ struct yyguts_t* yyg = (struct yyguts_t*) context->getScanner();
- if (context->shaderVersion < 300)
+ if (context->getShaderVersion() < 300)
{
context->error(*yylloc, "Floating-point suffix unsupported prior to GLSL ES 3.00", yytext);
context->recover();
}
void yyerror(YYLTYPE* lloc, TParseContext* context, const char* reason) {
- struct yyguts_t* yyg = (struct yyguts_t*) context->scanner;
+ struct yyguts_t* yyg = (struct yyguts_t*) context->getScanner();
if (context->AfterEOF) {
context->error(*lloc, reason, "unexpected EOF");
if (yylex_init_extra(context, &scanner))
return 1;
- context->scanner = scanner;
+ context->setScanner(scanner);
return 0;
}
int glslang_finalize(TParseContext* context) {
- yyscan_t scanner = context->scanner;
+ yyscan_t scanner = context->getScanner();
if (scanner == NULL) return 0;
- context->scanner = NULL;
+ context->setScanner(NULL);
yylex_destroy(scanner);
return 0;
int glslang_scan(size_t count, const char* const string[], const int length[],
TParseContext* context) {
- yyrestart(NULL, context->scanner);
- yyset_lineno(EncodeSourceLoc(0, 1), context->scanner);
+ yyrestart(NULL, context->getScanner());
+ yyset_lineno(EncodeSourceLoc(0, 1), context->getScanner());
context->AfterEOF = false;
// Initialize preprocessor.
- if (!context->preprocessor.init(count, string, length))
+ if (!context->getPreprocessor().init(count, string, length))
return 1;
// Define extension macros.
for (TExtensionBehavior::const_iterator iter = extBehavior.begin();
iter != extBehavior.end(); ++iter)
{
- context->preprocessor.predefineMacro(iter->first.c_str(), 1);
+ context->getPreprocessor().predefineMacro(iter->first.c_str(), 1);
}
- context->preprocessor.predefineMacro("GL_FRAGMENT_PRECISION_HIGH", 1);
+ context->getPreprocessor().predefineMacro("GL_FRAGMENT_PRECISION_HIGH", 1);
return 0;
}
#define YYENABLE_NLS 0
-#define YYLEX_PARAM context->scanner
+#define YYLEX_PARAM context->getScanner()
%}
%expect 1 /* One shift reduce conflict because of if | else */
#define YYLLOC_DEFAULT(Current, Rhs, N) do { (Current) = YYRHSLOC(Rhs, N ? 1 : 0); } while (0)
#define FRAG_VERT_ONLY(S, L) { \
- if (context->shaderType != GL_FRAGMENT_SHADER && \
- context->shaderType != GL_VERTEX_SHADER) { \
+ if (context->getShaderType() != GL_FRAGMENT_SHADER && \
+ context->getShaderType() != GL_VERTEX_SHADER) { \
context->error(L, " supported in vertex/fragment shaders only ", S); \
context->recover(); \
} \
}
#define VERTEX_ONLY(S, L) { \
- if (context->shaderType != GL_VERTEX_SHADER) { \
+ if (context->getShaderType() != GL_VERTEX_SHADER) { \
context->error(L, " supported in vertex shaders only ", S); \
context->recover(); \
} \
}
#define FRAG_ONLY(S, L) { \
- if (context->shaderType != GL_FRAGMENT_SHADER) { \
+ if (context->getShaderType() != GL_FRAGMENT_SHADER) { \
context->error(L, " supported in fragment shaders only ", S); \
context->recover(); \
} \
}
#define ES2_ONLY(S, L) { \
- if (context->shaderVersion != 100) { \
+ if (context->getShaderVersion() != 100) { \
context->error(L, " supported in GLSL ES 1.00 only ", S); \
context->recover(); \
} \
}
#define ES3_ONLY(S, L) { \
- if (context->shaderVersion != 300) { \
+ if (context->getShaderVersion() != 300) { \
context->error(L, " supported in GLSL ES 3.00 only ", S); \
context->recover(); \
} \
//
// Redeclarations are allowed. But, return types and parameter qualifiers must match.
//
- TFunction* prevDec = static_cast<TFunction*>(context->symbolTable.find($1->getMangledName(), context->shaderVersion));
+ TFunction* prevDec = static_cast<TFunction*>(context->symbolTable.find($1->getMangledName(), context->getShaderVersion()));
if (prevDec) {
if (prevDec->getReturnType() != $1->getReturnType()) {
context->error(@2, "overloaded functions must have the same return type", $1->getReturnType().getBasicString());
ES2_ONLY("varying", @1);
if (context->globalErrorCheck(@1, context->symbolTable.atGlobalLevel(), "varying"))
context->recover();
- if (context->shaderType == GL_VERTEX_SHADER)
+ if (context->getShaderType() == GL_VERTEX_SHADER)
$$.setBasic(EbtVoid, EvqVaryingOut, @1);
else
$$.setBasic(EbtVoid, EvqVaryingIn, @1);
ES2_ONLY("varying", @1);
if (context->globalErrorCheck(@1, context->symbolTable.atGlobalLevel(), "invariant varying"))
context->recover();
- if (context->shaderType == GL_VERTEX_SHADER)
+ if (context->getShaderType() == GL_VERTEX_SHADER)
$$.setBasic(EbtVoid, EvqInvariantVaryingOut, @1);
else
$$.setBasic(EbtVoid, EvqInvariantVaryingIn, @1);
}
| IN_QUAL {
ES3_ONLY("in", @1);
- $$.qualifier = (context->shaderType == GL_FRAGMENT_SHADER) ? EvqFragmentIn : EvqVertexIn;
+ $$.qualifier = (context->getShaderType() == GL_FRAGMENT_SHADER) ? EvqFragmentIn : EvqVertexIn;
$$.line = @1;
}
| OUT_QUAL {
ES3_ONLY("out", @1);
- $$.qualifier = (context->shaderType == GL_FRAGMENT_SHADER) ? EvqFragmentOut : EvqVertexOut;
+ $$.qualifier = (context->getShaderType() == GL_FRAGMENT_SHADER) ? EvqFragmentOut : EvqVertexOut;
$$.line = @1;
}
| CENTROID IN_QUAL {
ES3_ONLY("centroid in", @1);
- if (context->shaderType == GL_VERTEX_SHADER)
+ if (context->getShaderType() == GL_VERTEX_SHADER)
{
context->error(@1, "invalid storage qualifier", "it is an error to use 'centroid in' in the vertex shader");
context->recover();
}
- $$.qualifier = (context->shaderType == GL_FRAGMENT_SHADER) ? EvqCentroidIn : EvqVertexIn;
+ $$.qualifier = (context->getShaderType() == GL_FRAGMENT_SHADER) ? EvqCentroidIn : EvqVertexIn;
$$.line = @2;
}
| CENTROID OUT_QUAL {
ES3_ONLY("centroid out", @1);
- if (context->shaderType == GL_FRAGMENT_SHADER)
+ if (context->getShaderType() == GL_FRAGMENT_SHADER)
{
context->error(@1, "invalid storage qualifier", "it is an error to use 'centroid out' in the fragment shader");
context->recover();
}
- $$.qualifier = (context->shaderType == GL_FRAGMENT_SHADER) ? EvqFragmentOut : EvqCentroidOut;
+ $$.qualifier = (context->getShaderType() == GL_FRAGMENT_SHADER) ? EvqFragmentOut : EvqCentroidOut;
$$.line = @2;
}
| UNIFORM {
;
iteration_statement
- : WHILE LEFT_PAREN { context->symbolTable.push(); ++context->loopNestingLevel; } condition RIGHT_PAREN statement_no_new_scope {
+ : WHILE LEFT_PAREN { context->symbolTable.push(); context->incrLoopNestingLevel(); } condition RIGHT_PAREN statement_no_new_scope {
context->symbolTable.pop();
$$ = context->intermediate.addLoop(ELoopWhile, 0, $4, 0, $6, @1);
- --context->loopNestingLevel;
+ context->decrLoopNestingLevel();
}
- | DO { ++context->loopNestingLevel; } statement_with_scope WHILE LEFT_PAREN expression RIGHT_PAREN SEMICOLON {
+ | DO { context->incrLoopNestingLevel(); } statement_with_scope WHILE LEFT_PAREN expression RIGHT_PAREN SEMICOLON {
if (context->boolErrorCheck(@8, $6))
context->recover();
$$ = context->intermediate.addLoop(ELoopDoWhile, 0, $6, 0, $3, @4);
- --context->loopNestingLevel;
+ context->decrLoopNestingLevel();
}
- | FOR LEFT_PAREN { context->symbolTable.push(); ++context->loopNestingLevel; } for_init_statement for_rest_statement RIGHT_PAREN statement_no_new_scope {
+ | FOR LEFT_PAREN { context->symbolTable.push(); context->incrLoopNestingLevel(); } for_init_statement for_rest_statement RIGHT_PAREN statement_no_new_scope {
context->symbolTable.pop();
$$ = context->intermediate.addLoop(ELoopFor, $4, reinterpret_cast<TIntermTyped*>($5.node1), reinterpret_cast<TIntermTyped*>($5.node2), $7, @1);
- --context->loopNestingLevel;
+ context->decrLoopNestingLevel();
}
;
translation_unit
: external_declaration {
$$ = $1;
- context->treeRoot = $$;
+ context->setTreeRoot($$);
}
| translation_unit external_declaration {
$$ = context->intermediate.growAggregate($1, $2, 0);
- context->treeRoot = $$;
+ context->setTreeRoot($$);
}
;
: function_prototype {
TFunction* function = $1.function;
- const TSymbol *builtIn = context->symbolTable.findBuiltIn(function->getMangledName(), context->shaderVersion);
+ const TSymbol *builtIn = context->symbolTable.findBuiltIn(function->getMangledName(), context->getShaderVersion());
if (builtIn)
{
context->recover();
}
- TFunction* prevDec = static_cast<TFunction*>(context->symbolTable.find(function->getMangledName(), context->shaderVersion));
+ TFunction* prevDec = static_cast<TFunction*>(context->symbolTable.find(function->getMangledName(), context->getShaderVersion()));
//
// 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
//
// Remember the return type for later checking for RETURN statements.
//
- context->currentFunctionType = &(prevDec->getReturnType());
- context->functionReturnsValue = false;
+ context->setCurrentFunctionType(&(prevDec->getReturnType()));
+ context->setFunctionReturnsValue(false);
//
// Insert parameters into the symbol table.
}
context->intermediate.setAggregateOperator(paramNodes, EOpParameters, @1);
$1.intermAggregate = paramNodes;
- context->loopNestingLevel = 0;
+ context->setLoopNestingLevel(0);
}
compound_statement_no_new_scope {
//?? Check that all paths return a value if return type != void ?
// May be best done as post process phase on intermediate code
- if (context->currentFunctionType->getBasicType() != EbtVoid && ! context->functionReturnsValue) {
+ if (context->getCurrentFunctionType()->getBasicType() != EbtVoid && ! context->getFunctionReturnsValue()) {
context->error(@1, "function does not return a value:", "", $1.function->getName().c_str());
context->recover();
}
case 138:
YY_RULE_SETUP
{
- if (context->shaderVersion < 300) {
+ if (context->getShaderVersion() < 300) {
yylval->lex.string = NewPoolTString(yytext);
return check_type(yyscanner);
}
case 139:
YY_RULE_SETUP
{
- if (context->shaderVersion >= 300)
+ if (context->getShaderVersion() >= 300)
{
yylval->lex.string = NewPoolTString(yytext);
return check_type(yyscanner);
yy_size_t string_input(char* buf, yy_size_t max_size, yyscan_t yyscanner) {
pp::Token token;
- yyget_extra(yyscanner)->preprocessor.lex(&token);
+ yyget_extra(yyscanner)->getPreprocessor().lex(&token);
yy_size_t len = token.type == pp::Token::LAST ? 0 : token.text.size();
if (len < max_size)
memcpy(buf, token.text.c_str(), len);
struct yyguts_t* yyg = (struct yyguts_t*) yyscanner;
int token = IDENTIFIER;
- TSymbol* symbol = yyextra->symbolTable.find(yytext, yyextra->shaderVersion);
+ TSymbol* symbol = yyextra->symbolTable.find(yytext, yyextra->getShaderVersion());
if (yyextra->lexAfterType == false && symbol && symbol->isVariable()) {
TVariable* variable = static_cast<TVariable*>(symbol);
if (variable->isUserType()) {
int ES2_reserved_ES3_keyword(TParseContext *context, int token)
{
- yyscan_t yyscanner = (yyscan_t) context->scanner;
+ yyscan_t yyscanner = (yyscan_t) context->getScanner();
- if (context->shaderVersion < 300)
+ if (context->getShaderVersion() < 300)
{
return reserved_word(yyscanner);
}
int ES2_keyword_ES3_reserved(TParseContext *context, int token)
{
- yyscan_t yyscanner = (yyscan_t) context->scanner;
+ yyscan_t yyscanner = (yyscan_t) context->getScanner();
- if (context->shaderVersion >= 300)
+ if (context->getShaderVersion() >= 300)
{
return reserved_word(yyscanner);
}
int ES2_identifier_ES3_keyword(TParseContext *context, int token)
{
- struct yyguts_t* yyg = (struct yyguts_t*) context->scanner;
- yyscan_t yyscanner = (yyscan_t) context->scanner;
+ struct yyguts_t* yyg = (struct yyguts_t*) context->getScanner();
+ yyscan_t yyscanner = (yyscan_t) context->getScanner();
// not a reserved word in GLSL ES 1.00, so could be used as an identifier/type name
- if (context->shaderVersion < 300)
+ if (context->getShaderVersion() < 300)
{
yylval->lex.string = NewPoolTString(yytext);
return check_type(yyscanner);
int uint_constant(TParseContext *context)
{
- struct yyguts_t* yyg = (struct yyguts_t*) context->scanner;
- yyscan_t yyscanner = (yyscan_t) context->scanner;
+ struct yyguts_t* yyg = (struct yyguts_t*) context->getScanner();
+ yyscan_t yyscanner = (yyscan_t) context->getScanner();
- if (context->shaderVersion < 300)
+ if (context->getShaderVersion() < 300)
{
context->error(*yylloc, "Unsigned integers are unsupported prior to GLSL ES 3.00", yytext, "");
context->recover();
int floatsuffix_check(TParseContext* context)
{
- struct yyguts_t* yyg = (struct yyguts_t*) context->scanner;
+ struct yyguts_t* yyg = (struct yyguts_t*) context->getScanner();
- if (context->shaderVersion < 300)
+ if (context->getShaderVersion() < 300)
{
context->error(*yylloc, "Floating-point suffix unsupported prior to GLSL ES 3.00", yytext);
context->recover();
}
void yyerror(YYLTYPE* lloc, TParseContext* context, const char* reason) {
- struct yyguts_t* yyg = (struct yyguts_t*) context->scanner;
+ struct yyguts_t* yyg = (struct yyguts_t*) context->getScanner();
if (context->AfterEOF) {
context->error(*lloc, reason, "unexpected EOF");
if (yylex_init_extra(context,&scanner))
return 1;
- context->scanner = scanner;
+ context->setScanner(scanner);
return 0;
}
int glslang_finalize(TParseContext* context) {
- yyscan_t scanner = context->scanner;
+ yyscan_t scanner = context->getScanner();
if (scanner == NULL) return 0;
- context->scanner = NULL;
+ context->setScanner(NULL);
yylex_destroy(scanner);
return 0;
int glslang_scan(size_t count, const char* const string[], const int length[],
TParseContext* context) {
- yyrestart(NULL,context->scanner);
- yyset_lineno(EncodeSourceLoc(0, 1),context->scanner);
+ yyrestart(NULL,context->getScanner());
+ yyset_lineno(EncodeSourceLoc(0, 1),context->getScanner());
context->AfterEOF = false;
// Initialize preprocessor.
- if (!context->preprocessor.init(count, string, length))
+ if (!context->getPreprocessor().init(count, string, length))
return 1;
// Define extension macros.
for (TExtensionBehavior::const_iterator iter = extBehavior.begin();
iter != extBehavior.end(); ++iter)
{
- context->preprocessor.predefineMacro(iter->first.c_str(), 1);
+ context->getPreprocessor().predefineMacro(iter->first.c_str(), 1);
}
- context->preprocessor.predefineMacro("GL_FRAGMENT_PRECISION_HIGH", 1);
+ context->getPreprocessor().predefineMacro("GL_FRAGMENT_PRECISION_HIGH", 1);
return 0;
}
#define YYENABLE_NLS 0
-#define YYLEX_PARAM context->scanner
+#define YYLEX_PARAM context->getScanner()
#define YYLLOC_DEFAULT(Current, Rhs, N) do { (Current) = YYRHSLOC(Rhs, N ? 1 : 0); } while (0)
#define FRAG_VERT_ONLY(S, L) { \
- if (context->shaderType != GL_FRAGMENT_SHADER && \
- context->shaderType != GL_VERTEX_SHADER) { \
+ if (context->getShaderType() != GL_FRAGMENT_SHADER && \
+ context->getShaderType() != GL_VERTEX_SHADER) { \
context->error(L, " supported in vertex/fragment shaders only ", S); \
context->recover(); \
} \
}
#define VERTEX_ONLY(S, L) { \
- if (context->shaderType != GL_VERTEX_SHADER) { \
+ if (context->getShaderType() != GL_VERTEX_SHADER) { \
context->error(L, " supported in vertex shaders only ", S); \
context->recover(); \
} \
}
#define FRAG_ONLY(S, L) { \
- if (context->shaderType != GL_FRAGMENT_SHADER) { \
+ if (context->getShaderType() != GL_FRAGMENT_SHADER) { \
context->error(L, " supported in fragment shaders only ", S); \
context->recover(); \
} \
}
#define ES2_ONLY(S, L) { \
- if (context->shaderVersion != 100) { \
+ if (context->getShaderVersion() != 100) { \
context->error(L, " supported in GLSL ES 1.00 only ", S); \
context->recover(); \
} \
}
#define ES3_ONLY(S, L) { \
- if (context->shaderVersion != 300) { \
+ if (context->getShaderVersion() != 300) { \
context->error(L, " supported in GLSL ES 3.00 only ", S); \
context->recover(); \
} \
//
// Redeclarations are allowed. But, return types and parameter qualifiers must match.
//
- TFunction* prevDec = static_cast<TFunction*>(context->symbolTable.find((yyvsp[(1) - (2)].interm.function)->getMangledName(), context->shaderVersion));
+ TFunction* prevDec = static_cast<TFunction*>(context->symbolTable.find((yyvsp[(1) - (2)].interm.function)->getMangledName(), context->getShaderVersion()));
if (prevDec) {
if (prevDec->getReturnType() != (yyvsp[(1) - (2)].interm.function)->getReturnType()) {
context->error((yylsp[(2) - (2)]), "overloaded functions must have the same return type", (yyvsp[(1) - (2)].interm.function)->getReturnType().getBasicString());
ES2_ONLY("varying", (yylsp[(1) - (1)]));
if (context->globalErrorCheck((yylsp[(1) - (1)]), context->symbolTable.atGlobalLevel(), "varying"))
context->recover();
- if (context->shaderType == GL_VERTEX_SHADER)
+ if (context->getShaderType() == GL_VERTEX_SHADER)
(yyval.interm.type).setBasic(EbtVoid, EvqVaryingOut, (yylsp[(1) - (1)]));
else
(yyval.interm.type).setBasic(EbtVoid, EvqVaryingIn, (yylsp[(1) - (1)]));
ES2_ONLY("varying", (yylsp[(1) - (2)]));
if (context->globalErrorCheck((yylsp[(1) - (2)]), context->symbolTable.atGlobalLevel(), "invariant varying"))
context->recover();
- if (context->shaderType == GL_VERTEX_SHADER)
+ if (context->getShaderType() == GL_VERTEX_SHADER)
(yyval.interm.type).setBasic(EbtVoid, EvqInvariantVaryingOut, (yylsp[(1) - (2)]));
else
(yyval.interm.type).setBasic(EbtVoid, EvqInvariantVaryingIn, (yylsp[(1) - (2)]));
{
ES3_ONLY("in", (yylsp[(1) - (1)]));
- (yyval.interm.type).qualifier = (context->shaderType == GL_FRAGMENT_SHADER) ? EvqFragmentIn : EvqVertexIn;
+ (yyval.interm.type).qualifier = (context->getShaderType() == GL_FRAGMENT_SHADER) ? EvqFragmentIn : EvqVertexIn;
(yyval.interm.type).line = (yylsp[(1) - (1)]);
}
break;
{
ES3_ONLY("out", (yylsp[(1) - (1)]));
- (yyval.interm.type).qualifier = (context->shaderType == GL_FRAGMENT_SHADER) ? EvqFragmentOut : EvqVertexOut;
+ (yyval.interm.type).qualifier = (context->getShaderType() == GL_FRAGMENT_SHADER) ? EvqFragmentOut : EvqVertexOut;
(yyval.interm.type).line = (yylsp[(1) - (1)]);
}
break;
{
ES3_ONLY("centroid in", (yylsp[(1) - (2)]));
- if (context->shaderType == GL_VERTEX_SHADER)
+ if (context->getShaderType() == GL_VERTEX_SHADER)
{
context->error((yylsp[(1) - (2)]), "invalid storage qualifier", "it is an error to use 'centroid in' in the vertex shader");
context->recover();
}
- (yyval.interm.type).qualifier = (context->shaderType == GL_FRAGMENT_SHADER) ? EvqCentroidIn : EvqVertexIn;
+ (yyval.interm.type).qualifier = (context->getShaderType() == GL_FRAGMENT_SHADER) ? EvqCentroidIn : EvqVertexIn;
(yyval.interm.type).line = (yylsp[(2) - (2)]);
}
break;
{
ES3_ONLY("centroid out", (yylsp[(1) - (2)]));
- if (context->shaderType == GL_FRAGMENT_SHADER)
+ if (context->getShaderType() == GL_FRAGMENT_SHADER)
{
context->error((yylsp[(1) - (2)]), "invalid storage qualifier", "it is an error to use 'centroid out' in the fragment shader");
context->recover();
}
- (yyval.interm.type).qualifier = (context->shaderType == GL_FRAGMENT_SHADER) ? EvqFragmentOut : EvqCentroidOut;
+ (yyval.interm.type).qualifier = (context->getShaderType() == GL_FRAGMENT_SHADER) ? EvqFragmentOut : EvqCentroidOut;
(yyval.interm.type).line = (yylsp[(2) - (2)]);
}
break;
case 248:
- { context->symbolTable.push(); ++context->loopNestingLevel; }
+ { context->symbolTable.push(); context->incrLoopNestingLevel(); }
break;
case 249:
{
context->symbolTable.pop();
(yyval.interm.intermNode) = context->intermediate.addLoop(ELoopWhile, 0, (yyvsp[(4) - (6)].interm.intermTypedNode), 0, (yyvsp[(6) - (6)].interm.intermNode), (yylsp[(1) - (6)]));
- --context->loopNestingLevel;
+ context->decrLoopNestingLevel();
}
break;
case 250:
- { ++context->loopNestingLevel; }
+ { context->incrLoopNestingLevel(); }
break;
case 251:
context->recover();
(yyval.interm.intermNode) = context->intermediate.addLoop(ELoopDoWhile, 0, (yyvsp[(6) - (8)].interm.intermTypedNode), 0, (yyvsp[(3) - (8)].interm.intermNode), (yylsp[(4) - (8)]));
- --context->loopNestingLevel;
+ context->decrLoopNestingLevel();
}
break;
case 252:
- { context->symbolTable.push(); ++context->loopNestingLevel; }
+ { context->symbolTable.push(); context->incrLoopNestingLevel(); }
break;
case 253:
{
context->symbolTable.pop();
(yyval.interm.intermNode) = context->intermediate.addLoop(ELoopFor, (yyvsp[(4) - (7)].interm.intermNode), reinterpret_cast<TIntermTyped*>((yyvsp[(5) - (7)].interm.nodePair).node1), reinterpret_cast<TIntermTyped*>((yyvsp[(5) - (7)].interm.nodePair).node2), (yyvsp[(7) - (7)].interm.intermNode), (yylsp[(1) - (7)]));
- --context->loopNestingLevel;
+ context->decrLoopNestingLevel();
}
break;
{
(yyval.interm.intermNode) = (yyvsp[(1) - (1)].interm.intermNode);
- context->treeRoot = (yyval.interm.intermNode);
+ context->setTreeRoot((yyval.interm.intermNode));
}
break;
{
(yyval.interm.intermNode) = context->intermediate.growAggregate((yyvsp[(1) - (2)].interm.intermNode), (yyvsp[(2) - (2)].interm.intermNode), 0);
- context->treeRoot = (yyval.interm.intermNode);
+ context->setTreeRoot((yyval.interm.intermNode));
}
break;
{
TFunction* function = (yyvsp[(1) - (1)].interm).function;
- const TSymbol *builtIn = context->symbolTable.findBuiltIn(function->getMangledName(), context->shaderVersion);
+ const TSymbol *builtIn = context->symbolTable.findBuiltIn(function->getMangledName(), context->getShaderVersion());
if (builtIn)
{
context->recover();
}
- TFunction* prevDec = static_cast<TFunction*>(context->symbolTable.find(function->getMangledName(), context->shaderVersion));
+ TFunction* prevDec = static_cast<TFunction*>(context->symbolTable.find(function->getMangledName(), context->getShaderVersion()));
//
// 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
//
// Remember the return type for later checking for RETURN statements.
//
- context->currentFunctionType = &(prevDec->getReturnType());
- context->functionReturnsValue = false;
+ context->setCurrentFunctionType(&(prevDec->getReturnType()));
+ context->setFunctionReturnsValue(false);
//
// Insert parameters into the symbol table.
}
context->intermediate.setAggregateOperator(paramNodes, EOpParameters, (yylsp[(1) - (1)]));
(yyvsp[(1) - (1)].interm).intermAggregate = paramNodes;
- context->loopNestingLevel = 0;
+ context->setLoopNestingLevel(0);
}
break;
{
//?? Check that all paths return a value if return type != void ?
// May be best done as post process phase on intermediate code
- if (context->currentFunctionType->getBasicType() != EbtVoid && ! context->functionReturnsValue) {
+ if (context->getCurrentFunctionType()->getBasicType() != EbtVoid && ! context->getFunctionReturnsValue()) {
context->error((yylsp[(1) - (3)]), "function does not return a value:", "", (yyvsp[(1) - (3)].interm).function->getName().c_str());
context->recover();
}