diff --git a/Test/100.frag b/Test/100.frag index 51e2c5f006bc1b54673d82d1be3dbe247f1874c5..d6e62a0c8911c1ff29393f0b01420e72256ffcf3 100644 --- a/Test/100.frag +++ b/Test/100.frag @@ -164,6 +164,16 @@ void foo323433() } 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 diff --git a/Test/300.vert b/Test/300.vert index a5d06c3e58308d8d01a1791c8773fdf1a286b6f3..29453cfa2b515877c43d7359fff485841cc1e52f 100644 --- a/Test/300.vert +++ b/Test/300.vert @@ -147,3 +147,13 @@ int[] foo213234(); // ERROR int foo234234(float[]); // ERROR int foo234235(vec2[] v); // 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); diff --git a/Test/baseResults/100.frag.out b/Test/baseResults/100.frag.out index 4a53c1c7e8f9cba7b3c0122ba89908013e294aa2..83a7ce14a1016064ed1553c156c511a4f39ef239 100644 --- a/Test/baseResults/100.frag.out +++ b/Test/baseResults/100.frag.out @@ -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: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:169: '' : syntax error -ERROR: 58 compilation errors. No code generated. +ERROR: 0:170: 'multiple prototypes for same function' : not supported for this version or the enabled extensions +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! @@ -294,6 +296,28 @@ ERROR: node is still EOpNull! 0:163 'f13' (invariant mediump float) 0:163 Construct vec3 (3-component vector of 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:? 'a' (3-element array of mediump int) 0:? 'uint' (mediump int) diff --git a/Test/baseResults/100scope.vert.out b/Test/baseResults/100scope.vert.out index 02f1ad413939125521c7808ff63975e1c01ad15f..0063ec5fa70f48491a5040ad71d914bf5b89681b 100644 --- a/Test/baseResults/100scope.vert.out +++ b/Test/baseResults/100scope.vert.out @@ -1,6 +1,6 @@ 100scope.vert 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: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 diff --git a/Test/baseResults/300.vert.out b/Test/baseResults/300.vert.out index c70fc558a20a94f979f736d897abb456c983268f..156914dbf40e0f018d0d2b805bf06cb006ca3163 100644 --- a/Test/baseResults/300.vert.out +++ b/Test/baseResults/300.vert.out @@ -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 'w' (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:? 'm43' (uniform highp 4X3 matrix of float) 0:? 'm33' (uniform highp 3X3 matrix of float) diff --git a/Test/baseResults/300scope.vert.out b/Test/baseResults/300scope.vert.out index aa7f37e42655fc183e9377b10fdb6d552ac8da5b..a51f24aac46d235689db56f308150664545bc1de 100644 --- a/Test/baseResults/300scope.vert.out +++ b/Test/baseResults/300scope.vert.out @@ -1,15 +1,15 @@ 300scope.vert 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:20: 'tan' : redefinition 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: '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: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:28: 'return' : void function cannot return a value ERROR: 0:35: 'local function declaration' : not supported with this profile: es diff --git a/Test/baseResults/430scope.vert.out b/Test/baseResults/430scope.vert.out index c87f3ee54958ea57c989889d92406fc896f2219e..1dcd5f66a71b1c66fc12cf3b26640e7208aaa6c2 100644 --- a/Test/baseResults/430scope.vert.out +++ b/Test/baseResults/430scope.vert.out @@ -1,7 +1,7 @@ 430scope.vert Warning, version 430 is not yet complete; some version-specific features are present, but many are missing. 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:54: 'z' : undeclared identifier ERROR: 0:54: 'z' : redefinition diff --git a/glslang/Include/revision.h b/glslang/Include/revision.h index 3712b7b6b4671f19c4dbedc8c4b18d234892e5e3..b2ae399208948053460255db3eb383f0ee4e6a7a 100644 --- a/glslang/Include/revision.h +++ b/glslang/Include/revision.h @@ -9,5 +9,5 @@ // 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. -#define GLSLANG_REVISION "24330" -#define GLSLANG_DATE "2013/12/04 09:43:00" +#define GLSLANG_REVISION "24331" +#define GLSLANG_DATE "2013/12/04 10:23:03" diff --git a/glslang/MachineIndependent/ParseHelper.cpp b/glslang/MachineIndependent/ParseHelper.cpp index f1cddb5403a985d597df93417ffd0b47ca27734a..cb74ed65975bec02c7e196f1278efa5808a29b0a 100644 --- a/glslang/MachineIndependent/ParseHelper.cpp +++ b/glslang/MachineIndependent/ParseHelper.cpp @@ -671,19 +671,20 @@ TIntermTyped* TParseContext::handleDotDereference(TSourceLoc loc, TIntermTyped* // Handle seeing a function declarator in the grammar. This is the precursor // 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 if (! symbolTable.atGlobalLevel()) 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 // (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 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"); const TFunction* prevDec = symbol ? symbol->getAsFunction() : 0; 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(), ""); - } for (int i = 0; i < prevDec->getParamCount(); ++i) { 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); @@ -708,16 +710,26 @@ TFunction* TParseContext::handleFunctionDeclarator(TSourceLoc loc, TFunction& fu arrayObjectCheck(loc, function.getType(), "array in function return type"); - // All built-in functions are defined, even though they don't have a body. - if (symbolTable.atBuiltInLevel()) - function.setDefined(); + if (prototype) { + // All built-in functions are defined, even though they don't have a body. + // 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)) - 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, - // 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. // return &function; diff --git a/glslang/MachineIndependent/ParseHelper.h b/glslang/MachineIndependent/ParseHelper.h index 69044b110b457a01dd881250adee2bbce073f402..2df405701990bad89383471f94d56a0237790b43 100644 --- a/glslang/MachineIndependent/ParseHelper.h +++ b/glslang/MachineIndependent/ParseHelper.h @@ -88,7 +88,7 @@ public: void checkInputArrayConsistency(TSourceLoc, bool tailOnly = false); void checkInputArrayConsistency(TSourceLoc, TLayoutGeometry, TType&, const TString&); 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&); TIntermTyped* handleFunctionCall(TSourceLoc, TFunction*, TIntermNode*, TIntermAggregate*); void nonOpBuiltInCheck(TSourceLoc, const TFunction&, TIntermAggregate&); diff --git a/glslang/MachineIndependent/SymbolTable.cpp b/glslang/MachineIndependent/SymbolTable.cpp index 6a703249177dda799986683d8495142cb3b0d853..9c18a7a3e824da654468b7d37990c17c9049548c 100644 --- a/glslang/MachineIndependent/SymbolTable.cpp +++ b/glslang/MachineIndependent/SymbolTable.cpp @@ -286,6 +286,7 @@ TFunction::TFunction(const TFunction& copyOf) : TSymbol(copyOf) mangledName = copyOf.mangledName; op = copyOf.op; defined = copyOf.defined; + prototyped = copyOf.prototyped; } TFunction* TFunction::clone() const diff --git a/glslang/MachineIndependent/SymbolTable.h b/glslang/MachineIndependent/SymbolTable.h index bd1a5c9c98646a957c572f41a60a870dcc73fa87..71f07f5c1900b7b9ff883c7fd8b4b0b85880162f 100644 --- a/glslang/MachineIndependent/SymbolTable.h +++ b/glslang/MachineIndependent/SymbolTable.h @@ -194,12 +194,12 @@ public: explicit TFunction(TOperator o) : TSymbol(0), op(o), - defined(false) { } + defined(false), prototyped(false) { } TFunction(const TString *name, const TType& retType, TOperator tOp = EOpNull) : TSymbol(name), mangledName(*name + '('), op(tOp), - defined(false) { returnType.shallowCopy(retType); } + defined(false), prototyped(false) { returnType.shallowCopy(retType); } virtual TFunction* clone() const; virtual ~TFunction(); @@ -220,6 +220,8 @@ public: virtual TOperator getBuiltInOp() const { return op; } virtual void setDefined() { assert(writable); defined = true; } 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 TParameter& operator[](int i) { assert(writable); return parameters[i]; } @@ -237,6 +239,7 @@ protected: TString mangledName; TOperator op; bool defined; + bool prototyped; }; class TAnonMember : public TSymbol { diff --git a/glslang/MachineIndependent/glslang.y b/glslang/MachineIndependent/glslang.y index 3b21c6f13f12f3b6315db6bff1590387a9c0c13b..087d7ebefcaa28df4991027108ff49d5c9fd8515 100644 --- a/glslang/MachineIndependent/glslang.y +++ b/glslang/MachineIndependent/glslang.y @@ -748,6 +748,7 @@ constant_expression declaration : function_prototype SEMICOLON { + parseContext.handleFunctionDeclarator($1.loc, *$1.function, true /* prototype */); $$ = 0; // TODO: 4.0 functionality: subroutines: make the identifier a user type for this signature } @@ -820,7 +821,7 @@ identifier_list function_prototype : function_declarator RIGHT_PAREN { - $$.function = parseContext.handleFunctionDeclarator($2.loc, *$1); + $$.function = $1; $$.loc = $2.loc; } ; @@ -2389,6 +2390,7 @@ external_declaration function_definition : function_prototype { + $1.function = parseContext.handleFunctionDeclarator($1.loc, *$1.function, false /* not prototype */); $1.intermAggregate = parseContext.handleFunctionDefinition($1.loc, *$1.function); } compound_statement_no_new_scope {