glsl: Reject ambiguous function calls (multiple inexact matches).

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 60eb63a855,
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>
This commit is contained in:
Kenneth Graunke 2011-07-09 00:20:34 -07:00
parent 186e37c754
commit 7304909d65
1 changed files with 26 additions and 5 deletions

View 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;
}