Commit 5d653186 by Olli Etuaho

Disallow multiple function prototypes in ESSL 1.00

The same function can't be declared twice in ESSL 1.00. In ESSL 3.00 this is allowed. A function prototype following the definition of that function is not interpreted as redeclaration, and the shader compiler continues to allow this. BUG=angleproject:1067 TEST=angle_unittests, dEQP-GLES2.functional.shaders.functions.invalid.double_declare* Change-Id: I6d2ddafd456d378d92839600f19069ad1cd19aff Reviewed-on: https://chromium-review.googlesource.com/320082 Tryjob-Request: Olli Etuaho <oetuaho@nvidia.com> Tested-by: 's avatarOlli Etuaho <oetuaho@nvidia.com> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent ee63f5d9
...@@ -1928,6 +1928,20 @@ void TParseContext::parseGlobalLayoutQualifier(const TPublicType &typeQualifier) ...@@ -1928,6 +1928,20 @@ void TParseContext::parseGlobalLayoutQualifier(const TPublicType &typeQualifier)
TIntermAggregate *TParseContext::addFunctionPrototypeDeclaration(const TFunction &function, TIntermAggregate *TParseContext::addFunctionPrototypeDeclaration(const TFunction &function,
const TSourceLoc &location) const TSourceLoc &location)
{ {
// Note: symbolTableFunction could be the same as function if this is the first declaration.
// Either way the instance in the symbol table is used to track whether the function is declared
// multiple times.
TFunction *symbolTableFunction =
static_cast<TFunction *>(symbolTable.find(function.getMangledName(), getShaderVersion()));
if (symbolTableFunction->hasPrototypeDeclaration() && mShaderVersion == 100)
{
// ESSL 1.00.17 section 4.2.7.
// Doesn't apply to ESSL 3.00.4: see section 4.2.3.
error(location, "duplicate function prototype declarations are not allowed", "function");
recover();
}
symbolTableFunction->setHasPrototypeDeclaration();
TIntermAggregate *prototype = new TIntermAggregate; TIntermAggregate *prototype = new TIntermAggregate;
prototype->setType(function.getReturnType()); prototype->setType(function.getReturnType());
prototype->setName(function.getMangledName()); prototype->setName(function.getMangledName());
...@@ -2086,12 +2100,12 @@ void TParseContext::parseFunctionPrototype(const TSourceLoc &location, ...@@ -2086,12 +2100,12 @@ void TParseContext::parseFunctionPrototype(const TSourceLoc &location,
TFunction *TParseContext::parseFunctionDeclarator(const TSourceLoc &location, TFunction *function) TFunction *TParseContext::parseFunctionDeclarator(const TSourceLoc &location, TFunction *function)
{ {
// //
// Multiple declarations of the same function are allowed. // We don't know at this point whether this is a function definition or a prototype.
// // The definition production code will check for redefinitions.
// If this is a definition, the definition production code will check for redefinitions // In the case of ESSL 1.00 the prototype production code will also check for redeclarations.
// (we don't know at this point if it's a definition or not).
// //
// Redeclarations are allowed. But, return types and parameter qualifiers must match. // Return types and parameter qualifiers must match in all redeclarations, so those are checked
// here.
// //
TFunction *prevDec = TFunction *prevDec =
static_cast<TFunction *>(symbolTable.find(function->getMangledName(), getShaderVersion())); static_cast<TFunction *>(symbolTable.find(function->getMangledName(), getShaderVersion()));
......
...@@ -197,12 +197,16 @@ struct TParameter ...@@ -197,12 +197,16 @@ struct TParameter
class TFunction : public TSymbol class TFunction : public TSymbol
{ {
public: public:
TFunction(const TString *name, const TType *retType, TOperator tOp = EOpNull, const char *ext = "") TFunction(const TString *name,
const TType *retType,
TOperator tOp = EOpNull,
const char *ext = "")
: TSymbol(name), : TSymbol(name),
returnType(retType), returnType(retType),
mangledName(nullptr), mangledName(nullptr),
op(tOp), op(tOp),
defined(false) defined(false),
mHasPrototypeDeclaration(false)
{ {
relateToExtension(ext); relateToExtension(ext);
} }
...@@ -242,14 +246,10 @@ class TFunction : public TSymbol ...@@ -242,14 +246,10 @@ class TFunction : public TSymbol
return op; return op;
} }
void setDefined() void setDefined() { defined = true; }
{ bool isDefined() { return defined; }
defined = true; void setHasPrototypeDeclaration() { mHasPrototypeDeclaration = true; }
} bool hasPrototypeDeclaration() const { return mHasPrototypeDeclaration; }
bool isDefined()
{
return defined;
}
size_t getParamCount() const size_t getParamCount() const
{ {
...@@ -269,6 +269,7 @@ class TFunction : public TSymbol ...@@ -269,6 +269,7 @@ class TFunction : public TSymbol
mutable const TString *mangledName; mutable const TString *mangledName;
TOperator op; TOperator op;
bool defined; bool defined;
bool mHasPrototypeDeclaration;
}; };
// Interface block name sub-symbol // Interface block name sub-symbol
......
...@@ -1454,3 +1454,43 @@ TEST_F(MalformedShaderTest, NonIntegerIndex) ...@@ -1454,3 +1454,43 @@ TEST_F(MalformedShaderTest, NonIntegerIndex)
FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
} }
} }
// ESSL1 shaders with a duplicate function prototype should be rejected.
// ESSL 1.00.17 section 4.2.7.
TEST_F(MalformedShaderTest, DuplicatePrototypeESSL1)
{
const std::string &shaderString =
"precision mediump float;\n"
"void foo();\n"
"void foo();\n"
"void foo() {}\n"
"void main()\n"
"{\n"
" gl_FragColor = vec4(0.0);\n"
"}\n";
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
}
}
// ESSL3 shaders with a duplicate function prototype should be allowed.
// ESSL 3.00.4 section 4.2.3.
TEST_F(MalformedShaderTest, DuplicatePrototypeESSL3)
{
const std::string &shaderString =
"#version 300 es\n"
"precision mediump float;\n"
"out vec4 my_FragColor;\n"
"void foo();\n"
"void foo();\n"
"void foo() {}\n"
"void main()\n"
"{\n"
" my_FragColor = vec4(0.0);\n"
"}\n";
if (!compile(shaderString))
{
FAIL() << "Shader compilation failed, expecting success " << mInfoLog;
}
}
...@@ -256,8 +256,6 @@ ...@@ -256,8 +256,6 @@
989 WIN LINUX MAC : dEQP-GLES2.functional.shaders.preprocessor.extensions.after_non_preprocessing_tokens_fragment = FAIL 989 WIN LINUX MAC : dEQP-GLES2.functional.shaders.preprocessor.extensions.after_non_preprocessing_tokens_fragment = FAIL
1015 WIN LINUX MAC : dEQP-GLES2.functional.shaders.functions.invalid.return_array_in_struct_vertex = FAIL 1015 WIN LINUX MAC : dEQP-GLES2.functional.shaders.functions.invalid.return_array_in_struct_vertex = FAIL
1015 WIN LINUX MAC : dEQP-GLES2.functional.shaders.functions.invalid.return_array_in_struct_fragment = FAIL 1015 WIN LINUX MAC : dEQP-GLES2.functional.shaders.functions.invalid.return_array_in_struct_fragment = FAIL
996 WIN LINUX MAC : dEQP-GLES2.functional.shaders.functions.invalid.double_declare_vertex = FAIL
996 WIN LINUX MAC : dEQP-GLES2.functional.shaders.functions.invalid.double_declare_fragment = FAIL
1016 WIN LINUX MAC : dEQP-GLES2.functional.shaders.scoping.valid.local_variable_hides_function_parameter_vertex = FAIL 1016 WIN LINUX MAC : dEQP-GLES2.functional.shaders.scoping.valid.local_variable_hides_function_parameter_vertex = FAIL
1016 WIN LINUX MAC : dEQP-GLES2.functional.shaders.scoping.valid.local_variable_hides_function_parameter_fragment = FAIL 1016 WIN LINUX MAC : dEQP-GLES2.functional.shaders.scoping.valid.local_variable_hides_function_parameter_fragment = FAIL
1016 WIN LINUX MAC : dEQP-GLES2.functional.shaders.scoping.invalid.redeclare_function_vertex = FAIL 1016 WIN LINUX MAC : dEQP-GLES2.functional.shaders.scoping.invalid.redeclare_function_vertex = FAIL
......
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