glsl: Reject ambiguous function calls (multiple inexact matches).
authorKenneth Graunke <kenneth@whitecape.org>
Sat, 9 Jul 2011 07:20:34 +0000 (00:20 -0700)
committerKenneth Graunke <kenneth@whitecape.org>
Mon, 11 Jul 2011 17:53:28 +0000 (10:53 -0700)
According to the GLSL 1.20 specification, "it is a semantic error if
there are multiple ways to apply [implicit] conversions [...] such that
the call can be made to match multiple signatures."

Fixes a regression caused by 60eb63a855cb89962f2d5bb91e238ff2d1ab8702,
which implemented the wrong policy of finding a "closest" match.
However, this is not a revert, since the original code failed to
continue looking for an exact match once it found two inexact matches.

It's OK to have multiple inexact matches if there's also an exact match.

NOTE: This is a candidate for the 7.10 and 7.11 branches.

Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=38971
Reviewed-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Kenneth Graunke <kenneth@whitecape.org>
src/glsl/ir_function.cpp

index 1255072a571f137237db5a375ea905a1ac639dd6..0f2f1a0eea473d3fd95801a3643615b279db2975 100644 (file)
@@ -165,8 +165,18 @@ ir_function_signature *
 ir_function::matching_signature(const exec_list *actual_parameters)
 {
    ir_function_signature *match = NULL;
-   int matched_score = 0;
-
+   bool multiple_inexact_matches = false;
+
+   /* From page 42 (page 49 of the PDF) of the GLSL 1.20 spec:
+    *
+    * "If an exact match is found, the other signatures are ignored, and
+    *  the exact match is used.  Otherwise, if no exact match is found, then
+    *  the implicit conversions in Section 4.1.10 "Implicit Conversions" will
+    *  be applied to the calling arguments if this can make their types match
+    *  a signature.  In this case, it is a semantic error if there are
+    *  multiple ways to apply these conversions to the actual arguments of a
+    *  call such that the call can be made to match multiple signatures."
+    */
    foreach_iter(exec_list_iterator, iter, signatures) {
       ir_function_signature *const sig =
         (ir_function_signature *) iter.get();
@@ -178,13 +188,24 @@ ir_function::matching_signature(const exec_list *actual_parameters)
       if (score == 0)
         return sig;
 
-      /* If we found a match with fewer conversions, use that instead */
-      if (score > 0 && (match == NULL || score < matched_score)) {
-        match = sig;
-        matched_score = score;
+      if (score > 0) {
+        if (match == NULL)
+           match = sig;
+        else
+           multiple_inexact_matches = true;
       }
    }
 
+   /* There is no exact match (we would have returned it by now).  If there
+    * are multiple inexact matches, the call is ambiguous, which is an error.
+    *
+    * FINISHME: Report a decent error.  Returning NULL will likely result in
+    * FINISHME: a "no matching signature" error; it should report that the
+    * FINISHME: call is ambiguous.  But reporting errors from here is hard.
+    */
+   if (multiple_inexact_matches)
+      return NULL;
+
    return match;
 }