Commit d7cd4ae5 by Olli Etuaho Committed by Commit Bot

Check that function declarations don't use a reserved name

Reserved function names are now caught if the function is just declared without being called in the shader source. Actually, function calls don't need to be checked for reserved names, since that just generates a redundant error message if function declarations are being checked. Includes some cleanup of ParseContext::checkIsNotReserved. It doesn't need special handling of built-in symbols, as they are never passed to the function. BUG=chromium:739448 TEST=angle_unittests Change-Id: I7115e1a7509626b5109b5c054c0704b0c3c19c58 Reviewed-on: https://chromium-review.googlesource.com/561457Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarCorentin Wallez <cwallez@chromium.org> Commit-Queue: Olli Etuaho <oetuaho@nvidia.com>
parent 40a1a37c
...@@ -563,44 +563,38 @@ bool TParseContext::checkIsAtGlobalLevel(const TSourceLoc &line, const char *tok ...@@ -563,44 +563,38 @@ bool TParseContext::checkIsAtGlobalLevel(const TSourceLoc &line, const char *tok
return true; return true;
} }
// For now, keep it simple: if it starts "gl_", it's reserved, independent // ESSL 3.00.5 sections 3.8 and 3.9.
// of scope. Except, if the symbol table is at the built-in push-level, // If it starts "gl_" or contains two consecutive underscores, it's reserved.
// which is when we are parsing built-ins. // Also checks for "webgl_" and "_webgl_" reserved identifiers if parsing a webgl shader.
// Also checks for "webgl_" and "_webgl_" reserved identifiers if parsing a
// webgl shader.
bool TParseContext::checkIsNotReserved(const TSourceLoc &line, const TString &identifier) bool TParseContext::checkIsNotReserved(const TSourceLoc &line, const TString &identifier)
{ {
static const char *reservedErrMsg = "reserved built-in name"; static const char *reservedErrMsg = "reserved built-in name";
if (!symbolTable.atBuiltInLevel()) if (identifier.compare(0, 3, "gl_") == 0)
{ {
if (identifier.compare(0, 3, "gl_") == 0) error(line, reservedErrMsg, "gl_");
return false;
}
if (sh::IsWebGLBasedSpec(mShaderSpec))
{
if (identifier.compare(0, 6, "webgl_") == 0)
{ {
error(line, reservedErrMsg, "gl_"); error(line, reservedErrMsg, "webgl_");
return false; return false;
} }
if (sh::IsWebGLBasedSpec(mShaderSpec)) if (identifier.compare(0, 7, "_webgl_") == 0)
{ {
if (identifier.compare(0, 6, "webgl_") == 0) error(line, reservedErrMsg, "_webgl_");
{
error(line, reservedErrMsg, "webgl_");
return false;
}
if (identifier.compare(0, 7, "_webgl_") == 0)
{
error(line, reservedErrMsg, "_webgl_");
return false;
}
}
if (identifier.find("__") != TString::npos)
{
error(line,
"identifiers containing two consecutive underscores (__) are reserved as "
"possible future keywords",
identifier.c_str());
return false; return false;
} }
} }
if (identifier.find("__") != TString::npos)
{
error(line,
"identifiers containing two consecutive underscores (__) are reserved as "
"possible future keywords",
identifier.c_str());
return false;
}
return true; return true;
} }
...@@ -2737,6 +2731,8 @@ TIntermFunctionPrototype *TParseContext::createPrototypeNodeFromFunction( ...@@ -2737,6 +2731,8 @@ TIntermFunctionPrototype *TParseContext::createPrototypeNodeFromFunction(
const TSourceLoc &location, const TSourceLoc &location,
bool insertParametersToSymbolTable) bool insertParametersToSymbolTable)
{ {
checkIsNotReserved(location, function.getName());
TIntermFunctionPrototype *prototype = TIntermFunctionPrototype *prototype =
new TIntermFunctionPrototype(function.getReturnType(), TSymbolUniqueId(function)); new TIntermFunctionPrototype(function.getReturnType(), TSymbolUniqueId(function));
// TODO(oetuaho@nvidia.com): Instead of converting the function information here, the node could // TODO(oetuaho@nvidia.com): Instead of converting the function information here, the node could
...@@ -2997,7 +2993,6 @@ TFunction *TParseContext::parseFunctionHeader(const TPublicType &type, ...@@ -2997,7 +2993,6 @@ TFunction *TParseContext::parseFunctionHeader(const TPublicType &type,
TFunction *TParseContext::addNonConstructorFunc(const TString *name, const TSourceLoc &loc) TFunction *TParseContext::addNonConstructorFunc(const TString *name, const TSourceLoc &loc)
{ {
checkIsNotReserved(loc, *name);
const TType *returnType = TCache::getType(EbtVoid, EbpUndefined); const TType *returnType = TCache::getType(EbtVoid, EbpUndefined);
return new TFunction(name, returnType); return new TFunction(name, returnType);
} }
......
...@@ -3936,3 +3936,41 @@ TEST_F(ComputeShaderEnforcePackingValidationTest, MaxComputeUniformComponents) ...@@ -3936,3 +3936,41 @@ TEST_F(ComputeShaderEnforcePackingValidationTest, MaxComputeUniformComponents)
FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog; FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
} }
} }
// Test that a function can't be declared with a name starting with "gl_". Note that it's important
// that the function is not being called.
TEST_F(FragmentShaderValidationTest, FunctionDeclaredWithReservedName)
{
const std::string &shaderString =
"precision mediump float;\n"
"void gl_();\n"
"void main()\n"
"{\n"
" gl_FragColor = vec4(0.0);\n"
"}\n";
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
}
}
// Test that a function can't be defined with a name starting with "gl_". Note that it's important
// that the function is not being called.
TEST_F(FragmentShaderValidationTest, FunctionDefinedWithReservedName)
{
const std::string &shaderString =
"precision mediump float;\n"
"void gl_()\n"
"{\n"
"}\n"
"void main()\n"
"{\n"
" gl_FragColor = vec4(0.0);\n"
"}\n";
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment