Track whether function declarations are prototypes, and only allow at most one prototype for ES 100.
git-svn-id: https://cvs.khronos.org/svn/repos/ogl/trunk/ecosystem/public/sdk/tools/glslang@24342 e7fa87d3-cd2b-0410-9028-fcbf551c1848
This commit is contained in:
parent
e1f0f5b31f
commit
b88c60b03f
@ -164,6 +164,16 @@ void foo323433()
|
|||||||
}
|
}
|
||||||
|
|
||||||
int fgfg(float f, mediump int i);
|
int fgfg(float f, mediump int i);
|
||||||
int fgfg(float f, highp int i); // ERROR, precision qualifier difference
|
int fgfg(float f, highp int i) { return 2; } // ERROR, precision qualifier difference
|
||||||
|
|
||||||
|
int fffg(float f);
|
||||||
|
int fffg(float f); // ERROR, can't have multiple prototypes
|
||||||
|
|
||||||
|
int gggf(float f);
|
||||||
|
int gggf(float f) { return 2; }
|
||||||
|
|
||||||
|
int agggf(float f) { return 2; }
|
||||||
|
int agggf(float f);
|
||||||
|
int agggf(float f); // ERROR, second prototype
|
||||||
|
|
||||||
uniform samplerExternalOES badExt; // syntax ERROR
|
uniform samplerExternalOES badExt; // syntax ERROR
|
||||||
|
@ -147,3 +147,13 @@ int[] foo213234(); // ERROR
|
|||||||
int foo234234(float[]); // ERROR
|
int foo234234(float[]); // ERROR
|
||||||
int foo234235(vec2[] v); // ERROR
|
int foo234235(vec2[] v); // ERROR
|
||||||
precision highp float[2]; // ERROR
|
precision highp float[2]; // ERROR
|
||||||
|
|
||||||
|
int fffg(float f);
|
||||||
|
int fffg(float f);
|
||||||
|
|
||||||
|
int gggf(float f);
|
||||||
|
int gggf(float f) { return 2; }
|
||||||
|
int gggf(float f);
|
||||||
|
|
||||||
|
int agggf(float f) { return 2; }
|
||||||
|
int agggf(float f);
|
||||||
|
@ -63,8 +63,10 @@ ERROR: 0:147: 'texture2DProjGradEXT' : required extension not requested: GL_EXT_
|
|||||||
ERROR: 0:151: 'floating-point suffix' : not supported for this version or the enabled extensions
|
ERROR: 0:151: 'floating-point suffix' : not supported for this version or the enabled extensions
|
||||||
ERROR: 0:152: 'floating-point suffix' : not supported for this version or the enabled extensions
|
ERROR: 0:152: 'floating-point suffix' : not supported for this version or the enabled extensions
|
||||||
ERROR: 0:167: 'highp' : overloaded functions must have the same parameter precision qualifiers for argument 2
|
ERROR: 0:167: 'highp' : overloaded functions must have the same parameter precision qualifiers for argument 2
|
||||||
ERROR: 0:169: '' : syntax error
|
ERROR: 0:170: 'multiple prototypes for same function' : not supported for this version or the enabled extensions
|
||||||
ERROR: 58 compilation errors. No code generated.
|
ERROR: 0:177: 'multiple prototypes for same function' : not supported for this version or the enabled extensions
|
||||||
|
ERROR: 0:179: '' : syntax error
|
||||||
|
ERROR: 60 compilation errors. No code generated.
|
||||||
|
|
||||||
|
|
||||||
ERROR: node is still EOpNull!
|
ERROR: node is still EOpNull!
|
||||||
@ -294,6 +296,28 @@ ERROR: node is still EOpNull!
|
|||||||
0:163 'f13' (invariant mediump float)
|
0:163 'f13' (invariant mediump float)
|
||||||
0:163 Construct vec3 (3-component vector of float)
|
0:163 Construct vec3 (3-component vector of float)
|
||||||
0:163 'f13' (invariant mediump float)
|
0:163 'f13' (invariant mediump float)
|
||||||
|
0:167 Function Definition: fgfg(f1;i1; (mediump int)
|
||||||
|
0:167 Function Parameters:
|
||||||
|
0:167 'f' (in mediump float)
|
||||||
|
0:167 'i' (in highp int)
|
||||||
|
0:167 Sequence
|
||||||
|
0:167 Branch: Return with expression
|
||||||
|
0:167 Constant:
|
||||||
|
0:167 2 (const int)
|
||||||
|
0:173 Function Definition: gggf(f1; (mediump int)
|
||||||
|
0:173 Function Parameters:
|
||||||
|
0:173 'f' (in mediump float)
|
||||||
|
0:173 Sequence
|
||||||
|
0:173 Branch: Return with expression
|
||||||
|
0:173 Constant:
|
||||||
|
0:173 2 (const int)
|
||||||
|
0:175 Function Definition: agggf(f1; (mediump int)
|
||||||
|
0:175 Function Parameters:
|
||||||
|
0:175 'f' (in mediump float)
|
||||||
|
0:175 Sequence
|
||||||
|
0:175 Branch: Return with expression
|
||||||
|
0:175 Constant:
|
||||||
|
0:175 2 (const int)
|
||||||
0:? Linker Objects
|
0:? Linker Objects
|
||||||
0:? 'a' (3-element array of mediump int)
|
0:? 'a' (3-element array of mediump int)
|
||||||
0:? 'uint' (mediump int)
|
0:? 'uint' (mediump int)
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
100scope.vert
|
100scope.vert
|
||||||
ERROR: 0:5: 'a' : redefinition
|
ERROR: 0:5: 'a' : redefinition
|
||||||
ERROR: 0:17: 'b' : redeclaration of existing name
|
ERROR: 0:17: 'b' : function name is redeclaration of existing name
|
||||||
ERROR: 0:19: 'f' : redefinition
|
ERROR: 0:19: 'f' : redefinition
|
||||||
ERROR: 0:21: 'redefinition of built-in function' : not supported with this profile: es
|
ERROR: 0:21: 'redefinition of built-in function' : not supported with this profile: es
|
||||||
ERROR: 0:22: 'redefinition of built-in function' : not supported with this profile: es
|
ERROR: 0:22: 'redefinition of built-in function' : not supported with this profile: es
|
||||||
|
@ -241,6 +241,20 @@ ERROR: node is still EOpNull!
|
|||||||
0:143 move second child to first child (3-element array of highp float)
|
0:143 move second child to first child (3-element array of highp float)
|
||||||
0:143 'w' (3-element array of highp float)
|
0:143 'w' (3-element array of highp float)
|
||||||
0:143 'y' (3-element array of highp float)
|
0:143 'y' (3-element array of highp float)
|
||||||
|
0:155 Function Definition: gggf(f1; (highp int)
|
||||||
|
0:155 Function Parameters:
|
||||||
|
0:155 'f' (in highp float)
|
||||||
|
0:155 Sequence
|
||||||
|
0:155 Branch: Return with expression
|
||||||
|
0:155 Constant:
|
||||||
|
0:155 2 (const int)
|
||||||
|
0:158 Function Definition: agggf(f1; (highp int)
|
||||||
|
0:158 Function Parameters:
|
||||||
|
0:158 'f' (in highp float)
|
||||||
|
0:158 Sequence
|
||||||
|
0:158 Branch: Return with expression
|
||||||
|
0:158 Constant:
|
||||||
|
0:158 2 (const int)
|
||||||
0:? Linker Objects
|
0:? Linker Objects
|
||||||
0:? 'm43' (uniform highp 4X3 matrix of float)
|
0:? 'm43' (uniform highp 4X3 matrix of float)
|
||||||
0:? 'm33' (uniform highp 3X3 matrix of float)
|
0:? 'm33' (uniform highp 3X3 matrix of float)
|
||||||
|
@ -1,15 +1,15 @@
|
|||||||
300scope.vert
|
300scope.vert
|
||||||
ERROR: 0:5: 'a' : redefinition
|
ERROR: 0:5: 'a' : redefinition
|
||||||
ERROR: 0:17: 'b' : redeclaration of existing name
|
ERROR: 0:17: 'b' : function name is redeclaration of existing name
|
||||||
ERROR: 0:19: 'f' : redefinition
|
ERROR: 0:19: 'f' : redefinition
|
||||||
ERROR: 0:20: 'tan' : redefinition
|
ERROR: 0:20: 'tan' : redefinition
|
||||||
ERROR: 0:21: 'redefinition of built-in function' : not supported with this profile: es
|
ERROR: 0:21: 'redefinition of built-in function' : not supported with this profile: es
|
||||||
ERROR: 0:21: 'sin' : redeclaration of existing name
|
ERROR: 0:21: 'sin' : function name is redeclaration of existing name
|
||||||
ERROR: 0:22: 'redefinition of built-in function' : not supported with this profile: es
|
ERROR: 0:22: 'redefinition of built-in function' : not supported with this profile: es
|
||||||
ERROR: 0:22: 'cos' : redeclaration of existing name
|
ERROR: 0:22: 'cos' : function name is redeclaration of existing name
|
||||||
ERROR: 0:22: 'cos' : function already has a body
|
ERROR: 0:22: 'cos' : function already has a body
|
||||||
ERROR: 0:24: 'return' : void function cannot return a value
|
ERROR: 0:24: 'return' : void function cannot return a value
|
||||||
ERROR: 0:26: 'radians' : redeclaration of existing name
|
ERROR: 0:26: 'radians' : function name is redeclaration of existing name
|
||||||
ERROR: 0:26: 'radians' : can't find function
|
ERROR: 0:26: 'radians' : can't find function
|
||||||
ERROR: 0:28: 'return' : void function cannot return a value
|
ERROR: 0:28: 'return' : void function cannot return a value
|
||||||
ERROR: 0:35: 'local function declaration' : not supported with this profile: es
|
ERROR: 0:35: 'local function declaration' : not supported with this profile: es
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
430scope.vert
|
430scope.vert
|
||||||
Warning, version 430 is not yet complete; some version-specific features are present, but many are missing.
|
Warning, version 430 is not yet complete; some version-specific features are present, but many are missing.
|
||||||
ERROR: 0:5: 'a' : redefinition
|
ERROR: 0:5: 'a' : redefinition
|
||||||
ERROR: 0:17: 'b' : redeclaration of existing name
|
ERROR: 0:17: 'b' : function name is redeclaration of existing name
|
||||||
ERROR: 0:19: 'f' : redefinition
|
ERROR: 0:19: 'f' : redefinition
|
||||||
ERROR: 0:54: 'z' : undeclared identifier
|
ERROR: 0:54: 'z' : undeclared identifier
|
||||||
ERROR: 0:54: 'z' : redefinition
|
ERROR: 0:54: 'z' : redefinition
|
||||||
|
@ -9,5 +9,5 @@
|
|||||||
// source have to figure out how to create revision.h just to get a build
|
// source have to figure out how to create revision.h just to get a build
|
||||||
// going. However, if it is not updated, it can be a version behind.
|
// going. However, if it is not updated, it can be a version behind.
|
||||||
|
|
||||||
#define GLSLANG_REVISION "24330"
|
#define GLSLANG_REVISION "24331"
|
||||||
#define GLSLANG_DATE "2013/12/04 09:43:00"
|
#define GLSLANG_DATE "2013/12/04 10:23:03"
|
||||||
|
@ -671,19 +671,20 @@ TIntermTyped* TParseContext::handleDotDereference(TSourceLoc loc, TIntermTyped*
|
|||||||
// Handle seeing a function declarator in the grammar. This is the precursor
|
// Handle seeing a function declarator in the grammar. This is the precursor
|
||||||
// to recognizing a function prototype or function definition.
|
// to recognizing a function prototype or function definition.
|
||||||
//
|
//
|
||||||
TFunction* TParseContext::handleFunctionDeclarator(TSourceLoc loc, TFunction& function)
|
TFunction* TParseContext::handleFunctionDeclarator(TSourceLoc loc, TFunction& function, bool prototype)
|
||||||
{
|
{
|
||||||
// ES can't declare prototypes inside functions
|
// ES can't declare prototypes inside functions
|
||||||
if (! symbolTable.atGlobalLevel())
|
if (! symbolTable.atGlobalLevel())
|
||||||
requireProfile(loc, ~EEsProfile, "local function declaration");
|
requireProfile(loc, ~EEsProfile, "local function declaration");
|
||||||
|
|
||||||
//
|
//
|
||||||
// Multiple declarations of the same function are allowed.
|
// Multiple declarations of the same function name are allowed.
|
||||||
//
|
//
|
||||||
// If this is a definition, the definition production code will check for redefinitions
|
// If this is a definition, the definition production code will check for redefinitions
|
||||||
// (we don't know at this point if it's a definition or not).
|
// (we don't know at this point if it's a definition or not).
|
||||||
//
|
//
|
||||||
// Redeclarations (full prototype match) are allowed. But, return types and parameter qualifiers must match.
|
// Redeclarations (full signature match) are allowed. But, return types and parameter qualifiers must also match.
|
||||||
|
// - except ES 100, which only allows a single prototype
|
||||||
//
|
//
|
||||||
// ES 100 does not allow redefining, but does allow overloading of built-in functions.
|
// ES 100 does not allow redefining, but does allow overloading of built-in functions.
|
||||||
// ES 300 does not allow redefining or overloading of built-in functions.
|
// ES 300 does not allow redefining or overloading of built-in functions.
|
||||||
@ -694,9 +695,10 @@ TFunction* TParseContext::handleFunctionDeclarator(TSourceLoc loc, TFunction& fu
|
|||||||
requireProfile(loc, ~EEsProfile, "redefinition of built-in function");
|
requireProfile(loc, ~EEsProfile, "redefinition of built-in function");
|
||||||
const TFunction* prevDec = symbol ? symbol->getAsFunction() : 0;
|
const TFunction* prevDec = symbol ? symbol->getAsFunction() : 0;
|
||||||
if (prevDec) {
|
if (prevDec) {
|
||||||
if (prevDec->getType() != function.getType()) {
|
if (prevDec->isPrototyped() && prototype)
|
||||||
|
profileRequires(loc, EEsProfile, 300, 0, "multiple prototypes for same function");
|
||||||
|
if (prevDec->getType() != function.getType())
|
||||||
error(loc, "overloaded functions must have the same return type", function.getType().getBasicTypeString().c_str(), "");
|
error(loc, "overloaded functions must have the same return type", function.getType().getBasicTypeString().c_str(), "");
|
||||||
}
|
|
||||||
for (int i = 0; i < prevDec->getParamCount(); ++i) {
|
for (int i = 0; i < prevDec->getParamCount(); ++i) {
|
||||||
if ((*prevDec)[i].type->getQualifier().storage != function[i].type->getQualifier().storage)
|
if ((*prevDec)[i].type->getQualifier().storage != function[i].type->getQualifier().storage)
|
||||||
error(loc, "overloaded functions must have the same parameter storage qualifiers for argument", function[i].type->getStorageQualifierString(), "%d", i+1);
|
error(loc, "overloaded functions must have the same parameter storage qualifiers for argument", function[i].type->getStorageQualifierString(), "%d", i+1);
|
||||||
@ -708,16 +710,26 @@ TFunction* TParseContext::handleFunctionDeclarator(TSourceLoc loc, TFunction& fu
|
|||||||
|
|
||||||
arrayObjectCheck(loc, function.getType(), "array in function return type");
|
arrayObjectCheck(loc, function.getType(), "array in function return type");
|
||||||
|
|
||||||
// All built-in functions are defined, even though they don't have a body.
|
if (prototype) {
|
||||||
if (symbolTable.atBuiltInLevel())
|
// All built-in functions are defined, even though they don't have a body.
|
||||||
function.setDefined();
|
// Count their prototype as a definition instead.
|
||||||
|
if (symbolTable.atBuiltInLevel())
|
||||||
|
function.setDefined();
|
||||||
|
else {
|
||||||
|
if (prevDec && ! builtIn)
|
||||||
|
symbol->getAsFunction()->setPrototyped(); // need a writable one, but like having prevDec as a const
|
||||||
|
function.setPrototyped();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This insert won't actually insert it if it's a duplicate signature, but it will still check for
|
||||||
|
// other forms of name collisions.
|
||||||
if (! symbolTable.insert(function))
|
if (! symbolTable.insert(function))
|
||||||
error(loc, "redeclaration of existing name", function.getName().c_str(), "");
|
error(loc, "function name is redeclaration of existing name", function.getName().c_str(), "");
|
||||||
|
|
||||||
//
|
//
|
||||||
// If this is a redeclaration, it could also be a definition,
|
// If this is a redeclaration, it could also be a definition,
|
||||||
// in which case, we want to use the variable names from this one, and not the one that's
|
// in which case, we need to use the parameter names from this one, and not the one that's
|
||||||
// being redeclared. So, pass back this declaration, not the one in the symbol table.
|
// being redeclared. So, pass back this declaration, not the one in the symbol table.
|
||||||
//
|
//
|
||||||
return &function;
|
return &function;
|
||||||
|
@ -88,7 +88,7 @@ public:
|
|||||||
void checkInputArrayConsistency(TSourceLoc, bool tailOnly = false);
|
void checkInputArrayConsistency(TSourceLoc, bool tailOnly = false);
|
||||||
void checkInputArrayConsistency(TSourceLoc, TLayoutGeometry, TType&, const TString&);
|
void checkInputArrayConsistency(TSourceLoc, TLayoutGeometry, TType&, const TString&);
|
||||||
TIntermTyped* handleDotDereference(TSourceLoc, TIntermTyped* base, TString& field);
|
TIntermTyped* handleDotDereference(TSourceLoc, TIntermTyped* base, TString& field);
|
||||||
TFunction* handleFunctionDeclarator(TSourceLoc loc, TFunction& function);
|
TFunction* handleFunctionDeclarator(TSourceLoc loc, TFunction& function, bool prototype);
|
||||||
TIntermAggregate* handleFunctionDefinition(TSourceLoc, TFunction&);
|
TIntermAggregate* handleFunctionDefinition(TSourceLoc, TFunction&);
|
||||||
TIntermTyped* handleFunctionCall(TSourceLoc, TFunction*, TIntermNode*, TIntermAggregate*);
|
TIntermTyped* handleFunctionCall(TSourceLoc, TFunction*, TIntermNode*, TIntermAggregate*);
|
||||||
void nonOpBuiltInCheck(TSourceLoc, const TFunction&, TIntermAggregate&);
|
void nonOpBuiltInCheck(TSourceLoc, const TFunction&, TIntermAggregate&);
|
||||||
|
@ -286,6 +286,7 @@ TFunction::TFunction(const TFunction& copyOf) : TSymbol(copyOf)
|
|||||||
mangledName = copyOf.mangledName;
|
mangledName = copyOf.mangledName;
|
||||||
op = copyOf.op;
|
op = copyOf.op;
|
||||||
defined = copyOf.defined;
|
defined = copyOf.defined;
|
||||||
|
prototyped = copyOf.prototyped;
|
||||||
}
|
}
|
||||||
|
|
||||||
TFunction* TFunction::clone() const
|
TFunction* TFunction::clone() const
|
||||||
|
@ -194,12 +194,12 @@ public:
|
|||||||
explicit TFunction(TOperator o) :
|
explicit TFunction(TOperator o) :
|
||||||
TSymbol(0),
|
TSymbol(0),
|
||||||
op(o),
|
op(o),
|
||||||
defined(false) { }
|
defined(false), prototyped(false) { }
|
||||||
TFunction(const TString *name, const TType& retType, TOperator tOp = EOpNull) :
|
TFunction(const TString *name, const TType& retType, TOperator tOp = EOpNull) :
|
||||||
TSymbol(name),
|
TSymbol(name),
|
||||||
mangledName(*name + '('),
|
mangledName(*name + '('),
|
||||||
op(tOp),
|
op(tOp),
|
||||||
defined(false) { returnType.shallowCopy(retType); }
|
defined(false), prototyped(false) { returnType.shallowCopy(retType); }
|
||||||
virtual TFunction* clone() const;
|
virtual TFunction* clone() const;
|
||||||
virtual ~TFunction();
|
virtual ~TFunction();
|
||||||
|
|
||||||
@ -220,6 +220,8 @@ public:
|
|||||||
virtual TOperator getBuiltInOp() const { return op; }
|
virtual TOperator getBuiltInOp() const { return op; }
|
||||||
virtual void setDefined() { assert(writable); defined = true; }
|
virtual void setDefined() { assert(writable); defined = true; }
|
||||||
virtual bool isDefined() const { return defined; }
|
virtual bool isDefined() const { return defined; }
|
||||||
|
virtual void setPrototyped() { assert(writable); prototyped = true; }
|
||||||
|
virtual bool isPrototyped() const { return prototyped; }
|
||||||
|
|
||||||
virtual int getParamCount() const { return static_cast<int>(parameters.size()); }
|
virtual int getParamCount() const { return static_cast<int>(parameters.size()); }
|
||||||
virtual TParameter& operator[](int i) { assert(writable); return parameters[i]; }
|
virtual TParameter& operator[](int i) { assert(writable); return parameters[i]; }
|
||||||
@ -237,6 +239,7 @@ protected:
|
|||||||
TString mangledName;
|
TString mangledName;
|
||||||
TOperator op;
|
TOperator op;
|
||||||
bool defined;
|
bool defined;
|
||||||
|
bool prototyped;
|
||||||
};
|
};
|
||||||
|
|
||||||
class TAnonMember : public TSymbol {
|
class TAnonMember : public TSymbol {
|
||||||
|
@ -748,6 +748,7 @@ constant_expression
|
|||||||
|
|
||||||
declaration
|
declaration
|
||||||
: function_prototype SEMICOLON {
|
: function_prototype SEMICOLON {
|
||||||
|
parseContext.handleFunctionDeclarator($1.loc, *$1.function, true /* prototype */);
|
||||||
$$ = 0;
|
$$ = 0;
|
||||||
// TODO: 4.0 functionality: subroutines: make the identifier a user type for this signature
|
// TODO: 4.0 functionality: subroutines: make the identifier a user type for this signature
|
||||||
}
|
}
|
||||||
@ -820,7 +821,7 @@ identifier_list
|
|||||||
|
|
||||||
function_prototype
|
function_prototype
|
||||||
: function_declarator RIGHT_PAREN {
|
: function_declarator RIGHT_PAREN {
|
||||||
$$.function = parseContext.handleFunctionDeclarator($2.loc, *$1);
|
$$.function = $1;
|
||||||
$$.loc = $2.loc;
|
$$.loc = $2.loc;
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
@ -2389,6 +2390,7 @@ external_declaration
|
|||||||
|
|
||||||
function_definition
|
function_definition
|
||||||
: function_prototype {
|
: function_prototype {
|
||||||
|
$1.function = parseContext.handleFunctionDeclarator($1.loc, *$1.function, false /* not prototype */);
|
||||||
$1.intermAggregate = parseContext.handleFunctionDefinition($1.loc, *$1.function);
|
$1.intermAggregate = parseContext.handleFunctionDefinition($1.loc, *$1.function);
|
||||||
}
|
}
|
||||||
compound_statement_no_new_scope {
|
compound_statement_no_new_scope {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user