Commit c4a96d67 by Olli Etuaho

Names of built-in functions cannot be redeclared as functions

With ESSL 3.00, names of built-in functions cannot be redeclared as functions, and therefore an error needs to be generated if a built-in function is overloaded. This is fixed by inserting unmangled built-ins into a special set in the symbol table and checking if function declarations match any of the built-ins in the set. The regular symbol table structures can't be used for storing the unmangled names because that interferes with name hashing in OutputGLSL. Credit goes to Arun Patole, apatole@nvidia.com for initially investigating this issue and developing the first version of the patch. BUG=angleproject:1066 TEST=angle_unittests, dEQP-GLES3.functional.shaders.functions.invalid.overload_builtin_function* (2 tests started passing with this change) Change-Id: I28c8325f5a3a8f4a97226b0dfdbb9762724fa609 Reviewed-on: https://chromium-review.googlesource.com/328994Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Commit-Queue: Jamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarCorentin Wallez <cwallez@chromium.org>
parent eaef7c17
...@@ -2117,7 +2117,16 @@ TFunction *TParseContext::parseFunctionDeclarator(const TSourceLoc &location, TF ...@@ -2117,7 +2117,16 @@ TFunction *TParseContext::parseFunctionDeclarator(const TSourceLoc &location, TF
// //
TFunction *prevDec = TFunction *prevDec =
static_cast<TFunction *>(symbolTable.find(function->getMangledName(), getShaderVersion())); static_cast<TFunction *>(symbolTable.find(function->getMangledName(), getShaderVersion()));
if (prevDec)
if (getShaderVersion() >= 300 && symbolTable.hasUnmangledBuiltIn(function->getName().c_str()))
{
// With ESSL 3.00, names of built-in functions cannot be redeclared as functions.
// Therefore overloading or redefining builtin functions is an error.
error(location, "Name of a built-in function cannot be redeclared as function",
function->getName().c_str());
recover();
}
else if (prevDec)
{ {
if (prevDec->getReturnType() != function->getReturnType()) if (prevDec->getReturnType() != function->getReturnType())
{ {
......
...@@ -199,6 +199,7 @@ void TSymbolTable::insertBuiltIn(ESymbolLevel level, TOperator op, const char *e ...@@ -199,6 +199,7 @@ void TSymbolTable::insertBuiltIn(ESymbolLevel level, TOperator op, const char *e
{ {
if (ptype1->getBasicType() == EbtGSampler2D) if (ptype1->getBasicType() == EbtGSampler2D)
{ {
insertUnmangledBuiltIn(name);
bool gvec4 = (rvalue->getBasicType() == EbtGVec4); bool gvec4 = (rvalue->getBasicType() == EbtGVec4);
insertBuiltIn(level, gvec4 ? TCache::getType(EbtFloat, 4) : rvalue, name, TCache::getType(EbtSampler2D), ptype2, ptype3, ptype4, ptype5); insertBuiltIn(level, gvec4 ? TCache::getType(EbtFloat, 4) : rvalue, name, TCache::getType(EbtSampler2D), ptype2, ptype3, ptype4, ptype5);
insertBuiltIn(level, gvec4 ? TCache::getType(EbtInt, 4) : rvalue, name, TCache::getType(EbtISampler2D), ptype2, ptype3, ptype4, ptype5); insertBuiltIn(level, gvec4 ? TCache::getType(EbtInt, 4) : rvalue, name, TCache::getType(EbtISampler2D), ptype2, ptype3, ptype4, ptype5);
...@@ -206,6 +207,7 @@ void TSymbolTable::insertBuiltIn(ESymbolLevel level, TOperator op, const char *e ...@@ -206,6 +207,7 @@ void TSymbolTable::insertBuiltIn(ESymbolLevel level, TOperator op, const char *e
} }
else if (ptype1->getBasicType() == EbtGSampler3D) else if (ptype1->getBasicType() == EbtGSampler3D)
{ {
insertUnmangledBuiltIn(name);
bool gvec4 = (rvalue->getBasicType() == EbtGVec4); bool gvec4 = (rvalue->getBasicType() == EbtGVec4);
insertBuiltIn(level, gvec4 ? TCache::getType(EbtFloat, 4) : rvalue, name, TCache::getType(EbtSampler3D), ptype2, ptype3, ptype4, ptype5); insertBuiltIn(level, gvec4 ? TCache::getType(EbtFloat, 4) : rvalue, name, TCache::getType(EbtSampler3D), ptype2, ptype3, ptype4, ptype5);
insertBuiltIn(level, gvec4 ? TCache::getType(EbtInt, 4) : rvalue, name, TCache::getType(EbtISampler3D), ptype2, ptype3, ptype4, ptype5); insertBuiltIn(level, gvec4 ? TCache::getType(EbtInt, 4) : rvalue, name, TCache::getType(EbtISampler3D), ptype2, ptype3, ptype4, ptype5);
...@@ -213,6 +215,7 @@ void TSymbolTable::insertBuiltIn(ESymbolLevel level, TOperator op, const char *e ...@@ -213,6 +215,7 @@ void TSymbolTable::insertBuiltIn(ESymbolLevel level, TOperator op, const char *e
} }
else if (ptype1->getBasicType() == EbtGSamplerCube) else if (ptype1->getBasicType() == EbtGSamplerCube)
{ {
insertUnmangledBuiltIn(name);
bool gvec4 = (rvalue->getBasicType() == EbtGVec4); bool gvec4 = (rvalue->getBasicType() == EbtGVec4);
insertBuiltIn(level, gvec4 ? TCache::getType(EbtFloat, 4) : rvalue, name, TCache::getType(EbtSamplerCube), ptype2, ptype3, ptype4, ptype5); insertBuiltIn(level, gvec4 ? TCache::getType(EbtFloat, 4) : rvalue, name, TCache::getType(EbtSamplerCube), ptype2, ptype3, ptype4, ptype5);
insertBuiltIn(level, gvec4 ? TCache::getType(EbtInt, 4) : rvalue, name, TCache::getType(EbtISamplerCube), ptype2, ptype3, ptype4, ptype5); insertBuiltIn(level, gvec4 ? TCache::getType(EbtInt, 4) : rvalue, name, TCache::getType(EbtISamplerCube), ptype2, ptype3, ptype4, ptype5);
...@@ -220,6 +223,7 @@ void TSymbolTable::insertBuiltIn(ESymbolLevel level, TOperator op, const char *e ...@@ -220,6 +223,7 @@ void TSymbolTable::insertBuiltIn(ESymbolLevel level, TOperator op, const char *e
} }
else if (ptype1->getBasicType() == EbtGSampler2DArray) else if (ptype1->getBasicType() == EbtGSampler2DArray)
{ {
insertUnmangledBuiltIn(name);
bool gvec4 = (rvalue->getBasicType() == EbtGVec4); bool gvec4 = (rvalue->getBasicType() == EbtGVec4);
insertBuiltIn(level, gvec4 ? TCache::getType(EbtFloat, 4) : rvalue, name, TCache::getType(EbtSampler2DArray), ptype2, ptype3, ptype4, ptype5); insertBuiltIn(level, gvec4 ? TCache::getType(EbtFloat, 4) : rvalue, name, TCache::getType(EbtSampler2DArray), ptype2, ptype3, ptype4, ptype5);
insertBuiltIn(level, gvec4 ? TCache::getType(EbtInt, 4) : rvalue, name, TCache::getType(EbtISampler2DArray), ptype2, ptype3, ptype4, ptype5); insertBuiltIn(level, gvec4 ? TCache::getType(EbtInt, 4) : rvalue, name, TCache::getType(EbtISampler2DArray), ptype2, ptype3, ptype4, ptype5);
...@@ -228,6 +232,7 @@ void TSymbolTable::insertBuiltIn(ESymbolLevel level, TOperator op, const char *e ...@@ -228,6 +232,7 @@ void TSymbolTable::insertBuiltIn(ESymbolLevel level, TOperator op, const char *e
else if (IsGenType(rvalue) || IsGenType(ptype1) || IsGenType(ptype2) || IsGenType(ptype3)) else if (IsGenType(rvalue) || IsGenType(ptype1) || IsGenType(ptype2) || IsGenType(ptype3))
{ {
ASSERT(!ptype4 && !ptype5); ASSERT(!ptype4 && !ptype5);
insertUnmangledBuiltIn(name);
insertBuiltIn(level, op, ext, SpecificType(rvalue, 1), name, SpecificType(ptype1, 1), SpecificType(ptype2, 1), SpecificType(ptype3, 1)); insertBuiltIn(level, op, ext, SpecificType(rvalue, 1), name, SpecificType(ptype1, 1), SpecificType(ptype2, 1), SpecificType(ptype3, 1));
insertBuiltIn(level, op, ext, SpecificType(rvalue, 2), name, SpecificType(ptype1, 2), SpecificType(ptype2, 2), SpecificType(ptype3, 2)); insertBuiltIn(level, op, ext, SpecificType(rvalue, 2), name, SpecificType(ptype1, 2), SpecificType(ptype2, 2), SpecificType(ptype3, 2));
insertBuiltIn(level, op, ext, SpecificType(rvalue, 3), name, SpecificType(ptype1, 3), SpecificType(ptype2, 3), SpecificType(ptype3, 3)); insertBuiltIn(level, op, ext, SpecificType(rvalue, 3), name, SpecificType(ptype1, 3), SpecificType(ptype2, 3), SpecificType(ptype3, 3));
...@@ -236,6 +241,7 @@ void TSymbolTable::insertBuiltIn(ESymbolLevel level, TOperator op, const char *e ...@@ -236,6 +241,7 @@ void TSymbolTable::insertBuiltIn(ESymbolLevel level, TOperator op, const char *e
else if (IsVecType(rvalue) || IsVecType(ptype1) || IsVecType(ptype2) || IsVecType(ptype3)) else if (IsVecType(rvalue) || IsVecType(ptype1) || IsVecType(ptype2) || IsVecType(ptype3))
{ {
ASSERT(!ptype4 && !ptype5); ASSERT(!ptype4 && !ptype5);
insertUnmangledBuiltIn(name);
insertBuiltIn(level, op, ext, VectorType(rvalue, 2), name, VectorType(ptype1, 2), VectorType(ptype2, 2), VectorType(ptype3, 2)); insertBuiltIn(level, op, ext, VectorType(rvalue, 2), name, VectorType(ptype1, 2), VectorType(ptype2, 2), VectorType(ptype3, 2));
insertBuiltIn(level, op, ext, VectorType(rvalue, 3), name, VectorType(ptype1, 3), VectorType(ptype2, 3), VectorType(ptype3, 3)); insertBuiltIn(level, op, ext, VectorType(rvalue, 3), name, VectorType(ptype1, 3), VectorType(ptype2, 3), VectorType(ptype3, 3));
insertBuiltIn(level, op, ext, VectorType(rvalue, 4), name, VectorType(ptype1, 4), VectorType(ptype2, 4), VectorType(ptype3, 4)); insertBuiltIn(level, op, ext, VectorType(rvalue, 4), name, VectorType(ptype1, 4), VectorType(ptype2, 4), VectorType(ptype3, 4));
...@@ -266,6 +272,7 @@ void TSymbolTable::insertBuiltIn(ESymbolLevel level, TOperator op, const char *e ...@@ -266,6 +272,7 @@ void TSymbolTable::insertBuiltIn(ESymbolLevel level, TOperator op, const char *e
function->addParameter(TConstParameter(ptype5)); function->addParameter(TConstParameter(ptype5));
} }
ASSERT(hasUnmangledBuiltIn(name));
insert(level, function); insert(level, function);
} }
} }
......
...@@ -405,18 +405,21 @@ class TSymbolTable : angle::NonCopyable ...@@ -405,18 +405,21 @@ class TSymbolTable : angle::NonCopyable
void insertBuiltIn(ESymbolLevel level, const TType *rvalue, const char *name, void insertBuiltIn(ESymbolLevel level, const TType *rvalue, const char *name,
const TType *ptype1, const TType *ptype2 = 0, const TType *ptype3 = 0, const TType *ptype4 = 0, const TType *ptype5 = 0) const TType *ptype1, const TType *ptype2 = 0, const TType *ptype3 = 0, const TType *ptype4 = 0, const TType *ptype5 = 0)
{ {
insertUnmangledBuiltIn(name);
insertBuiltIn(level, EOpNull, "", rvalue, name, ptype1, ptype2, ptype3, ptype4, ptype5); insertBuiltIn(level, EOpNull, "", rvalue, name, ptype1, ptype2, ptype3, ptype4, ptype5);
} }
void insertBuiltIn(ESymbolLevel level, const char *ext, const TType *rvalue, const char *name, void insertBuiltIn(ESymbolLevel level, const char *ext, const TType *rvalue, const char *name,
const TType *ptype1, const TType *ptype2 = 0, const TType *ptype3 = 0, const TType *ptype4 = 0, const TType *ptype5 = 0) const TType *ptype1, const TType *ptype2 = 0, const TType *ptype3 = 0, const TType *ptype4 = 0, const TType *ptype5 = 0)
{ {
insertUnmangledBuiltIn(name);
insertBuiltIn(level, EOpNull, ext, rvalue, name, ptype1, ptype2, ptype3, ptype4, ptype5); insertBuiltIn(level, EOpNull, ext, rvalue, name, ptype1, ptype2, ptype3, ptype4, ptype5);
} }
void insertBuiltIn(ESymbolLevel level, TOperator op, const TType *rvalue, const char *name, void insertBuiltIn(ESymbolLevel level, TOperator op, const TType *rvalue, const char *name,
const TType *ptype1, const TType *ptype2 = 0, const TType *ptype3 = 0, const TType *ptype4 = 0, const TType *ptype5 = 0) const TType *ptype1, const TType *ptype2 = 0, const TType *ptype3 = 0, const TType *ptype4 = 0, const TType *ptype5 = 0)
{ {
insertUnmangledBuiltIn(name);
insertBuiltIn(level, op, "", rvalue, name, ptype1, ptype2, ptype3, ptype4, ptype5); insertBuiltIn(level, op, "", rvalue, name, ptype1, ptype2, ptype3, ptype4, ptype5);
} }
...@@ -474,16 +477,29 @@ class TSymbolTable : angle::NonCopyable ...@@ -474,16 +477,29 @@ class TSymbolTable : angle::NonCopyable
return ++uniqueIdCounter; return ++uniqueIdCounter;
} }
bool hasUnmangledBuiltIn(const char *name)
{
return mUnmangledBuiltinNames.count(std::string(name)) > 0;
}
private: private:
ESymbolLevel currentLevel() const ESymbolLevel currentLevel() const
{ {
return static_cast<ESymbolLevel>(table.size() - 1); return static_cast<ESymbolLevel>(table.size() - 1);
} }
// Used to insert unmangled functions to check redeclaration of built-ins in ESSL 3.00.
void insertUnmangledBuiltIn(const char *name)
{
mUnmangledBuiltinNames.insert(std::string(name));
}
std::vector<TSymbolTableLevel *> table; std::vector<TSymbolTableLevel *> table;
typedef TMap<TBasicType, TPrecision> PrecisionStackLevel; typedef TMap<TBasicType, TPrecision> PrecisionStackLevel;
std::vector< PrecisionStackLevel *> precisionStack; std::vector< PrecisionStackLevel *> precisionStack;
std::set<std::string> mUnmangledBuiltinNames;
std::set<std::string> mInvariantVaryings; std::set<std::string> mInvariantVaryings;
bool mGlobalInvariant; bool mGlobalInvariant;
......
...@@ -1532,3 +1532,43 @@ TEST_F(MalformedShaderTest, ESSL300FragmentInvariantAll) ...@@ -1532,3 +1532,43 @@ TEST_F(MalformedShaderTest, ESSL300FragmentInvariantAll)
FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
} }
} }
// Built-in functions can be overloaded in ESSL 1.00.
TEST_F(MalformedShaderTest, ESSL100BuiltInFunctionOverload)
{
const std::string &shaderString =
"precision mediump float;\n"
"int sin(int x)\n"
"{\n"
" return int(sin(float(x)));\n"
"}\n"
"void main()\n"
"{\n"
" gl_FragColor = vec4(sin(1));"
"}\n";
if (!compile(shaderString))
{
FAIL() << "Shader compilation failed, expecting success " << mInfoLog;
}
}
// Built-in functions can not be overloaded in ESSL 3.00.
TEST_F(MalformedShaderTest, ESSL300BuiltInFunctionOverload)
{
const std::string &shaderString =
"#version 300 es\n"
"precision mediump float;\n"
"out vec4 my_FragColor;\n"
"int sin(int x)\n"
"{\n"
" return int(sin(float(x)));\n"
"}\n"
"void main()\n"
"{\n"
" my_FragColor = vec4(sin(1));"
"}\n";
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure " << 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