From 0d22e31c7576e0f80bea07b9bd265b633ff3c066 Mon Sep 17 00:00:00 2001
From: John Kessenich <cepheus@frii.com>
Date: Wed, 30 Oct 2013 23:17:34 +0000
Subject: [PATCH] Implement 1.20 style function signature matching under
 implicit conversion.  This was the last key unimplemented feature of versions
 120 through 330.

git-svn-id: https://cvs.khronos.org/svn/repos/ogl/trunk/ecosystem/public/sdk/tools/glslang@23798 e7fa87d3-cd2b-0410-9028-fcbf551c1848
---
 Test/120.vert                                |  59 ++++++++++
 Test/baseResults/120.frag.out                |   1 -
 Test/baseResults/120.vert.out                | 102 +++++++++++++++-
 Test/baseResults/always-discard.frag.out     |   1 -
 Test/baseResults/always-discard2.frag.out    |   1 -
 Test/baseResults/conditionalDiscard.frag.out |   1 -
 Test/baseResults/cppIndent.vert.out          |   1 -
 Test/baseResults/cppNest.vert.out            |   1 -
 Test/baseResults/cppSimple.vert.out          |   1 -
 Test/baseResults/decls.frag.out              |   1 -
 Test/baseResults/deepRvalue.frag.out         |   1 -
 Test/baseResults/discard-dce.frag.out        |   1 -
 Test/baseResults/doWhileLoop.frag.out        |   1 -
 Test/baseResults/earlyReturnDiscard.frag.out |   1 -
 Test/baseResults/empty.frag.out              |   1 -
 Test/baseResults/flowControl.frag.out        |   1 -
 Test/baseResults/forLoop.frag.out            |   1 -
 Test/baseResults/forwardRef.frag.out         |   1 -
 Test/baseResults/length.frag.out             |   1 -
 Test/baseResults/mains1.frag.out             |   2 -
 Test/baseResults/matrixError.vert.out        |   1 -
 Test/baseResults/nonSquare.vert.out          |   1 -
 Test/baseResults/sample.frag.out             |   1 -
 Test/baseResults/sample.vert.out             |   1 -
 Test/baseResults/swizzle.frag.out            |   1 -
 Test/baseResults/syntaxError.frag.out        |   1 -
 Test/baseResults/test.frag.out               |   1 -
 Test/baseResults/versionsErrors.frag.out     |   1 -
 Test/baseResults/voidFunction.frag.out       |   1 -
 Test/baseResults/whileLoop.frag.out          |   1 -
 Todo.txt                                     |   2 +-
 glslang/Include/Types.h                      |  22 +++-
 glslang/MachineIndependent/ParseHelper.cpp   | 116 ++++++++++++++++---
 glslang/MachineIndependent/ParseHelper.h     |   5 +-
 glslang/MachineIndependent/ShaderLang.cpp    |   5 +-
 glslang/MachineIndependent/SymbolTable.h     |  36 +++++-
 36 files changed, 317 insertions(+), 59 deletions(-)

diff --git a/Test/120.vert b/Test/120.vert
index 9c31d1ac7..b1f69480e 100644
--- a/Test/120.vert
+++ b/Test/120.vert
@@ -51,3 +51,62 @@ int[2][3] foo(                 // ERROR
               float[2][3] a,   // ERROR
               float[2] b[3],   // ERROR
               float c[2][3]);  // ERROR
+
+int overloadA(in float f);
+int overloadA(out float f);        // ERROR, different qualifiers
+float overloadA(float);            // ERROR, different return value for same signature
+float overloadA(out float f, int);
+float overloadA(int i);
+
+vec2 overloadB(float, float);
+
+vec2 overloadC(int, int);
+vec2 overloadC(int, float);
+vec2 overloadC(float, int);
+vec2 overloadC(vec2, vec2);
+
+vec3 overloadD(int, float);
+vec3 overloadD(float, int);
+
+vec3 overloadE(float[2]);
+vec3 overloadE(mat2 m);
+vec3 overloadE(vec2 v);
+
+void foo()
+{
+    float f;
+    int i;
+
+    overloadB(f, f);
+    overloadB(f, 2);
+    overloadB(1, i);
+
+    overloadC(1, i);
+    overloadC(vec2(1), vec2(2));
+    overloadC(f, 3.0);           // ERROR, no way
+    overloadC(ivec2(1), vec2(2));
+
+    overloadD(i, f);
+    overloadD(f, i);
+    overloadD(i, i);   // ERROR, ambiguous
+
+    int overloadB;     // hiding
+    overloadB(1, i);   // ERROR
+
+    sin(1);
+    texture2D(s2D, ivec2(0));
+    clamp(attv4, 0, 1);
+    clamp(ivec4(attv4), 0, 1);
+
+    int a[2];
+    overloadC(a, 3); // ERROR
+    overloadE(a);    // ERROR
+    overloadE(3.3);  // ERROR
+    overloadE(vec2(3.3));
+    overloadE(mat2(0.5));
+    overloadE(ivec4(1)); // ERROR
+    overloadE(ivec2(1));
+
+    float b[2];
+    overloadE(b);
+}
diff --git a/Test/baseResults/120.frag.out b/Test/baseResults/120.frag.out
index a550fee2e..3b8bd701d 100644
--- a/Test/baseResults/120.frag.out
+++ b/Test/baseResults/120.frag.out
@@ -1,4 +1,3 @@
-Warning, version 120 is not yet complete; most features are present, but a few are missing.
 ERROR: 0:9: 'in for stage inputs' : not supported for this version or the enabled extensions 
 ERROR: 0:10: 'out for stage outputs' : not supported for this version or the enabled extensions 
 ERROR: 0:54: '+' :  wrong operand types: no operation '+' exists that takes a left-hand operand of type '2-component vector of float' and a right operand of type '3-component vector of float' (or there is no acceptable conversion)
diff --git a/Test/baseResults/120.vert.out b/Test/baseResults/120.vert.out
index 9f499f87b..851bbf017 100644
--- a/Test/baseResults/120.vert.out
+++ b/Test/baseResults/120.vert.out
@@ -1,4 +1,3 @@
-Warning, version 120 is not yet complete; most features are present, but a few are missing.
 ERROR: 0:3: 'in for stage inputs' : not supported for this version or the enabled extensions 
 ERROR: 0:4: 'out for stage outputs' : not supported for this version or the enabled extensions 
 ERROR: 0:11: 'gl_Position' : cannot add storage, auxiliary, memory, interpolation, or precision qualifier to an existing variable 
@@ -33,7 +32,15 @@ ERROR: 0:50: 'arrays of arrays' : not supported with this profile: none
 ERROR: 0:51: 'arrays of arrays' : not supported with this profile: none
 ERROR: 0:52: 'arrays of arrays' : not supported with this profile: none
 ERROR: 0:53: 'arrays of arrays' : not supported with this profile: none
-ERROR: 34 compilation errors.  No code generated.
+ERROR: 0:56: 'out' : overloaded functions must have the same parameter qualifiers 
+ERROR: 0:57: 'float' : overloaded functions must have the same return type 
+ERROR: 0:86: 'overloadC' : no matching overloaded function found 
+ERROR: 0:91: 'overloadD' : ambiguous function signature match: multiple signatures match under implicit type conversion 
+ERROR: 0:102: 'overloadC' : no matching overloaded function found 
+ERROR: 0:103: 'overloadE' : no matching overloaded function found 
+ERROR: 0:104: 'overloadE' : no matching overloaded function found 
+ERROR: 0:107: 'overloadE' : no matching overloaded function found 
+ERROR: 42 compilation errors.  No code generated.
 
 ERROR: node is still EOpNull!
 0:15  Function Definition: main( (void)
@@ -81,6 +88,97 @@ ERROR: node is still EOpNull!
 0:43        'gl_PointSize' (invariant gl_PointSize float)
 0:43        Constant:
 0:43          3.800000
+0:75  Function Definition: foo( (void)
+0:75    Function Parameters: 
+0:?     Sequence
+0:80      Function Call: overloadB(f1;f1; (2-component vector of float)
+0:80        'f' (float)
+0:80        'f' (float)
+0:81      Function Call: overloadB(f1;f1; (2-component vector of float)
+0:81        'f' (float)
+0:81        Constant:
+0:81          2 (const int)
+0:82      Function Call: overloadB(f1;f1; (2-component vector of float)
+0:82        Constant:
+0:82          1 (const int)
+0:82        'i' (int)
+0:84      Function Call: overloadC(i1;i1; (2-component vector of float)
+0:84        Constant:
+0:84          1 (const int)
+0:84        'i' (int)
+0:85      Function Call: overloadC(vf2;vf2; (2-component vector of float)
+0:85        Constant:
+0:85          1.000000
+0:85          1.000000
+0:85        Constant:
+0:85          2.000000
+0:85          2.000000
+0:86      Constant:
+0:86        0.000000
+0:87      Function Call: overloadC(vf2;vf2; (2-component vector of float)
+0:87        Constant:
+0:87          1 (const int)
+0:87          1 (const int)
+0:87        Constant:
+0:87          2.000000
+0:87          2.000000
+0:89      Function Call: overloadD(i1;f1; (3-component vector of float)
+0:89        'i' (int)
+0:89        'f' (float)
+0:90      Function Call: overloadD(f1;i1; (3-component vector of float)
+0:90        'f' (float)
+0:90        'i' (int)
+0:91      Function Call: overloadD(f1;i1; (3-component vector of float)
+0:91        'i' (int)
+0:91        'i' (int)
+0:94      Function Call: overloadB(f1;f1; (2-component vector of float)
+0:94        Constant:
+0:94          1 (const int)
+0:94        'i' (int)
+0:96      Constant:
+0:96        0.000000
+0:97      Function Call: texture2D(s21;vf2; (4-component vector of float)
+0:97        's2D' (uniform sampler2D)
+0:97        Constant:
+0:97          0 (const int)
+0:97          0 (const int)
+0:98      clamp (4-component vector of float)
+0:98        'attv4' (in 4-component vector of float)
+0:98        Constant:
+0:98          0 (const int)
+0:98        Constant:
+0:98          1 (const int)
+0:99      clamp (4-component vector of float)
+0:99        Convert float to int (4-component vector of int)
+0:99          'attv4' (in 4-component vector of float)
+0:99        Constant:
+0:99          0 (const int)
+0:99        Constant:
+0:99          1 (const int)
+0:102      Constant:
+0:102        0.000000
+0:103      Constant:
+0:103        0.000000
+0:104      Constant:
+0:104        0.000000
+0:105      Function Call: overloadE(vf2; (3-component vector of float)
+0:105        Constant:
+0:105          3.300000
+0:105          3.300000
+0:106      Function Call: overloadE(mf22; (3-component vector of float)
+0:106        Constant:
+0:106          0.500000
+0:106          0.000000
+0:106          0.000000
+0:106          0.500000
+0:107      Constant:
+0:107        0.000000
+0:108      Function Call: overloadE(vf2; (3-component vector of float)
+0:108        Constant:
+0:108          1 (const int)
+0:108          1 (const int)
+0:111      Function Call: overloadE(f1[2]; (3-component vector of float)
+0:111        'b' (2-element array of float)
 0:?   Linker Objects
 0:?     'i' (in 4-component vector of float)
 0:?     'o' (smooth out 4-component vector of float)
diff --git a/Test/baseResults/always-discard.frag.out b/Test/baseResults/always-discard.frag.out
index 76055e5f2..579e3ec50 100644
--- a/Test/baseResults/always-discard.frag.out
+++ b/Test/baseResults/always-discard.frag.out
@@ -1,4 +1,3 @@
-Warning, version 110 is not yet complete; most features are present, but a few are missing.
 0:? Sequence
 0:4  Function Definition: main( (void)
 0:4    Function Parameters: 
diff --git a/Test/baseResults/always-discard2.frag.out b/Test/baseResults/always-discard2.frag.out
index 724c8aecc..401fab76f 100644
--- a/Test/baseResults/always-discard2.frag.out
+++ b/Test/baseResults/always-discard2.frag.out
@@ -1,4 +1,3 @@
-Warning, version 110 is not yet complete; most features are present, but a few are missing.
 0:? Sequence
 0:4  Function Definition: main( (void)
 0:4    Function Parameters: 
diff --git a/Test/baseResults/conditionalDiscard.frag.out b/Test/baseResults/conditionalDiscard.frag.out
index 1d3359b9d..a4c3e6c25 100644
--- a/Test/baseResults/conditionalDiscard.frag.out
+++ b/Test/baseResults/conditionalDiscard.frag.out
@@ -1,4 +1,3 @@
-Warning, version 110 is not yet complete; most features are present, but a few are missing.
 0:? Sequence
 0:6  Function Definition: main( (void)
 0:6    Function Parameters: 
diff --git a/Test/baseResults/cppIndent.vert.out b/Test/baseResults/cppIndent.vert.out
index 93c643a7d..221640e41 100644
--- a/Test/baseResults/cppIndent.vert.out
+++ b/Test/baseResults/cppIndent.vert.out
@@ -1,4 +1,3 @@
-Warning, version 110 is not yet complete; most features are present, but a few are missing.
 0:? Sequence
 0:5  Sequence
 0:5    move second child to first child (float)
diff --git a/Test/baseResults/cppNest.vert.out b/Test/baseResults/cppNest.vert.out
index 60255be6e..918f832e0 100644
--- a/Test/baseResults/cppNest.vert.out
+++ b/Test/baseResults/cppNest.vert.out
@@ -1,4 +1,3 @@
-Warning, version 110 is not yet complete; most features are present, but a few are missing.
 0:? Sequence
 0:5  Sequence
 0:5    move second child to first child (float)
diff --git a/Test/baseResults/cppSimple.vert.out b/Test/baseResults/cppSimple.vert.out
index 48dfcff90..89201f1a4 100644
--- a/Test/baseResults/cppSimple.vert.out
+++ b/Test/baseResults/cppSimple.vert.out
@@ -1,4 +1,3 @@
-Warning, version 110 is not yet complete; most features are present, but a few are missing.
 ERROR: 0:77: '#error' : good1  
 ERROR: 0:81: '#error' : good2  
 ERROR: 0:85: '#error' : good3  
diff --git a/Test/baseResults/decls.frag.out b/Test/baseResults/decls.frag.out
index 6e11cfff0..f965ed910 100644
--- a/Test/baseResults/decls.frag.out
+++ b/Test/baseResults/decls.frag.out
@@ -1,4 +1,3 @@
-Warning, version 120 is not yet complete; most features are present, but a few are missing.
 ERROR: 0:19: 'vi4' : illegal use of type 'void' 
 ERROR: 0:20: 'vj' : illegal use of type 'void' 
 ERROR: 0:20: 'vk5' : illegal use of type 'void' 
diff --git a/Test/baseResults/deepRvalue.frag.out b/Test/baseResults/deepRvalue.frag.out
index 97a20f8bd..a1281944d 100644
--- a/Test/baseResults/deepRvalue.frag.out
+++ b/Test/baseResults/deepRvalue.frag.out
@@ -1,4 +1,3 @@
-Warning, version 120 is not yet complete; most features are present, but a few are missing.
 0:? Sequence
 0:5  Sequence
 0:5    move second child to first child (4-component vector of float)
diff --git a/Test/baseResults/discard-dce.frag.out b/Test/baseResults/discard-dce.frag.out
index 6cc24a01e..97f012bce 100644
--- a/Test/baseResults/discard-dce.frag.out
+++ b/Test/baseResults/discard-dce.frag.out
@@ -1,4 +1,3 @@
-Warning, version 110 is not yet complete; most features are present, but a few are missing.
 0:? Sequence
 0:4  Function Definition: main( (void)
 0:4    Function Parameters: 
diff --git a/Test/baseResults/doWhileLoop.frag.out b/Test/baseResults/doWhileLoop.frag.out
index 7071474ed..32956c44f 100644
--- a/Test/baseResults/doWhileLoop.frag.out
+++ b/Test/baseResults/doWhileLoop.frag.out
@@ -1,4 +1,3 @@
-Warning, version 110 is not yet complete; most features are present, but a few are missing.
 0:? Sequence
 0:7  Function Definition: main( (void)
 0:7    Function Parameters: 
diff --git a/Test/baseResults/earlyReturnDiscard.frag.out b/Test/baseResults/earlyReturnDiscard.frag.out
index 3b6144bed..288f55efb 100644
--- a/Test/baseResults/earlyReturnDiscard.frag.out
+++ b/Test/baseResults/earlyReturnDiscard.frag.out
@@ -1,4 +1,3 @@
-Warning, version 110 is not yet complete; most features are present, but a few are missing.
 0:? Sequence
 0:19  Function Definition: main( (void)
 0:19    Function Parameters: 
diff --git a/Test/baseResults/empty.frag.out b/Test/baseResults/empty.frag.out
index fa91cf3bb..a17d25409 100644
--- a/Test/baseResults/empty.frag.out
+++ b/Test/baseResults/empty.frag.out
@@ -11,7 +11,6 @@ WARNING: #version: statement missing; use #version on first line of shader
 0:?   Linker Objects
 
 empty3.frag
-Warning, version 110 is not yet complete; most features are present, but a few are missing.
 
 0:? Sequence
 0:?   Linker Objects
diff --git a/Test/baseResults/flowControl.frag.out b/Test/baseResults/flowControl.frag.out
index d237e726c..606671d13 100644
--- a/Test/baseResults/flowControl.frag.out
+++ b/Test/baseResults/flowControl.frag.out
@@ -1,4 +1,3 @@
-Warning, version 120 is not yet complete; most features are present, but a few are missing.
 0:? Sequence
 0:10  Function Definition: main( (void)
 0:10    Function Parameters: 
diff --git a/Test/baseResults/forLoop.frag.out b/Test/baseResults/forLoop.frag.out
index 4fec57932..5db7911f2 100644
--- a/Test/baseResults/forLoop.frag.out
+++ b/Test/baseResults/forLoop.frag.out
@@ -1,4 +1,3 @@
-Warning, version 120 is not yet complete; most features are present, but a few are missing.
 0:? Sequence
 0:8  Function Definition: main( (void)
 0:8    Function Parameters: 
diff --git a/Test/baseResults/forwardRef.frag.out b/Test/baseResults/forwardRef.frag.out
index 6ea65d762..d63454a90 100644
--- a/Test/baseResults/forwardRef.frag.out
+++ b/Test/baseResults/forwardRef.frag.out
@@ -1,4 +1,3 @@
-Warning, version 110 is not yet complete; most features are present, but a few are missing.
 0:? Sequence
 0:11  Function Definition: main( (void)
 0:11    Function Parameters: 
diff --git a/Test/baseResults/length.frag.out b/Test/baseResults/length.frag.out
index b51af1706..0543e1571 100644
--- a/Test/baseResults/length.frag.out
+++ b/Test/baseResults/length.frag.out
@@ -1,4 +1,3 @@
-Warning, version 120 is not yet complete; most features are present, but a few are missing.
 0:? Sequence
 0:11  Function Definition: main( (void)
 0:11    Function Parameters: 
diff --git a/Test/baseResults/mains1.frag.out b/Test/baseResults/mains1.frag.out
index 43dba1490..723d725d1 100644
--- a/Test/baseResults/mains1.frag.out
+++ b/Test/baseResults/mains1.frag.out
@@ -1,5 +1,4 @@
 mains1.frag
-Warning, version 110 is not yet complete; most features are present, but a few are missing.
 
 0:? Sequence
 0:3  Function Definition: main( (void)
@@ -7,7 +6,6 @@ Warning, version 110 is not yet complete; most features are present, but a few a
 0:?   Linker Objects
 
 mains2.frag
-Warning, version 110 is not yet complete; most features are present, but a few are missing.
 
 0:? Sequence
 0:3  Function Definition: main( (void)
diff --git a/Test/baseResults/matrixError.vert.out b/Test/baseResults/matrixError.vert.out
index fa5a82bd9..70bdae84a 100644
--- a/Test/baseResults/matrixError.vert.out
+++ b/Test/baseResults/matrixError.vert.out
@@ -1,4 +1,3 @@
-Warning, version 120 is not yet complete; most features are present, but a few are missing.
 ERROR: 0:10: 'constructor' : too many arguments 
 ERROR: 0:7: 'const' : non-matching or non-convertible constant type for const initializer 
 ERROR: 0:17: 'assign' :  cannot convert from '2-component vector of float' to '3-component vector of float'
diff --git a/Test/baseResults/nonSquare.vert.out b/Test/baseResults/nonSquare.vert.out
index 5257200f8..6b1961dd1 100644
--- a/Test/baseResults/nonSquare.vert.out
+++ b/Test/baseResults/nonSquare.vert.out
@@ -1,4 +1,3 @@
-Warning, version 120 is not yet complete; most features are present, but a few are missing.
 0:? Sequence
 0:15  Function Definition: main( (void)
 0:15    Function Parameters: 
diff --git a/Test/baseResults/sample.frag.out b/Test/baseResults/sample.frag.out
index 13c8679c4..0e85f8e96 100644
--- a/Test/baseResults/sample.frag.out
+++ b/Test/baseResults/sample.frag.out
@@ -1,4 +1,3 @@
-Warning, version 110 is not yet complete; most features are present, but a few are missing.
 0:? Sequence
 0:38  Function Definition: main( (void)
 0:38    Function Parameters: 
diff --git a/Test/baseResults/sample.vert.out b/Test/baseResults/sample.vert.out
index 29e3a05c4..e7942be44 100644
--- a/Test/baseResults/sample.vert.out
+++ b/Test/baseResults/sample.vert.out
@@ -1,4 +1,3 @@
-Warning, version 110 is not yet complete; most features are present, but a few are missing.
 0:? Sequence
 0:38  Function Definition: main( (void)
 0:38    Function Parameters: 
diff --git a/Test/baseResults/swizzle.frag.out b/Test/baseResults/swizzle.frag.out
index 3f1b94719..e6b3a9342 100644
--- a/Test/baseResults/swizzle.frag.out
+++ b/Test/baseResults/swizzle.frag.out
@@ -1,4 +1,3 @@
-Warning, version 110 is not yet complete; most features are present, but a few are missing.
 0:? Sequence
 0:9  Function Definition: main( (void)
 0:9    Function Parameters: 
diff --git a/Test/baseResults/syntaxError.frag.out b/Test/baseResults/syntaxError.frag.out
index f8264de07..54df81398 100644
--- a/Test/baseResults/syntaxError.frag.out
+++ b/Test/baseResults/syntaxError.frag.out
@@ -1,4 +1,3 @@
-Warning, version 120 is not yet complete; most features are present, but a few are missing.
 ERROR: 0:9: 'vec5' : undeclared identifier 
 ERROR: 0:9: '' :  syntax error
 ERROR: 2 compilation errors.  No code generated.
diff --git a/Test/baseResults/test.frag.out b/Test/baseResults/test.frag.out
index 9e2a28917..74bf27089 100644
--- a/Test/baseResults/test.frag.out
+++ b/Test/baseResults/test.frag.out
@@ -1,4 +1,3 @@
-Warning, version 110 is not yet complete; most features are present, but a few are missing.
 0:? Sequence
 0:13  Function Definition: main( (void)
 0:13    Function Parameters: 
diff --git a/Test/baseResults/versionsErrors.frag.out b/Test/baseResults/versionsErrors.frag.out
index 6a5f61a35..b339567bb 100644
--- a/Test/baseResults/versionsErrors.frag.out
+++ b/Test/baseResults/versionsErrors.frag.out
@@ -1,5 +1,4 @@
 ERROR: #version: versions before 150 do not allow a profile token
-Warning, version 110 is not yet complete; most features are present, but a few are missing.
 ERROR: 0:38: 'attribute' : not supported in this stage: fragment
 ERROR: 0:40: 'sampler2DRect' : Reserved word. 
 ERROR: 0:40: 'rectangle texture' : not supported for this version or the enabled extensions 
diff --git a/Test/baseResults/voidFunction.frag.out b/Test/baseResults/voidFunction.frag.out
index 5cc5d1eea..4b62cd21f 100644
--- a/Test/baseResults/voidFunction.frag.out
+++ b/Test/baseResults/voidFunction.frag.out
@@ -1,4 +1,3 @@
-Warning, version 120 is not yet complete; most features are present, but a few are missing.
 0:? Sequence
 0:7  Sequence
 0:7    move second child to first child (float)
diff --git a/Test/baseResults/whileLoop.frag.out b/Test/baseResults/whileLoop.frag.out
index 4300f1811..7b25a0c3f 100644
--- a/Test/baseResults/whileLoop.frag.out
+++ b/Test/baseResults/whileLoop.frag.out
@@ -1,4 +1,3 @@
-Warning, version 110 is not yet complete; most features are present, but a few are missing.
 0:? Sequence
 0:7  Function Definition: main( (void)
 0:7    Function Parameters: 
diff --git a/Todo.txt b/Todo.txt
index 1e6be183a..f3ce5b491 100644
--- a/Todo.txt
+++ b/Todo.txt
@@ -57,7 +57,7 @@ Shader Functionality to Implement/Finish
     GLSL 1.2
       + Handle multiple compilation units per stage
       + Allow initializers on uniform declarations
-      - signature matching takes type conversions into account, ambiguity is an error
+      + signature matching takes type conversions into account, ambiguity is an error
       - allow constructors to contain non-dereferenced arrays?
     GLSL 1.3
       . flat is for both user and predeclared built-in in/out variables
diff --git a/glslang/Include/Types.h b/glslang/Include/Types.h
index e7e4bc37c..9ca44076c 100644
--- a/glslang/Include/Types.h
+++ b/glslang/Include/Types.h
@@ -846,20 +846,30 @@ public:
     // See if two types match, in all aspects except arrayness
     bool sameElementType(const TType& right) const
     {
-        return  basicType == right.basicType  &&
-                  sampler == right.sampler    &&
+        return basicType == right.basicType && sameElementShape(right);
+    }
+
+    // See if two type's arrayness match
+    bool sameArrayness(const TType& right) const
+    {
+        return ((arraySizes == 0 && right.arraySizes == 0) ||
+                (arraySizes && right.arraySizes && arraySizes->sizes == right.arraySizes->sizes));
+    }
+
+    // See if two type's elements match in all ways except basic type
+    bool sameElementShape(const TType& right) const
+    {
+        return    sampler == right.sampler    &&
                vectorSize == right.vectorSize &&
                matrixCols == right.matrixCols &&
                matrixRows == right.matrixRows &&
                sameStructType(right);
     }
 
-    // See if two types match in all ways (just the actual type, not qualification
+    // See if two types match in all ways (just the actual type, not qualification)
     bool operator==(const TType& right) const
     {
-        return sameElementType(right) &&
-               ((arraySizes == 0 && right.arraySizes == 0) ||
-                (arraySizes && right.arraySizes && arraySizes->sizes == right.arraySizes->sizes));
+        return sameElementType(right) && sameArrayness(right);
     }
 
     bool operator!=(const TType& right) const
diff --git a/glslang/MachineIndependent/ParseHelper.cpp b/glslang/MachineIndependent/ParseHelper.cpp
index 14c92a5f8..c46b7e4de 100644
--- a/glslang/MachineIndependent/ParseHelper.cpp
+++ b/glslang/MachineIndependent/ParseHelper.cpp
@@ -829,7 +829,13 @@ TIntermAggregate* TParseContext::handleFunctionPrototype(TSourceLoc loc, TFuncti
 }
 
 //
-// Handle seeing a function call in the grammar.
+// Handle seeing function call syntax in the grammar, which could be any of
+//  - .length() method
+//  - constructor
+//  - a call to a built-in function mapped to an operator
+//  - a call to a built-in function that will remain a function call (e.g., texturing)
+//  - user function
+//  - subroutine call (not implemented yet)
 //
 TIntermTyped* TParseContext::handleFunctionCall(TSourceLoc loc, TFunction* fnCall, TIntermNode* intermNode, TIntermAggregate* intermAggregate)
 {
@@ -866,11 +872,11 @@ TIntermTyped* TParseContext::handleFunctionCall(TSourceLoc loc, TFunction* fnCal
         }
     } else {
         //
-        // Not a constructor.  Find it in the symbol table.
+        // Find it in the symbol table.
         //
         const TFunction* fnCandidate;
         bool builtIn;
-        fnCandidate = findFunction(loc, fnCall, &builtIn);
+        fnCandidate = findFunction(loc, *fnCall, builtIn);
         if (fnCandidate) {
             //
             // A declared function.  But, it might still map to a built-in
@@ -898,6 +904,7 @@ TIntermTyped* TParseContext::handleFunctionCall(TSourceLoc loc, TFunction* fnCal
                     intermediate.addToCallGraph(infoSink, currentCaller, fnCandidate->getMangledName());
                 }
 
+                // Make sure storage qualifications work for these arguments.
                 TStorageQualifier qual;
                 TQualifierList& qualifierList = result->getAsAggregate()->getQualifierList();
                 for (int i = 0; i < fnCandidate->getParamCount(); ++i) {
@@ -912,12 +919,6 @@ TIntermTyped* TParseContext::handleFunctionCall(TSourceLoc loc, TFunction* fnCal
                 if (builtIn)
                     nonOpBuiltInCheck(loc, *fnCandidate, result->getAsAggregate());
             }
-        } else {
-            // error message was put out by PaFindFunction()
-            // Put on a dummy node for error recovery
-            TConstUnionArray unionArray(1);
-            unionArray[0].setDConst(0.0);
-            result = intermediate.addConstantUnion(unionArray, TType(EbtFloat, EvqConst), loc);
         }
     }
 
@@ -2543,24 +2544,105 @@ void TParseContext::checkNoShaderLayouts(TSourceLoc loc, const TPublicType& publ
 //
 // Return the function symbol if found, otherwise 0.
 //
-const TFunction* TParseContext::findFunction(TSourceLoc loc, TFunction* call, bool *builtIn)
+const TFunction* TParseContext::findFunction(TSourceLoc loc, const TFunction& call, bool& builtIn)
 {
-    TSymbol* symbol = symbolTable.find(call->getMangledName(), builtIn);
+    const TFunction* function = 0;
+
+    if (profile == EEsProfile || version < 120)
+        function = findFunctionExact(loc, call, builtIn);
+    else if (version < 400)
+        function = findFunction120(loc, call, builtIn);
+    else
+        function = findFunction400(loc, call, builtIn);
 
+    return function;
+}
+
+// Function finding algorithm for ES and desktop 110.
+const TFunction* TParseContext::findFunctionExact(TSourceLoc loc, const TFunction& call, bool& builtIn)
+{
+    const TFunction* function = 0;
+
+    TSymbol* symbol = symbolTable.find(call.getMangledName(), &builtIn);
     if (symbol == 0) {
-        error(loc, "no matching overloaded function found", call->getName().c_str(), "");
+        error(loc, "no matching overloaded function found", call.getName().c_str(), "");
 
         return 0;
     }
 
-    const TFunction* function = symbol->getAsFunction();
-    if (! function) {
-        error(loc, "function name expected", call->getName().c_str(), "");
+    return symbol->getAsFunction();
+}
 
-        return 0;
+// Function finding algorithm for desktop versions 120 through 330.
+const TFunction* TParseContext::findFunction120(TSourceLoc loc, const TFunction& call, bool& builtIn)
+{
+    // first, look for an exact match
+    TSymbol* symbol = symbolTable.find(call.getMangledName(), &builtIn);
+    if (symbol)
+        return symbol->getAsFunction();
+
+    // exact match not found, look through a list of overloaded functions of the same name
+
+    // "If no exact match is found, then [implicit conversions] will be applied to find a match. Mismatched types
+    // on input parameters (in or inout or default) must have a conversion from the calling argument type to the
+    // formal parameter type. Mismatched types on output parameters (out or inout) must have a conversion
+    // from the formal parameter type to the calling argument type.  When argument conversions are used to find
+    // a match, it is a semantic error if there are multiple ways to apply these conversions to make the call match
+    // more than one function."
+
+    const TFunction* candidate = 0;
+    TVector<TFunction*> candidateList;
+    symbolTable.findFunctionNameList(call.getMangledName(), candidateList, builtIn);
+
+    int numPossibleMatches = 0;
+    for (TVector<TFunction*>::const_iterator it = candidateList.begin(); it != candidateList.end(); ++it) {
+        bool possibleMatch = true;
+        const TFunction& function = *(*it);
+        for (int i = 0; i < function.getParamCount(); ++i) {
+            // same types is easy
+            if (*function[i].type == *call[i].type)
+                continue;
+
+            // We have a mismatch in type, see if it is implicitly convertible
+
+            if (function[i].type->isArray() || call[i].type->isArray() ||
+                ! function[i].type->sameElementShape(*call[i].type))
+                possibleMatch = false;
+            else {
+                // do direction-specific checks for conversion of basic type
+                TStorageQualifier qualifier = function[i].type->getQualifier().storage;
+                if (qualifier == EvqIn || qualifier == EvqInOut) {
+                    if (! intermediate.canImplicitlyPromote(call[i].type->getBasicType(), function[i].type->getBasicType()))
+                        possibleMatch = false;
+                }
+                if (qualifier == EvqOut || qualifier == EvqInOut) {
+                    if (! intermediate.canImplicitlyPromote(function[i].type->getBasicType(), call[i].type->getBasicType()))
+                        possibleMatch = false;
+                }
+            }
+            if (! possibleMatch)
+                break;
+        }
+        if (possibleMatch) {
+            if (candidate) {
+                // our second match, meaning ambiguity
+                error(loc, "ambiguous function signature match: multiple signatures match under implicit type conversion", call.getName().c_str(), "");
+            } else
+                candidate = &function;
+        }
     }
 
-    return function;
+    if (candidate == 0)
+        error(loc, "no matching overloaded function found", call.getName().c_str(), "");
+
+    return candidate;
+}
+
+// Function finding algorithm for desktop version 400 and above.
+const TFunction* TParseContext::findFunction400(TSourceLoc loc, const TFunction& call, bool& builtIn)
+{
+    // TODO: 4.00 functionality: findFunction400()
+    return findFunction120(loc, call, builtIn);
 }
 
 //
diff --git a/glslang/MachineIndependent/ParseHelper.h b/glslang/MachineIndependent/ParseHelper.h
index 4f9e0537d..7e499e7da 100644
--- a/glslang/MachineIndependent/ParseHelper.h
+++ b/glslang/MachineIndependent/ParseHelper.h
@@ -140,7 +140,10 @@ public:
     void layoutQualifierCheck(TSourceLoc, const TQualifier&);
     void checkNoShaderLayouts(TSourceLoc, const TPublicType&);
 
-    const TFunction* findFunction(TSourceLoc, TFunction* pfnCall, bool *builtIn = 0);
+    const TFunction* findFunction(TSourceLoc loc, const TFunction& call, bool& builtIn);
+    const TFunction* findFunctionExact(TSourceLoc loc, const TFunction& call, bool& builtIn);
+    const TFunction* findFunction120(TSourceLoc loc, const TFunction& call, bool& builtIn);
+    const TFunction* findFunction400(TSourceLoc loc, const TFunction& call, bool& builtIn);
     TIntermNode* declareVariable(TSourceLoc, TString& identifier, TPublicType&, TArraySizes* typeArray = 0, TIntermTyped* initializer = 0);
     TIntermTyped* addConstructor(TSourceLoc, TIntermNode*, const TType&, TOperator);
     TIntermTyped* constructStruct(TIntermNode*, const TType&, int, TSourceLoc);
diff --git a/glslang/MachineIndependent/ShaderLang.cpp b/glslang/MachineIndependent/ShaderLang.cpp
index 9f8bc17a5..407277674 100644
--- a/glslang/MachineIndependent/ShaderLang.cpp
+++ b/glslang/MachineIndependent/ShaderLang.cpp
@@ -378,10 +378,11 @@ bool DeduceVersionProfile(TInfoSink& infoSink, EShLanguage stage, bool versionNo
     switch(version) {
     case 100:
     case 300:
-        // versions are complete
-        break;
+
     case 110:
     case 120:
+        // versions are complete
+        break;
     case 130:
     case 140:
         infoSink.info << "Warning, version " << version << " is not yet complete; most features are present, but a few are missing.\n";
diff --git a/glslang/MachineIndependent/SymbolTable.h b/glslang/MachineIndependent/SymbolTable.h
index b71d62cdd..e51f9cee3 100644
--- a/glslang/MachineIndependent/SymbolTable.h
+++ b/glslang/MachineIndependent/SymbolTable.h
@@ -322,6 +322,19 @@ public:
             return (*it).second;
     }
 
+    void findFunctionNameList(const TString& name, TVector<TFunction*>& list)
+    {
+        size_t parenAt = name.find_first_of('(');
+        TString base(name, 0, parenAt + 1);
+
+        tLevel::const_iterator begin = level.lower_bound(base);
+        base[parenAt] = ')';  // assume ')' is lexically after '('
+        tLevel::const_iterator end = level.upper_bound(base);
+        for (tLevel::const_iterator it = begin; it != end; ++it)
+            list.push_back(it->second->getAsFunction());
+    }
+
+    // See if there is already a function in the table having the given non-function-style name.
     bool hasFunctionName(const TString& name) const
     {
         tLevel::const_iterator candidate = level.lower_bound(name);
@@ -397,7 +410,7 @@ public:
         while (table.size() > adoptedLevels)
             pop(0);
     }
-
+    
     void adoptLevels(TSymbolTable& symTable)
     {
         for (unsigned int level = 0; level < symTable.table.size(); ++level) {
@@ -511,6 +524,27 @@ public:
         return symbol;
     }
 
+    void findFunctionNameList(const TString& name, TVector<TFunction*>& list, bool& builtIn)
+    {
+        // For user levels, return the set found in the first scope with a match
+        builtIn = false;
+        int level = currentLevel();
+        do {
+            table[level]->findFunctionNameList(name, list);
+            --level;
+        } while (list.empty() && level >= globalLevel);
+
+        if (! list.empty())
+            return;
+
+        // Gather across all built-in levels; they don't hide each other
+        builtIn = true;
+        do {
+            table[level]->findFunctionNameList(name, list);
+            --level;
+        } while (level >= 0);
+    }
+
     void relateToOperator(const char* name, TOperator op)
     {
         for (unsigned int level = 0; level < table.size(); ++level)
-- 
GitLab