Factor out parameter list matching from ast_function::hir for later reuse.
Unfortunately, we still have two kinds of matching - one, with implicit conversions (for use in calls) and another without them (for finding a prototype to overwrite when processing a function body). This commit does not attempt to coalesce the two.
This commit is contained in:

committed by
Ian Romanick

parent
abd40b1521
commit
0d605cb97c
@@ -1883,36 +1883,6 @@ ast_parameter_declarator::parameters_to_hir(struct simple_node *ast_parameters,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static bool
|
|
||||||
parameter_lists_match(exec_list *list_a, exec_list *list_b)
|
|
||||||
{
|
|
||||||
exec_list_iterator iter_a = list_a->iterator();
|
|
||||||
exec_list_iterator iter_b = list_b->iterator();
|
|
||||||
|
|
||||||
while (iter_a.has_next() && iter_b.has_next()) {
|
|
||||||
ir_variable *a = (ir_variable *)iter_a.get();
|
|
||||||
ir_variable *b = (ir_variable *)iter_b.get();
|
|
||||||
|
|
||||||
/* If the types of the parameters do not match, the parameters lists
|
|
||||||
* are different.
|
|
||||||
*/
|
|
||||||
if (a->type != b->type)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
iter_a.next();
|
|
||||||
iter_b.next();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Unless both lists are exhausted, they differ in length and, by
|
|
||||||
* definition, do not match.
|
|
||||||
*/
|
|
||||||
if (iter_a.has_next() != iter_b.has_next())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
ir_rvalue *
|
ir_rvalue *
|
||||||
ast_function::hir(exec_list *instructions,
|
ast_function::hir(exec_list *instructions,
|
||||||
struct _mesa_glsl_parse_state *state)
|
struct _mesa_glsl_parse_state *state)
|
||||||
@@ -1943,45 +1913,30 @@ ast_function::hir(exec_list *instructions,
|
|||||||
const char *const name = identifier;
|
const char *const name = identifier;
|
||||||
f = state->symbols->get_function(name);
|
f = state->symbols->get_function(name);
|
||||||
if (f != NULL) {
|
if (f != NULL) {
|
||||||
foreach_iter(exec_list_iterator, iter, *f) {
|
ir_function_signature *sig = f->exact_matching_signature(&hir_parameters);
|
||||||
sig = (struct ir_function_signature *) iter.get();
|
if (sig != NULL) {
|
||||||
|
const char *badvar = sig->qualifiers_match(&hir_parameters);
|
||||||
|
if (badvar != NULL) {
|
||||||
|
YYLTYPE loc = this->get_location();
|
||||||
|
|
||||||
/* Compare the parameter list of the function being defined to the
|
_mesa_glsl_error(&loc, state, "function `%s' parameter `%s' "
|
||||||
* existing function. If the parameter lists match, then the return
|
"qualifiers don't match prototype", name, badvar);
|
||||||
* type must also match and the existing function must not have a
|
|
||||||
* definition.
|
|
||||||
*/
|
|
||||||
if (parameter_lists_match(& hir_parameters, & sig->parameters)) {
|
|
||||||
const char *mismatch = sig->qualifiers_match(&hir_parameters);
|
|
||||||
if (mismatch != NULL) {
|
|
||||||
YYLTYPE loc = this->get_location();
|
|
||||||
|
|
||||||
_mesa_glsl_error(&loc, state, "function `%s' parameter `%s' "
|
|
||||||
"qualifiers don't match prototype",
|
|
||||||
name, mismatch);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sig->return_type != return_type) {
|
|
||||||
YYLTYPE loc = this->get_location();
|
|
||||||
|
|
||||||
_mesa_glsl_error(& loc, state,
|
|
||||||
"function `%s' return type doesn't match "
|
|
||||||
"prototype",
|
|
||||||
name);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_definition && sig->is_defined) {
|
|
||||||
YYLTYPE loc = this->get_location();
|
|
||||||
|
|
||||||
_mesa_glsl_error(& loc, state, "function `%s' redefined", name);
|
|
||||||
sig = NULL;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sig = NULL;
|
if (sig->return_type != return_type) {
|
||||||
}
|
YYLTYPE loc = this->get_location();
|
||||||
|
|
||||||
|
_mesa_glsl_error(&loc, state, "function `%s' return type doesn't "
|
||||||
|
"match prototype", name);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_definition && sig->is_defined) {
|
||||||
|
YYLTYPE loc = this->get_location();
|
||||||
|
|
||||||
|
_mesa_glsl_error(& loc, state, "function `%s' redefined", name);
|
||||||
|
sig = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
} else if (state->symbols->name_declared_this_scope(name)) {
|
} else if (state->symbols->name_declared_this_scope(name)) {
|
||||||
/* This function name shadows a non-function use of the same name.
|
/* This function name shadows a non-function use of the same name.
|
||||||
*/
|
*/
|
||||||
|
9
ir.h
9
ir.h
@@ -276,10 +276,17 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find a signature that matches a set of actual parameters.
|
* Find a signature that matches a set of actual parameters, taking implicit
|
||||||
|
* conversions into account.
|
||||||
*/
|
*/
|
||||||
const ir_function_signature *matching_signature(exec_list *actual_param);
|
const ir_function_signature *matching_signature(exec_list *actual_param);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find a signature that exactly matches a set of actual parameters without
|
||||||
|
* any implicit type conversions.
|
||||||
|
*/
|
||||||
|
ir_function_signature *exact_matching_signature(exec_list *actual_ps);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Name of the function.
|
* Name of the function.
|
||||||
*/
|
*/
|
||||||
|
@@ -180,3 +180,46 @@ ir_function::matching_signature(exec_list *actual_parameters)
|
|||||||
|
|
||||||
return match;
|
return match;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static bool
|
||||||
|
parameter_lists_match_exact(exec_list *list_a, exec_list *list_b)
|
||||||
|
{
|
||||||
|
exec_list_iterator iter_a = list_a->iterator();
|
||||||
|
exec_list_iterator iter_b = list_b->iterator();
|
||||||
|
|
||||||
|
while (iter_a.has_next() && iter_b.has_next()) {
|
||||||
|
ir_variable *a = (ir_variable *)iter_a.get();
|
||||||
|
ir_variable *b = (ir_variable *)iter_b.get();
|
||||||
|
|
||||||
|
/* If the types of the parameters do not match, the parameters lists
|
||||||
|
* are different.
|
||||||
|
*/
|
||||||
|
if (a->type != b->type)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
iter_a.next();
|
||||||
|
iter_b.next();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Unless both lists are exhausted, they differ in length and, by
|
||||||
|
* definition, do not match.
|
||||||
|
*/
|
||||||
|
if (iter_a.has_next() != iter_b.has_next())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
ir_function_signature *
|
||||||
|
ir_function::exact_matching_signature(exec_list *actual_parameters)
|
||||||
|
{
|
||||||
|
foreach_iter(exec_list_iterator, iter, signatures) {
|
||||||
|
ir_function_signature *const sig =
|
||||||
|
(ir_function_signature *) iter.get();
|
||||||
|
|
||||||
|
if (parameter_lists_match_exact(&sig->parameters, actual_parameters))
|
||||||
|
return sig;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user