Commit b88c60b0 by John Kessenich

Track whether function declarations are prototypes, and only allow at most one…

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
parent e1f0f5b3
...@@ -164,6 +164,16 @@ void foo323433() ...@@ -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 ...@@ -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_ ...@@ -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! ...@@ -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)
......
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! ...@@ -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)
......
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
......
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 @@ ...@@ -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* ...@@ -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 ...@@ -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 ...@@ -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: ...@@ -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) ...@@ -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: ...@@ -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: ...@@ -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: ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 {
......
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