Front-end: Add a function selector under implicit type conversion.
authorJohn Kessenich <cepheus@frii.com>
Fri, 19 Aug 2016 13:31:31 +0000 (07:31 -0600)
committerJohn Kessenich <cepheus@frii.com>
Sun, 21 Aug 2016 20:26:27 +0000 (14:26 -0600)
Use the new function selector for #version 400 and above,
parameterized for the GLSL #version 400 selection rules.

This can be used for both GLSL and HLSL, and other languages
as well.

Test/400.vert
Test/baseResults/400.vert.out
glslang/MachineIndependent/ParseHelper.cpp
glslang/MachineIndependent/ParseHelper.h

index 2c3dd04..315c7ea 100644 (file)
@@ -4,6 +4,103 @@ in double d;   // ERROR, no doubles
 in dvec3 d3;   // ERROR, no doubles
 in dmat4 dm4;  // ERROR, no doubles
 
-void main()
+// function selection under type conversion
+void foo1(double a, uint b)  {}\r
+void foo1(double a, int b)   {}\r
+void foo1(double a, float b) {}\r
+void foo1(double a, double b){}\r
+\r
+void foo2(double a, float b) {}\r
+void foo2(double a, double b){}\r
+\r
+void foo3(double a, float b) {}\r
+void foo3(float a, double b) {}\r
+\r
+void ftd(  int,  float, double) {}\r
+void ftd( uint,  float, double) {}\r
+void ftd(float, double, double) {}\r
+\r
+void main()\r
+{\r
+    double d;\r
+       uint u;\r
+       int i;\r
+       float f;\r
+\r
+       foo1(d, d);\r
+       foo1(d, u);\r
+       foo1(d, i);\r
+       foo1(d, f);\r
+\r
+       foo1(f, d);\r
+       foo1(f, u);\r
+       foo1(f, i);\r
+       foo1(f, f);\r
+\r
+       foo1(u, d);\r
+       foo1(u, u);\r
+       foo1(u, i);\r
+       foo1(u, f);\r
+\r
+       foo1(i, d);\r
+       foo1(i, u);\r
+       foo1(i, i);\r
+       foo1(i, f);\r
+\r
+       foo2(d, d);\r
+       foo2(d, u);\r
+       foo2(d, i);\r
+       foo2(d, f);\r
+\r
+       foo2(f, d);\r
+       foo2(f, u);\r
+       foo2(f, i);\r
+       foo2(f, f);\r
+\r
+       foo2(u, d);\r
+       foo2(u, u);\r
+       foo2(u, i);\r
+       foo2(u, f);\r
+\r
+       foo2(i, d);\r
+       foo2(i, u);\r
+       foo2(i, i);\r
+       foo2(i, f);\r
+\r
+       foo3(d, d);  // ERROR, no match\r
+       foo3(d, u);\r
+       foo3(d, i);\r
+       foo3(d, f);\r
+\r
+       foo3(f, d);\r
+       foo3(f, u); // ERROR, ambiguous\r
+       foo3(f, i); // ERROR, ambiguous\r
+       foo3(f, f); // ERROR, ambiguous\r
+\r
+       foo3(u, d);\r
+       foo3(u, u); // ERROR, ambiguous\r
+       foo3(u, i); // ERROR, ambiguous\r
+       foo3(u, f); // ERROR, ambiguous\r
+\r
+       foo3(i, d);\r
+       foo3(i, u); // ERROR, ambiguous\r
+       foo3(i, i); // ERROR, ambiguous\r
+       foo3(i, f); // ERROR, ambiguous\r
+\r
+       ftd(i, f, f);\r
+       ftd(u, f, f);\r
+}
+
+void itf(int, float, int);
+void itf(int, double, int);
+
+void tf()
 {
+    double d;\r
+       uint u;\r
+       int i;\r
+       float f;\r
+       
+       itf(i, i, i);
+       itf(i, u, i);
 }
index 946f21d..2b0d63d 100755 (executable)
@@ -3,13 +3,288 @@ Warning, version 400 is not yet complete; most version-specific features are pre
 ERROR: 0:3: 'vertex-shader `double` type input' : not supported for this version or the enabled extensions 
 ERROR: 0:4: 'vertex-shader `double` type input' : not supported for this version or the enabled extensions 
 ERROR: 0:5: 'vertex-shader `double` type input' : not supported for this version or the enabled extensions 
-ERROR: 3 compilation errors.  No code generated.
+ERROR: 0:70: 'foo3' : no matching overloaded function found 
+ERROR: 0:76: 'foo3' : ambiguous best function under implicit type conversion 
+ERROR: 0:77: 'foo3' : ambiguous best function under implicit type conversion 
+ERROR: 0:78: 'foo3' : ambiguous best function under implicit type conversion 
+ERROR: 0:81: 'foo3' : ambiguous best function under implicit type conversion 
+ERROR: 0:82: 'foo3' : ambiguous best function under implicit type conversion 
+ERROR: 0:83: 'foo3' : ambiguous best function under implicit type conversion 
+ERROR: 0:86: 'foo3' : ambiguous best function under implicit type conversion 
+ERROR: 0:87: 'foo3' : ambiguous best function under implicit type conversion 
+ERROR: 0:88: 'foo3' : ambiguous best function under implicit type conversion 
+ERROR: 13 compilation errors.  No code generated.
 
 
 Shader version: 400
 ERROR: node is still EOpNull!
-0:7  Function Definition: main( (global void)
-0:7    Function Parameters: 
+0:8  Function Definition: foo1(d1;u1; (global void)
+0:8    Function Parameters: 
+0:8      'a' (in double)
+0:8      'b' (in uint)
+0:9  Function Definition: foo1(d1;i1; (global void)
+0:9    Function Parameters: 
+0:9      'a' (in double)
+0:9      'b' (in int)
+0:10  Function Definition: foo1(d1;f1; (global void)
+0:10    Function Parameters: 
+0:10      'a' (in double)
+0:10      'b' (in float)
+0:11  Function Definition: foo1(d1;d1; (global void)
+0:11    Function Parameters: 
+0:11      'a' (in double)
+0:11      'b' (in double)
+0:13  Function Definition: foo2(d1;f1; (global void)
+0:13    Function Parameters: 
+0:13      'a' (in double)
+0:13      'b' (in float)
+0:14  Function Definition: foo2(d1;d1; (global void)
+0:14    Function Parameters: 
+0:14      'a' (in double)
+0:14      'b' (in double)
+0:16  Function Definition: foo3(d1;f1; (global void)
+0:16    Function Parameters: 
+0:16      'a' (in double)
+0:16      'b' (in float)
+0:17  Function Definition: foo3(f1;d1; (global void)
+0:17    Function Parameters: 
+0:17      'a' (in float)
+0:17      'b' (in double)
+0:19  Function Definition: ftd(i1;f1;d1; (global void)
+0:19    Function Parameters: 
+0:19      '' (in int)
+0:19      '' (in float)
+0:19      '' (in double)
+0:20  Function Definition: ftd(u1;f1;d1; (global void)
+0:20    Function Parameters: 
+0:20      '' (in uint)
+0:20      '' (in float)
+0:20      '' (in double)
+0:21  Function Definition: ftd(f1;d1;d1; (global void)
+0:21    Function Parameters: 
+0:21      '' (in float)
+0:21      '' (in double)
+0:21      '' (in double)
+0:23  Function Definition: main( (global void)
+0:23    Function Parameters: 
+0:?     Sequence
+0:30      Function Call: foo1(d1;d1; (global void)
+0:30        'd' (temp double)
+0:30        'd' (temp double)
+0:31      Function Call: foo1(d1;u1; (global void)
+0:31        'd' (temp double)
+0:31        'u' (temp uint)
+0:32      Function Call: foo1(d1;i1; (global void)
+0:32        'd' (temp double)
+0:32        'i' (temp int)
+0:33      Function Call: foo1(d1;f1; (global void)
+0:33        'd' (temp double)
+0:33        'f' (temp float)
+0:35      Function Call: foo1(d1;d1; (global void)
+0:35        Convert float to double (temp double)
+0:35          'f' (temp float)
+0:35        'd' (temp double)
+0:36      Function Call: foo1(d1;u1; (global void)
+0:36        Convert float to double (temp double)
+0:36          'f' (temp float)
+0:36        'u' (temp uint)
+0:37      Function Call: foo1(d1;i1; (global void)
+0:37        Convert float to double (temp double)
+0:37          'f' (temp float)
+0:37        'i' (temp int)
+0:38      Function Call: foo1(d1;f1; (global void)
+0:38        Convert float to double (temp double)
+0:38          'f' (temp float)
+0:38        'f' (temp float)
+0:40      Function Call: foo1(d1;d1; (global void)
+0:40        Convert uint to double (temp double)
+0:40          'u' (temp uint)
+0:40        'd' (temp double)
+0:41      Function Call: foo1(d1;u1; (global void)
+0:41        Convert uint to double (temp double)
+0:41          'u' (temp uint)
+0:41        'u' (temp uint)
+0:42      Function Call: foo1(d1;i1; (global void)
+0:42        Convert uint to double (temp double)
+0:42          'u' (temp uint)
+0:42        'i' (temp int)
+0:43      Function Call: foo1(d1;f1; (global void)
+0:43        Convert uint to double (temp double)
+0:43          'u' (temp uint)
+0:43        'f' (temp float)
+0:45      Function Call: foo1(d1;d1; (global void)
+0:45        Convert int to double (temp double)
+0:45          'i' (temp int)
+0:45        'd' (temp double)
+0:46      Function Call: foo1(d1;u1; (global void)
+0:46        Convert int to double (temp double)
+0:46          'i' (temp int)
+0:46        'u' (temp uint)
+0:47      Function Call: foo1(d1;i1; (global void)
+0:47        Convert int to double (temp double)
+0:47          'i' (temp int)
+0:47        'i' (temp int)
+0:48      Function Call: foo1(d1;f1; (global void)
+0:48        Convert int to double (temp double)
+0:48          'i' (temp int)
+0:48        'f' (temp float)
+0:50      Function Call: foo2(d1;d1; (global void)
+0:50        'd' (temp double)
+0:50        'd' (temp double)
+0:51      Function Call: foo2(d1;f1; (global void)
+0:51        'd' (temp double)
+0:51        Convert uint to float (temp float)
+0:51          'u' (temp uint)
+0:52      Function Call: foo2(d1;f1; (global void)
+0:52        'd' (temp double)
+0:52        Convert int to float (temp float)
+0:52          'i' (temp int)
+0:53      Function Call: foo2(d1;f1; (global void)
+0:53        'd' (temp double)
+0:53        'f' (temp float)
+0:55      Function Call: foo2(d1;d1; (global void)
+0:55        Convert float to double (temp double)
+0:55          'f' (temp float)
+0:55        'd' (temp double)
+0:56      Function Call: foo2(d1;f1; (global void)
+0:56        Convert float to double (temp double)
+0:56          'f' (temp float)
+0:56        Convert uint to float (temp float)
+0:56          'u' (temp uint)
+0:57      Function Call: foo2(d1;f1; (global void)
+0:57        Convert float to double (temp double)
+0:57          'f' (temp float)
+0:57        Convert int to float (temp float)
+0:57          'i' (temp int)
+0:58      Function Call: foo2(d1;f1; (global void)
+0:58        Convert float to double (temp double)
+0:58          'f' (temp float)
+0:58        'f' (temp float)
+0:60      Function Call: foo2(d1;d1; (global void)
+0:60        Convert uint to double (temp double)
+0:60          'u' (temp uint)
+0:60        'd' (temp double)
+0:61      Function Call: foo2(d1;f1; (global void)
+0:61        Convert uint to double (temp double)
+0:61          'u' (temp uint)
+0:61        Convert uint to float (temp float)
+0:61          'u' (temp uint)
+0:62      Function Call: foo2(d1;f1; (global void)
+0:62        Convert uint to double (temp double)
+0:62          'u' (temp uint)
+0:62        Convert int to float (temp float)
+0:62          'i' (temp int)
+0:63      Function Call: foo2(d1;f1; (global void)
+0:63        Convert uint to double (temp double)
+0:63          'u' (temp uint)
+0:63        'f' (temp float)
+0:65      Function Call: foo2(d1;d1; (global void)
+0:65        Convert int to double (temp double)
+0:65          'i' (temp int)
+0:65        'd' (temp double)
+0:66      Function Call: foo2(d1;f1; (global void)
+0:66        Convert int to double (temp double)
+0:66          'i' (temp int)
+0:66        Convert uint to float (temp float)
+0:66          'u' (temp uint)
+0:67      Function Call: foo2(d1;f1; (global void)
+0:67        Convert int to double (temp double)
+0:67          'i' (temp int)
+0:67        Convert int to float (temp float)
+0:67          'i' (temp int)
+0:68      Function Call: foo2(d1;f1; (global void)
+0:68        Convert int to double (temp double)
+0:68          'i' (temp int)
+0:68        'f' (temp float)
+0:70      Constant:
+0:70        0.000000
+0:71      Function Call: foo3(d1;f1; (global void)
+0:71        'd' (temp double)
+0:71        Convert uint to float (temp float)
+0:71          'u' (temp uint)
+0:72      Function Call: foo3(d1;f1; (global void)
+0:72        'd' (temp double)
+0:72        Convert int to float (temp float)
+0:72          'i' (temp int)
+0:73      Function Call: foo3(d1;f1; (global void)
+0:73        'd' (temp double)
+0:73        'f' (temp float)
+0:75      Function Call: foo3(f1;d1; (global void)
+0:75        'f' (temp float)
+0:75        'd' (temp double)
+0:76      Function Call: foo3(d1;f1; (global void)
+0:76        Convert float to double (temp double)
+0:76          'f' (temp float)
+0:76        Convert uint to float (temp float)
+0:76          'u' (temp uint)
+0:77      Function Call: foo3(d1;f1; (global void)
+0:77        Convert float to double (temp double)
+0:77          'f' (temp float)
+0:77        Convert int to float (temp float)
+0:77          'i' (temp int)
+0:78      Function Call: foo3(d1;f1; (global void)
+0:78        Convert float to double (temp double)
+0:78          'f' (temp float)
+0:78        'f' (temp float)
+0:80      Function Call: foo3(f1;d1; (global void)
+0:80        Convert uint to float (temp float)
+0:80          'u' (temp uint)
+0:80        'd' (temp double)
+0:81      Function Call: foo3(d1;f1; (global void)
+0:81        Convert uint to double (temp double)
+0:81          'u' (temp uint)
+0:81        Convert uint to float (temp float)
+0:81          'u' (temp uint)
+0:82      Function Call: foo3(d1;f1; (global void)
+0:82        Convert uint to double (temp double)
+0:82          'u' (temp uint)
+0:82        Convert int to float (temp float)
+0:82          'i' (temp int)
+0:83      Function Call: foo3(d1;f1; (global void)
+0:83        Convert uint to double (temp double)
+0:83          'u' (temp uint)
+0:83        'f' (temp float)
+0:85      Function Call: foo3(f1;d1; (global void)
+0:85        Convert int to float (temp float)
+0:85          'i' (temp int)
+0:85        'd' (temp double)
+0:86      Function Call: foo3(d1;f1; (global void)
+0:86        Convert int to double (temp double)
+0:86          'i' (temp int)
+0:86        Convert uint to float (temp float)
+0:86          'u' (temp uint)
+0:87      Function Call: foo3(d1;f1; (global void)
+0:87        Convert int to double (temp double)
+0:87          'i' (temp int)
+0:87        Convert int to float (temp float)
+0:87          'i' (temp int)
+0:88      Function Call: foo3(d1;f1; (global void)
+0:88        Convert int to double (temp double)
+0:88          'i' (temp int)
+0:88        'f' (temp float)
+0:90      Function Call: ftd(i1;f1;d1; (global void)
+0:90        'i' (temp int)
+0:90        'f' (temp float)
+0:90        Convert float to double (temp double)
+0:90          'f' (temp float)
+0:91      Function Call: ftd(u1;f1;d1; (global void)
+0:91        'u' (temp uint)
+0:91        'f' (temp float)
+0:91        Convert float to double (temp double)
+0:91          'f' (temp float)
+0:97  Function Definition: tf( (global void)
+0:97    Function Parameters: 
+0:?     Sequence
+0:104      Function Call: itf(i1;f1;i1; (global void)
+0:104        'i' (temp int)
+0:104        Convert int to float (temp float)
+0:104          'i' (temp int)
+0:104        'i' (temp int)
+0:105      Function Call: itf(i1;f1;i1; (global void)
+0:105        'i' (temp int)
+0:105        Convert uint to float (temp float)
+0:105          'u' (temp uint)
+0:105        'i' (temp int)
 0:?   Linker Objects
 0:?     'd' (in double)
 0:?     'd3' (in 3-component vector of double)
@@ -23,8 +298,273 @@ Linked vertex stage:
 
 Shader version: 400
 ERROR: node is still EOpNull!
-0:7  Function Definition: main( (global void)
-0:7    Function Parameters: 
+0:8  Function Definition: foo1(d1;u1; (global void)
+0:8    Function Parameters: 
+0:8      'a' (in double)
+0:8      'b' (in uint)
+0:9  Function Definition: foo1(d1;i1; (global void)
+0:9    Function Parameters: 
+0:9      'a' (in double)
+0:9      'b' (in int)
+0:10  Function Definition: foo1(d1;f1; (global void)
+0:10    Function Parameters: 
+0:10      'a' (in double)
+0:10      'b' (in float)
+0:11  Function Definition: foo1(d1;d1; (global void)
+0:11    Function Parameters: 
+0:11      'a' (in double)
+0:11      'b' (in double)
+0:13  Function Definition: foo2(d1;f1; (global void)
+0:13    Function Parameters: 
+0:13      'a' (in double)
+0:13      'b' (in float)
+0:14  Function Definition: foo2(d1;d1; (global void)
+0:14    Function Parameters: 
+0:14      'a' (in double)
+0:14      'b' (in double)
+0:16  Function Definition: foo3(d1;f1; (global void)
+0:16    Function Parameters: 
+0:16      'a' (in double)
+0:16      'b' (in float)
+0:17  Function Definition: foo3(f1;d1; (global void)
+0:17    Function Parameters: 
+0:17      'a' (in float)
+0:17      'b' (in double)
+0:19  Function Definition: ftd(i1;f1;d1; (global void)
+0:19    Function Parameters: 
+0:19      '' (in int)
+0:19      '' (in float)
+0:19      '' (in double)
+0:20  Function Definition: ftd(u1;f1;d1; (global void)
+0:20    Function Parameters: 
+0:20      '' (in uint)
+0:20      '' (in float)
+0:20      '' (in double)
+0:21  Function Definition: ftd(f1;d1;d1; (global void)
+0:21    Function Parameters: 
+0:21      '' (in float)
+0:21      '' (in double)
+0:21      '' (in double)
+0:23  Function Definition: main( (global void)
+0:23    Function Parameters: 
+0:?     Sequence
+0:30      Function Call: foo1(d1;d1; (global void)
+0:30        'd' (temp double)
+0:30        'd' (temp double)
+0:31      Function Call: foo1(d1;u1; (global void)
+0:31        'd' (temp double)
+0:31        'u' (temp uint)
+0:32      Function Call: foo1(d1;i1; (global void)
+0:32        'd' (temp double)
+0:32        'i' (temp int)
+0:33      Function Call: foo1(d1;f1; (global void)
+0:33        'd' (temp double)
+0:33        'f' (temp float)
+0:35      Function Call: foo1(d1;d1; (global void)
+0:35        Convert float to double (temp double)
+0:35          'f' (temp float)
+0:35        'd' (temp double)
+0:36      Function Call: foo1(d1;u1; (global void)
+0:36        Convert float to double (temp double)
+0:36          'f' (temp float)
+0:36        'u' (temp uint)
+0:37      Function Call: foo1(d1;i1; (global void)
+0:37        Convert float to double (temp double)
+0:37          'f' (temp float)
+0:37        'i' (temp int)
+0:38      Function Call: foo1(d1;f1; (global void)
+0:38        Convert float to double (temp double)
+0:38          'f' (temp float)
+0:38        'f' (temp float)
+0:40      Function Call: foo1(d1;d1; (global void)
+0:40        Convert uint to double (temp double)
+0:40          'u' (temp uint)
+0:40        'd' (temp double)
+0:41      Function Call: foo1(d1;u1; (global void)
+0:41        Convert uint to double (temp double)
+0:41          'u' (temp uint)
+0:41        'u' (temp uint)
+0:42      Function Call: foo1(d1;i1; (global void)
+0:42        Convert uint to double (temp double)
+0:42          'u' (temp uint)
+0:42        'i' (temp int)
+0:43      Function Call: foo1(d1;f1; (global void)
+0:43        Convert uint to double (temp double)
+0:43          'u' (temp uint)
+0:43        'f' (temp float)
+0:45      Function Call: foo1(d1;d1; (global void)
+0:45        Convert int to double (temp double)
+0:45          'i' (temp int)
+0:45        'd' (temp double)
+0:46      Function Call: foo1(d1;u1; (global void)
+0:46        Convert int to double (temp double)
+0:46          'i' (temp int)
+0:46        'u' (temp uint)
+0:47      Function Call: foo1(d1;i1; (global void)
+0:47        Convert int to double (temp double)
+0:47          'i' (temp int)
+0:47        'i' (temp int)
+0:48      Function Call: foo1(d1;f1; (global void)
+0:48        Convert int to double (temp double)
+0:48          'i' (temp int)
+0:48        'f' (temp float)
+0:50      Function Call: foo2(d1;d1; (global void)
+0:50        'd' (temp double)
+0:50        'd' (temp double)
+0:51      Function Call: foo2(d1;f1; (global void)
+0:51        'd' (temp double)
+0:51        Convert uint to float (temp float)
+0:51          'u' (temp uint)
+0:52      Function Call: foo2(d1;f1; (global void)
+0:52        'd' (temp double)
+0:52        Convert int to float (temp float)
+0:52          'i' (temp int)
+0:53      Function Call: foo2(d1;f1; (global void)
+0:53        'd' (temp double)
+0:53        'f' (temp float)
+0:55      Function Call: foo2(d1;d1; (global void)
+0:55        Convert float to double (temp double)
+0:55          'f' (temp float)
+0:55        'd' (temp double)
+0:56      Function Call: foo2(d1;f1; (global void)
+0:56        Convert float to double (temp double)
+0:56          'f' (temp float)
+0:56        Convert uint to float (temp float)
+0:56          'u' (temp uint)
+0:57      Function Call: foo2(d1;f1; (global void)
+0:57        Convert float to double (temp double)
+0:57          'f' (temp float)
+0:57        Convert int to float (temp float)
+0:57          'i' (temp int)
+0:58      Function Call: foo2(d1;f1; (global void)
+0:58        Convert float to double (temp double)
+0:58          'f' (temp float)
+0:58        'f' (temp float)
+0:60      Function Call: foo2(d1;d1; (global void)
+0:60        Convert uint to double (temp double)
+0:60          'u' (temp uint)
+0:60        'd' (temp double)
+0:61      Function Call: foo2(d1;f1; (global void)
+0:61        Convert uint to double (temp double)
+0:61          'u' (temp uint)
+0:61        Convert uint to float (temp float)
+0:61          'u' (temp uint)
+0:62      Function Call: foo2(d1;f1; (global void)
+0:62        Convert uint to double (temp double)
+0:62          'u' (temp uint)
+0:62        Convert int to float (temp float)
+0:62          'i' (temp int)
+0:63      Function Call: foo2(d1;f1; (global void)
+0:63        Convert uint to double (temp double)
+0:63          'u' (temp uint)
+0:63        'f' (temp float)
+0:65      Function Call: foo2(d1;d1; (global void)
+0:65        Convert int to double (temp double)
+0:65          'i' (temp int)
+0:65        'd' (temp double)
+0:66      Function Call: foo2(d1;f1; (global void)
+0:66        Convert int to double (temp double)
+0:66          'i' (temp int)
+0:66        Convert uint to float (temp float)
+0:66          'u' (temp uint)
+0:67      Function Call: foo2(d1;f1; (global void)
+0:67        Convert int to double (temp double)
+0:67          'i' (temp int)
+0:67        Convert int to float (temp float)
+0:67          'i' (temp int)
+0:68      Function Call: foo2(d1;f1; (global void)
+0:68        Convert int to double (temp double)
+0:68          'i' (temp int)
+0:68        'f' (temp float)
+0:70      Constant:
+0:70        0.000000
+0:71      Function Call: foo3(d1;f1; (global void)
+0:71        'd' (temp double)
+0:71        Convert uint to float (temp float)
+0:71          'u' (temp uint)
+0:72      Function Call: foo3(d1;f1; (global void)
+0:72        'd' (temp double)
+0:72        Convert int to float (temp float)
+0:72          'i' (temp int)
+0:73      Function Call: foo3(d1;f1; (global void)
+0:73        'd' (temp double)
+0:73        'f' (temp float)
+0:75      Function Call: foo3(f1;d1; (global void)
+0:75        'f' (temp float)
+0:75        'd' (temp double)
+0:76      Function Call: foo3(d1;f1; (global void)
+0:76        Convert float to double (temp double)
+0:76          'f' (temp float)
+0:76        Convert uint to float (temp float)
+0:76          'u' (temp uint)
+0:77      Function Call: foo3(d1;f1; (global void)
+0:77        Convert float to double (temp double)
+0:77          'f' (temp float)
+0:77        Convert int to float (temp float)
+0:77          'i' (temp int)
+0:78      Function Call: foo3(d1;f1; (global void)
+0:78        Convert float to double (temp double)
+0:78          'f' (temp float)
+0:78        'f' (temp float)
+0:80      Function Call: foo3(f1;d1; (global void)
+0:80        Convert uint to float (temp float)
+0:80          'u' (temp uint)
+0:80        'd' (temp double)
+0:81      Function Call: foo3(d1;f1; (global void)
+0:81        Convert uint to double (temp double)
+0:81          'u' (temp uint)
+0:81        Convert uint to float (temp float)
+0:81          'u' (temp uint)
+0:82      Function Call: foo3(d1;f1; (global void)
+0:82        Convert uint to double (temp double)
+0:82          'u' (temp uint)
+0:82        Convert int to float (temp float)
+0:82          'i' (temp int)
+0:83      Function Call: foo3(d1;f1; (global void)
+0:83        Convert uint to double (temp double)
+0:83          'u' (temp uint)
+0:83        'f' (temp float)
+0:85      Function Call: foo3(f1;d1; (global void)
+0:85        Convert int to float (temp float)
+0:85          'i' (temp int)
+0:85        'd' (temp double)
+0:86      Function Call: foo3(d1;f1; (global void)
+0:86        Convert int to double (temp double)
+0:86          'i' (temp int)
+0:86        Convert uint to float (temp float)
+0:86          'u' (temp uint)
+0:87      Function Call: foo3(d1;f1; (global void)
+0:87        Convert int to double (temp double)
+0:87          'i' (temp int)
+0:87        Convert int to float (temp float)
+0:87          'i' (temp int)
+0:88      Function Call: foo3(d1;f1; (global void)
+0:88        Convert int to double (temp double)
+0:88          'i' (temp int)
+0:88        'f' (temp float)
+0:90      Function Call: ftd(i1;f1;d1; (global void)
+0:90        'i' (temp int)
+0:90        'f' (temp float)
+0:90        Convert float to double (temp double)
+0:90          'f' (temp float)
+0:91      Function Call: ftd(u1;f1;d1; (global void)
+0:91        'u' (temp uint)
+0:91        'f' (temp float)
+0:91        Convert float to double (temp double)
+0:91          'f' (temp float)
+0:97  Function Definition: tf( (global void)
+0:97    Function Parameters: 
+0:?     Sequence
+0:104      Function Call: itf(i1;f1;i1; (global void)
+0:104        'i' (temp int)
+0:104        Convert int to float (temp float)
+0:104          'i' (temp int)
+0:104        'i' (temp int)
+0:105      Function Call: itf(i1;f1;i1; (global void)
+0:105        'i' (temp int)
+0:105        Convert uint to float (temp float)
+0:105          'u' (temp uint)
+0:105        'i' (temp int)
 0:?   Linker Objects
 0:?     'd' (in double)
 0:?     'd3' (in 3-component vector of double)
index 090e082..f25c785 100644 (file)
@@ -4895,10 +4895,239 @@ const TFunction* TParseContext::findFunction120(const TSourceLoc& loc, const TFu
 }
 
 // Function finding algorithm for desktop version 400 and above.
+//
+// "When function calls are resolved, an exact type match for all the arguments
+// is sought. If an exact match is found, all other functions are ignored, and
+// the exact match is used. If no exact match is found, then the implicit
+// conversions in section 4.1.10 \93Implicit Conversions\94 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.
+//
+// "If implicit conversions can be used to find more than one matching function,
+// a single best-matching function is sought. To determine a best match, the
+// conversions between calling argument and formal parameter types are compared
+// for each function argument and pair of matching functions. After these
+// comparisons are performed, each pair of matching functions are compared.
+// A function declaration A is considered a better match than function
+// declaration B if
+//
+//  * for at least one function argument, the conversion for that argument in A
+//    is better than the corresponding conversion in B; and
+//  * there is no function argument for which the conversion in B is better than
+//    the corresponding conversion in A.
+//
+// "If a single function declaration is considered a better match than every
+// other matching function declaration, it will be used. Otherwise, a
+// compile-time semantic error for an ambiguous overloaded function call occurs.
+//
+// "To determine whether the conversion for a single argument in one match is
+// better than that for another match, the following rules are applied, in order:
+//
+//  1. An exact match is better than a match involving any implicit conversion.
+//  2. A match involving an implicit conversion from float to double is better
+//     than a match involving any other implicit conversion.
+//  3. A match involving an implicit conversion from either int or uint to float
+//     is better than a match involving an implicit conversion from either int
+//     or uint to double.
+//
+// "If none of the rules above apply to a particular pair of conversions, neither
+// conversion is considered better than the other."
+//
 const TFunction* TParseContext::findFunction400(const TSourceLoc& loc, const TFunction& call, bool& builtIn)
 {
-    // TODO: 4.00 functionality: findFunction400()
-    return findFunction120(loc, call, builtIn);
+    // first, look for an exact match
+    TSymbol* symbol = symbolTable.find(call.getMangledName(), &builtIn);
+    if (symbol)
+        return symbol->getAsFunction();
+
+    // no exact match, use the generic selector, parameterized by the GLSL rules
+
+    // create list of candidates to send
+    TVector<const TFunction*> candidateList;
+    symbolTable.findFunctionNameList(call.getMangledName(), candidateList, builtIn);
+    
+    // can 'from' convert to 'to'?
+    auto convertible = [this](const TType& from, const TType& to) {
+        if (from == to)
+            return true;
+        if (from.isArray() || to.isArray() || ! from.sameElementShape(to))
+            return false;
+        return intermediate.canImplicitlyPromote(from.getBasicType(), to.getBasicType());
+    };
+
+    // Is 'to2' a better conversion than 'to1'?
+    // Ties should not be considered as better.
+    // Assumes 'convertible' already said true.
+    auto better = [](const TType& from, const TType& to1, const TType& to2) {
+        // 1. exact match
+        if (from == to2)
+            return from != to1;
+        if (from == to1)
+            return false;
+
+        // 2. float -> double is better
+        if (from.getBasicType() == EbtFloat) {
+            if (to2.getBasicType() == EbtDouble && to1.getBasicType() != EbtDouble)
+                return true;
+        }
+
+        // 3. -> float is better than -> double
+        return to2.getBasicType() == EbtFloat && to1.getBasicType() == EbtDouble;
+    };
+
+    // for ambiguity reporting
+    bool tie = false;
+    
+    // send to the generic selector
+    const TFunction* bestMatch = selectFunction(candidateList, call, convertible, better, tie);
+
+    if (bestMatch == nullptr)
+        error(loc, "no matching overloaded function found", call.getName().c_str(), "");
+    else if (tie)
+        error(loc, "ambiguous best function under implicit type conversion", call.getName().c_str(), "");
+
+    return bestMatch;
+}
+
+// Select the best matching function for 'call' from 'candidateList'.
+//
+// Assumptions
+//
+// There is no exact match, so a selection algorithm needs to run. That is, the
+// language-specific handler should should check for exact match first, to
+// decide what to do, before calling this selector.
+//
+// Input
+//
+//  * list of candidate signatures to select from
+//  * the call
+//  * a predicate function convertible(from, to) that says whether or not type
+//    'from' can implicitly convert to type 'to' (it includes the case of what
+//    the calling language would consider a matching type with no conversion
+//    needed)
+//  * a predicate function better(from1, from2, to1, to2) that says whether or
+//    not a conversion from from <-> to2 is considered better than a conversion
+//    from <-> to1 (both in and out directions need testing, as declared by the
+//    formal parameter)
+//
+// Output
+//
+//  * best matching candidate (or none, if no viable candidates found)
+//  * whether there was a tie for the best match (ambiguous overload selection,
+//    caller's choice for how to report)
+//
+const TFunction* TParseContextBase::selectFunction(
+    TVector<const TFunction*> candidateList,
+    const TFunction& call,
+    std::function<bool(const TType& from, const TType& to)> convertible,
+    std::function<bool(const TType& from, const TType& to1, const TType& to2)> better,
+    /* output */ bool& tie)
+{
+// 
+// Operation
+// 
+// 1. Prune the input list of candidates down to a list of viable candidates,
+// where each viable candidate has
+// 
+//  * at least as many parameters as there are calling arguments, with any
+//    remainding parameters being optional or having default values
+//  * each parameter is true under convertible(A, B), where A is the calling
+//    type for in and B is the formal type, and in addition, for out B is the
+//    calling type and A is the formal type
+// 
+// 2. If there are no viable candidates, return with no match.
+// 
+// 3. If there is only one viable candidate, it is the best match.
+//
+// 4. If there are multiple viable candidates, select the first viable candidate
+// as the incumbent. Compare the incumbent to the next viable candidate, and if
+// that candidate is better (bullets below), make it the incumbent. Repeat, with
+// a linear walk through the viable candidate list. The final incumbent will be
+// returned as the best match. A viable candidate is better than the incumbent if
+// 
+//  * it has a function argument with a better(...) conversion than the incumbent,
+//    for all directions needed by in and out
+//  * the incumbent has no argument with a better(...) conversion then the
+//    candidate, for either in or out (as needed)
+//
+// 5. Check for ambiguity by comparing the best match against all other viable
+// candidates. If any other viable candidate has a function argument with a
+// better(...) conversion than the best candidate (for either in or out
+// directions), return that there was a tie for best.
+//
+
+    tie = false;
+
+    // 1. prune to viable...
+    TVector<const TFunction*> viableCandidates;
+    for (auto it = candidateList.begin(); it != candidateList.end(); ++it) {
+        const TFunction& candidate = *(*it);
+
+        // to even be a potential match, number of arguments has to match
+        if (call.getParamCount() != candidate.getParamCount())
+            continue;
+
+        // see if arguments are convertible
+        bool viable = true;
+        for (int param = 0; param < candidate.getParamCount(); ++param) {
+            if (candidate[param].type->getQualifier().isParamInput()) {
+                if (! convertible(*call[param].type, *candidate[param].type)) {
+                    viable = false;
+                    break;
+                }
+            }
+            if (candidate[param].type->getQualifier().isParamOutput()) {
+                if (! convertible(*candidate[param].type, *call[param].type)) {
+                    viable = false;
+                    break;
+                }
+            }
+        }
+
+        if (viable)
+            viableCandidates.push_back(&candidate);
+    }
+
+    // 2. none viable...
+    if (viableCandidates.size() == 0)
+        return nullptr;
+
+    // 3. only one viable...
+    if (viableCandidates.size() == 1)
+        return viableCandidates.front();
+
+    // 4. find best...
+    auto betterParam = [&call, &better](const TFunction& can1, const TFunction& can2){
+        // is call -> can2 better than call -> can1 for any parameter
+        bool hasBetterParam = false;
+        for (int param = 0; param < call.getParamCount(); ++param) {
+            if (better(*call[param].type, *can1[param].type, *can2[param].type)) {
+                hasBetterParam = true;
+                break;
+            }
+        }
+        return hasBetterParam;
+    };
+
+    const TFunction* incumbent = viableCandidates.front();
+    for (auto it = viableCandidates.begin() + 1; it != viableCandidates.end(); ++it) {
+        const TFunction& candidate = *(*it);
+        if (betterParam(*incumbent, candidate) && ! betterParam(candidate, *incumbent))
+            incumbent = &candidate;
+    }
+
+    // 5. ambiguity...
+    for (auto it = viableCandidates.begin(); it != viableCandidates.end(); ++it) {
+        if (incumbent == *it)
+            continue;
+        const TFunction& candidate = *(*it);
+        if (betterParam(*incumbent, candidate))
+            tie = true;
+    }
+
+    return incumbent;
 }
 
 // When a declaration includes a type, but not a variable name, it can be 
index 544c3d3..a905619 100644 (file)
@@ -142,6 +142,12 @@ protected:
     std::function<void(int, int, const char*)> versionCallback;
     std::function<void(int, const char*, const char*)> extensionCallback;
     std::function<void(int, const char*)> errorCallback;
+
+    // see implementation for detail
+    const TFunction* selectFunction(TVector<const TFunction*>, const TFunction&,
+        std::function<bool(const TType&, const TType&)>,
+        std::function<bool(const TType&, const TType&, const TType&)>,
+        /* output */ bool& tie);
 };
 
 //