Always add most extension symbols to symbol table
An error will be generated either way if the extension symbols are
used incorrectly since each use of an extension function or variable
checks whether the extension is enabled.
We now also track extension in unmangled built-in names, so that
redefining built-ins of extensions that are not enabled can be
supported.
This includes refactoring the shader extension tests to share a common
helper class ShaderExtensionTest.
BUG=angleproject:2267
TEST=angle_unittests
Change-Id: I9cc5e9bd62fa07796e69256a6a9a493531a62446
Reviewed-on: https://chromium-review.googlesource.com/926526
Commit-Queue: Olli Etuaho <oetuaho@nvidia.com>
Reviewed-by: Jamie Madill <jmadill@chromium.org>
diff --git a/src/compiler/translator/ParseContext.cpp b/src/compiler/translator/ParseContext.cpp
index 474fdc4..bdfafa4 100644
--- a/src/compiler/translator/ParseContext.cpp
+++ b/src/compiler/translator/ParseContext.cpp
@@ -3228,7 +3228,7 @@
// first declaration. Either way the instance in the symbol table is used to track whether the
// function is declared multiple times.
bool hadPrototypeDeclaration = false;
- const TFunction *function = symbolTable.markUserDefinedFunctionHasPrototypeDeclaration(
+ const TFunction *function = symbolTable.markFunctionHasPrototypeDeclaration(
parsedFunction.getMangledName(), &hadPrototypeDeclaration);
if (hadPrototypeDeclaration && mShaderVersion == 100)
@@ -3282,22 +3282,12 @@
TIntermFunctionPrototype **prototypeOut)
{
ASSERT(function);
- const TSymbol *builtIn =
- symbolTable.findBuiltIn(ImmutableString(function->getMangledName()), getShaderVersion());
- if (builtIn)
+ bool wasDefined = false;
+ function = symbolTable.setFunctionParameterNamesFromDefinition(function, &wasDefined);
+ if (wasDefined)
{
- error(location, "built-in functions cannot be redefined", function->name());
- }
- else
- {
- bool wasDefined = false;
- function =
- symbolTable.setUserDefinedFunctionParameterNamesFromDefinition(function, &wasDefined);
- if (wasDefined)
- {
- error(location, "function already has a body", function->name());
- }
+ error(location, "function already has a body", function->name());
}
// Remember the return type for later checking for return statements.
@@ -3315,11 +3305,6 @@
// The definition production code will check for redefinitions.
// In the case of ESSL 1.00 the prototype production code will also check for redeclarations.
//
- // Return types and parameter qualifiers must match in all redeclarations, so those are checked
- // here.
- //
- const TFunction *prevDec = static_cast<const TFunction *>(
- symbolTable.find(ImmutableString(function->getMangledName()), getShaderVersion()));
for (size_t i = 0u; i < function->getParamCount(); ++i)
{
@@ -3332,15 +3317,36 @@
}
}
- if (getShaderVersion() >= 300 && symbolTable.hasUnmangledBuiltInForShaderVersion(
- function->name().data(), getShaderVersion()))
+ if (getShaderVersion() >= 300)
{
- // With ESSL 3.00 and above, 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->name());
+ const UnmangledBuiltIn *builtIn =
+ symbolTable.getUnmangledBuiltInForShaderVersion(function->name(), getShaderVersion());
+ if (builtIn &&
+ (builtIn->extension == TExtension::UNDEFINED || isExtensionEnabled(builtIn->extension)))
+ {
+ // With ESSL 3.00 and above, 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->name());
+ }
}
- else if (prevDec)
+ else
+ {
+ // ESSL 1.00.17 section 4.2.6: built-ins can be overloaded but not redefined. We assume that
+ // this applies to redeclarations as well.
+ const TSymbol *builtIn =
+ symbolTable.findBuiltIn(function->getMangledName(), getShaderVersion());
+ if (builtIn)
+ {
+ error(location, "built-in functions cannot be redefined", function->name());
+ }
+ }
+
+ // Return types and parameter qualifiers must match in all redeclarations, so those are checked
+ // here.
+ const TFunction *prevDec =
+ static_cast<const TFunction *>(symbolTable.findGlobal(function->getMangledName()));
+ if (prevDec)
{
if (prevDec->getReturnType() != function->getReturnType())
{