diff --git a/Test/400.vert b/Test/400.vert index 2c3dd0424..315c7ea04 100644 --- a/Test/400.vert +++ b/Test/400.vert @@ -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) {} +void foo1(double a, int b) {} +void foo1(double a, float b) {} +void foo1(double a, double b){} + +void foo2(double a, float b) {} +void foo2(double a, double b){} + +void foo3(double a, float b) {} +void foo3(float a, double b) {} + +void ftd( int, float, double) {} +void ftd( uint, float, double) {} +void ftd(float, double, double) {} + +void main() +{ + double d; + uint u; + int i; + float f; + + foo1(d, d); + foo1(d, u); + foo1(d, i); + foo1(d, f); + + foo1(f, d); + foo1(f, u); + foo1(f, i); + foo1(f, f); + + foo1(u, d); + foo1(u, u); + foo1(u, i); + foo1(u, f); + + foo1(i, d); + foo1(i, u); + foo1(i, i); + foo1(i, f); + + foo2(d, d); + foo2(d, u); + foo2(d, i); + foo2(d, f); + + foo2(f, d); + foo2(f, u); + foo2(f, i); + foo2(f, f); + + foo2(u, d); + foo2(u, u); + foo2(u, i); + foo2(u, f); + + foo2(i, d); + foo2(i, u); + foo2(i, i); + foo2(i, f); + + foo3(d, d); // ERROR, no match + foo3(d, u); + foo3(d, i); + foo3(d, f); + + foo3(f, d); + foo3(f, u); // ERROR, ambiguous + foo3(f, i); // ERROR, ambiguous + foo3(f, f); // ERROR, ambiguous + + foo3(u, d); + foo3(u, u); // ERROR, ambiguous + foo3(u, i); // ERROR, ambiguous + foo3(u, f); // ERROR, ambiguous + + foo3(i, d); + foo3(i, u); // ERROR, ambiguous + foo3(i, i); // ERROR, ambiguous + foo3(i, f); // ERROR, ambiguous + + ftd(i, f, f); + ftd(u, f, f); +} + +void itf(int, float, int); +void itf(int, double, int); + +void tf() +{ + double d; + uint u; + int i; + float f; + + itf(i, i, i); + itf(i, u, i); } diff --git a/Test/baseResults/400.vert.out b/Test/baseResults/400.vert.out index 946f21d58..2b0d63da1 100755 --- a/Test/baseResults/400.vert.out +++ b/Test/baseResults/400.vert.out @@ -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) diff --git a/glslang/MachineIndependent/ParseHelper.cpp b/glslang/MachineIndependent/ParseHelper.cpp index 090e082e9..f25c78511 100644 --- a/glslang/MachineIndependent/ParseHelper.cpp +++ b/glslang/MachineIndependent/ParseHelper.cpp @@ -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 “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. +// +// "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 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 candidateList, + const TFunction& call, + std::function convertible, + std::function 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 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 diff --git a/glslang/MachineIndependent/ParseHelper.h b/glslang/MachineIndependent/ParseHelper.h index 544c3d30d..a9056196a 100644 --- a/glslang/MachineIndependent/ParseHelper.h +++ b/glslang/MachineIndependent/ParseHelper.h @@ -142,6 +142,12 @@ protected: std::function versionCallback; std::function extensionCallback; std::function errorCallback; + + // see implementation for detail + const TFunction* selectFunction(TVector, const TFunction&, + std::function, + std::function, + /* output */ bool& tie); }; //