|
|
|
|
@@ -19,7 +19,7 @@ static inline bool unit_add_base_extension_method(SemaContext *context, Compilat
|
|
|
|
|
static inline bool unit_add_method(SemaContext *context, Type *parent_type, Decl *method);
|
|
|
|
|
static bool sema_analyse_operator_common(SemaContext *context, Decl *method, TypeInfo **rtype_ptr, Decl ***params_ptr,
|
|
|
|
|
uint32_t parameters);
|
|
|
|
|
static inline Decl *operator_in_module_typed(SemaContext *c, Module *module, OperatorOverload operator_overload,
|
|
|
|
|
static inline bool operator_in_module_typed(SemaContext *c, Module *module, OperatorOverload operator_overload,
|
|
|
|
|
OverloadType overload_type, Type *method_type, Expr *binary_arg, Type *binary_type, Decl **candidate_ref, Decl **ambiguous_ref);
|
|
|
|
|
static inline Decl *operator_in_module_exact_typed(Module *module, OperatorOverload operator_overload, OverloadType overload_type, Type *method_type, Type *param_type, Decl *skipped);
|
|
|
|
|
static inline bool sema_analyse_operator_element_at(SemaContext *context, Decl *method);
|
|
|
|
|
@@ -48,7 +48,7 @@ static bool sema_analyse_attributes(SemaContext *context, Decl *decl, Attr **att
|
|
|
|
|
static bool sema_analyse_attributes_for_var(SemaContext *context, Decl *decl, bool *erase_decl);
|
|
|
|
|
static bool sema_check_section(SemaContext *context, Attr *attr);
|
|
|
|
|
static inline bool sema_analyse_attribute_decl(SemaContext *context, SemaContext *c, Decl *decl, bool *erase_decl);
|
|
|
|
|
static Decl *sema_find_typed_operator_in_list(SemaContext *context, Decl **methods, OperatorOverload operator_overload, OverloadType overload_type, Type *parent_type, Expr *binary_arg, Type *binary_type, Decl **candidate_ref, Decl **ambiguous_ref);
|
|
|
|
|
static bool sema_find_typed_operator_in_list(SemaContext *context, Decl **methods, OperatorOverload operator_overload, OverloadType overload_type, Type *parent_type, Expr *binary_arg, Type *binary_type, Decl **candidate_ref, Decl **ambiguous_ref);
|
|
|
|
|
static Decl *sema_find_exact_typed_operator_in_list(Decl **methods, OperatorOverload operator_overload, OverloadType overload_type, Type *parent_type, Type *binary_type, Decl *skipped);
|
|
|
|
|
|
|
|
|
|
static inline bool sema_analyse_typedef(SemaContext *context, Decl *decl, bool *erase_decl);
|
|
|
|
|
@@ -1709,16 +1709,15 @@ INLINE bool decl_matches_overload(Decl *method, Type *type, OperatorOverload ove
|
|
|
|
|
return method->func_decl.operator == overload && typeget(method->func_decl.type_parent)->canonical == type;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline Decl *operator_in_module_typed(SemaContext *c, Module *module, OperatorOverload operator_overload, OverloadType overload_type, Type *method_type, Expr *binary_arg, Type *binary_type, Decl **candidate_ref, Decl **ambiguous_ref)
|
|
|
|
|
static inline bool operator_in_module_typed(SemaContext *c, Module *module, OperatorOverload operator_overload, OverloadType overload_type, Type *method_type, Expr *binary_arg, Type *binary_type, Decl **candidate_ref, Decl **ambiguous_ref)
|
|
|
|
|
{
|
|
|
|
|
if (module->is_generic) return NULL;
|
|
|
|
|
Decl *found = sema_find_typed_operator_in_list(c, module->private_method_extensions, operator_overload, OVERLOAD_TYPE_SYMMETRIC, method_type, binary_arg, binary_type, candidate_ref, ambiguous_ref);
|
|
|
|
|
if (found) return found;
|
|
|
|
|
if (!sema_find_typed_operator_in_list(c, module->private_method_extensions, operator_overload, OVERLOAD_TYPE_SYMMETRIC, method_type, binary_arg, binary_type, candidate_ref, ambiguous_ref)) return false;
|
|
|
|
|
FOREACH(Module *, sub_module, module->sub_modules)
|
|
|
|
|
{
|
|
|
|
|
return operator_in_module_typed(c, sub_module, operator_overload, overload_type, method_type, binary_arg, binary_type, candidate_ref, ambiguous_ref);
|
|
|
|
|
if (!operator_in_module_typed(c, sub_module, operator_overload, overload_type, method_type, binary_arg, binary_type, candidate_ref, ambiguous_ref)) return false;
|
|
|
|
|
}
|
|
|
|
|
return NULL;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline Decl *operator_in_module_exact_typed(Module *module, OperatorOverload operator_overload, OverloadType overload_type, Type *method_type, Type *param_type, Decl *skipped)
|
|
|
|
|
@@ -1779,6 +1778,7 @@ Decl *sema_find_untyped_operator(SemaContext *context, Type *type, OperatorOverl
|
|
|
|
|
|
|
|
|
|
static Decl *sema_find_exact_typed_operator_in_list(Decl **methods, OperatorOverload operator_overload, OverloadType overload_type, Type *parent_type, Type *binary_type, Decl *skipped)
|
|
|
|
|
{
|
|
|
|
|
Decl *wildcard = NULL;
|
|
|
|
|
FOREACH(Decl *, func, methods)
|
|
|
|
|
{
|
|
|
|
|
if (func == skipped) continue;
|
|
|
|
|
@@ -1786,39 +1786,46 @@ static Decl *sema_find_exact_typed_operator_in_list(Decl **methods, OperatorOver
|
|
|
|
|
if (func->func_decl.operator != operator_overload) continue;
|
|
|
|
|
if (parent_type && parent_type != typeget(func->func_decl.type_parent)) continue;
|
|
|
|
|
if ((overload_type & func->func_decl.overload_type) == 0) continue;
|
|
|
|
|
Type *first_arg = func->func_decl.signature.params[1]->type->canonical;
|
|
|
|
|
if (first_arg != binary_type) continue;
|
|
|
|
|
if (func->func_decl.is_wildcard_overload)
|
|
|
|
|
{
|
|
|
|
|
wildcard = func;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
Type *first_arg = func->func_decl.signature.params[1]->type;
|
|
|
|
|
if (first_arg->canonical != binary_type) continue;
|
|
|
|
|
return func;
|
|
|
|
|
}
|
|
|
|
|
return NULL;
|
|
|
|
|
return wildcard;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static Decl *sema_find_typed_operator_in_list(SemaContext *context, Decl **methods, OperatorOverload operator_overload, OverloadType overload_type, Type *parent_type, Expr *binary_arg, Type *binary_type, Decl **candidate_ref, Decl **ambiguous_ref)
|
|
|
|
|
static bool sema_find_typed_operator_in_list(SemaContext *context, Decl **methods, OperatorOverload operator_overload, OverloadType overload_type, Type *parent_type, Expr *binary_arg, Type *binary_type, Decl **candidate_ref, Decl **ambiguous_ref)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
Decl *candidate = *candidate_ref;
|
|
|
|
|
FOREACH(Decl *, func, methods)
|
|
|
|
|
{
|
|
|
|
|
if (func->func_decl.operator != operator_overload) continue;
|
|
|
|
|
if (parent_type && parent_type != typeget(func->func_decl.type_parent)) continue;
|
|
|
|
|
if ((overload_type & func->func_decl.overload_type) == 0) continue;
|
|
|
|
|
Type *first_arg = func->func_decl.signature.params[1]->type->canonical;
|
|
|
|
|
if (first_arg != binary_type)
|
|
|
|
|
if (!func->func_decl.is_wildcard_overload)
|
|
|
|
|
{
|
|
|
|
|
if (!binary_arg) continue;
|
|
|
|
|
if (may_cast(context, binary_arg, first_arg, false, true))
|
|
|
|
|
Type *first_arg = func->func_decl.signature.params[1]->type->canonical;
|
|
|
|
|
if (first_arg != binary_type)
|
|
|
|
|
{
|
|
|
|
|
if (*candidate_ref)
|
|
|
|
|
{
|
|
|
|
|
*ambiguous_ref = func;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
*candidate_ref = func;
|
|
|
|
|
if (!binary_arg) continue;
|
|
|
|
|
if (!may_cast(context, binary_arg, first_arg, false, true)) continue;
|
|
|
|
|
}
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
unit_register_external_symbol(context, func);
|
|
|
|
|
return func;
|
|
|
|
|
if (candidate && !candidate->func_decl.is_wildcard_overload)
|
|
|
|
|
{
|
|
|
|
|
*ambiguous_ref = func;
|
|
|
|
|
*candidate_ref = candidate;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
candidate = func;
|
|
|
|
|
}
|
|
|
|
|
return NULL;
|
|
|
|
|
*candidate_ref = candidate;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static Decl *sema_find_exact_typed_operator(SemaContext *context, Type *type, OperatorOverload operator_overload, OverloadType overload_type, Type *param_type, Decl *skipped)
|
|
|
|
|
@@ -1848,67 +1855,69 @@ static Decl *sema_find_exact_typed_operator(SemaContext *context, Type *type, Op
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static Decl *sema_find_typed_operator_type(SemaContext *context, OperatorOverload operator_overload, OverloadType overloat_type, Type *lhs_type, Type *rhs_type, Expr *rhs, Decl **candidate_ref, Decl **ambiguous_ref)
|
|
|
|
|
static bool sema_find_typed_operator_type(SemaContext *context, OperatorOverload operator_overload, OverloadType overloat_type, Type *lhs_type, Type *rhs_type, Expr *rhs, Decl **candidate_ref, Decl **ambiguous_ref)
|
|
|
|
|
{
|
|
|
|
|
// Can we find the overload directly on the method?
|
|
|
|
|
Decl *func = sema_find_typed_operator_in_list(context, lhs_type->decl->methods, operator_overload, overloat_type, lhs_type,
|
|
|
|
|
rhs, rhs_type, candidate_ref, ambiguous_ref);
|
|
|
|
|
if (func) return func;
|
|
|
|
|
if (!sema_find_typed_operator_in_list(context, lhs_type->decl->methods,
|
|
|
|
|
operator_overload, overloat_type, lhs_type,
|
|
|
|
|
rhs, rhs_type, candidate_ref, ambiguous_ref)) return false;
|
|
|
|
|
// Can we find it as a local extension?
|
|
|
|
|
Decl *extension = sema_find_typed_operator_in_list(context, context->unit->local_method_extensions,
|
|
|
|
|
operator_overload, overloat_type, lhs_type, rhs, rhs_type, candidate_ref, ambiguous_ref);
|
|
|
|
|
if (!sema_find_typed_operator_in_list(context, context->unit->local_method_extensions,
|
|
|
|
|
operator_overload, overloat_type, lhs_type, rhs, rhs_type, candidate_ref, ambiguous_ref)) return false;
|
|
|
|
|
|
|
|
|
|
// Can we find it in the current module?
|
|
|
|
|
if (extension) return extension;
|
|
|
|
|
extension = operator_in_module_typed(context, context->compilation_unit->module, operator_overload, overloat_type,
|
|
|
|
|
lhs_type, rhs, rhs_type, candidate_ref, ambiguous_ref);
|
|
|
|
|
if (extension) return extension;
|
|
|
|
|
// TODO incorrect, doesn't recurse
|
|
|
|
|
// Look through our public imports
|
|
|
|
|
if (!operator_in_module_typed(context, context->compilation_unit->module, operator_overload, overloat_type,
|
|
|
|
|
lhs_type, rhs, rhs_type, candidate_ref, ambiguous_ref)) return false;
|
|
|
|
|
FOREACH(Decl *, import, context->unit->public_imports)
|
|
|
|
|
{
|
|
|
|
|
extension = operator_in_module_typed(context, import->import.module, operator_overload, overloat_type,
|
|
|
|
|
lhs_type, rhs, rhs_type, candidate_ref, ambiguous_ref);
|
|
|
|
|
if (extension) return extension;
|
|
|
|
|
if (!operator_in_module_typed(context, import->import.module, operator_overload, overloat_type,
|
|
|
|
|
lhs_type, rhs, rhs_type, candidate_ref, ambiguous_ref)) return false;
|
|
|
|
|
}
|
|
|
|
|
return NULL;
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Decl *sema_find_typed_operator(SemaContext *context, OperatorOverload operator_overload, Expr *lhs, Expr *rhs, Decl **ambiguous_ref, bool *reverse)
|
|
|
|
|
{
|
|
|
|
|
assert(operator_overload >= OVERLOAD_TYPED_START);
|
|
|
|
|
assert(lhs && rhs && ambiguous_ref);
|
|
|
|
|
Type *left_type = type_no_optional(lhs->type)->canonical;
|
|
|
|
|
Type *right_type = type_no_optional(rhs->type)->canonical;
|
|
|
|
|
|
|
|
|
|
Decl *candidate = NULL;
|
|
|
|
|
Decl *ambiguous = NULL;
|
|
|
|
|
Decl *left_candidate = NULL;
|
|
|
|
|
*reverse = false;
|
|
|
|
|
if (type_is_user_defined(left_type))
|
|
|
|
|
{
|
|
|
|
|
Decl *found = sema_find_typed_operator_type(context, operator_overload, OVERLOAD_TYPE_LEFT, left_type, right_type, rhs, &candidate, &ambiguous);
|
|
|
|
|
if (found) return found;
|
|
|
|
|
if (!sema_find_typed_operator_type(context, operator_overload, OVERLOAD_TYPE_LEFT, left_type, right_type, rhs, &candidate, &ambiguous)) return NULL;
|
|
|
|
|
left_candidate = candidate;
|
|
|
|
|
}
|
|
|
|
|
candidate = NULL;
|
|
|
|
|
if (type_is_user_defined(right_type))
|
|
|
|
|
{
|
|
|
|
|
Decl *found = sema_find_typed_operator_type(context, operator_overload, OVERLOAD_TYPE_RIGHT, right_type, left_type, lhs, &candidate, &ambiguous);
|
|
|
|
|
if (found)
|
|
|
|
|
{
|
|
|
|
|
*reverse = true;
|
|
|
|
|
return found;
|
|
|
|
|
}
|
|
|
|
|
if (!sema_find_typed_operator_type(context, operator_overload, OVERLOAD_TYPE_RIGHT, right_type, left_type, lhs, &candidate, &ambiguous)) return NULL;
|
|
|
|
|
}
|
|
|
|
|
if (ambiguous)
|
|
|
|
|
|
|
|
|
|
// If one or the other is missing, pick the right one.
|
|
|
|
|
if (!left_candidate)
|
|
|
|
|
{
|
|
|
|
|
*ambiguous_ref = ambiguous;
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
if (candidate)
|
|
|
|
|
{
|
|
|
|
|
*reverse = candidate != left_candidate;
|
|
|
|
|
*reverse = true;
|
|
|
|
|
return candidate;
|
|
|
|
|
}
|
|
|
|
|
if (!candidate) return left_candidate;
|
|
|
|
|
|
|
|
|
|
// Both exist, prefer non-wildcard
|
|
|
|
|
if (left_candidate->func_decl.is_wildcard_overload && !candidate->func_decl.is_wildcard_overload)
|
|
|
|
|
{
|
|
|
|
|
*reverse = true;
|
|
|
|
|
return candidate;
|
|
|
|
|
}
|
|
|
|
|
if (candidate->func_decl.is_wildcard_overload && !left_candidate->func_decl.is_wildcard_overload)
|
|
|
|
|
{
|
|
|
|
|
return left_candidate;
|
|
|
|
|
}
|
|
|
|
|
*ambiguous_ref = candidate;
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -2193,7 +2202,22 @@ INLINE bool sema_analyse_operator_method(SemaContext *context, Type *parent_type
|
|
|
|
|
// See if the operator has already been defined.
|
|
|
|
|
OperatorOverload operator = method->func_decl.operator;
|
|
|
|
|
|
|
|
|
|
Type *second_param = vec_size(method->func_decl.signature.params) > 1 ? method->func_decl.signature.params[1]->type->canonical : NULL;
|
|
|
|
|
|
|
|
|
|
Type *second_param = NULL;
|
|
|
|
|
if (vec_size(method->func_decl.signature.params) > 1)
|
|
|
|
|
{
|
|
|
|
|
second_param = method->func_decl.signature.params[1]->type;
|
|
|
|
|
if (!second_param)
|
|
|
|
|
{
|
|
|
|
|
if (method->func_decl.overload_type & OVERLOAD_TYPE_RIGHT)
|
|
|
|
|
{
|
|
|
|
|
RETURN_SEMA_ERROR(method, "Only regular overloads can have untyped right hand parameters");
|
|
|
|
|
}
|
|
|
|
|
method->func_decl.is_wildcard_overload = true;
|
|
|
|
|
second_param = type_void;
|
|
|
|
|
}
|
|
|
|
|
second_param = second_param->canonical;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!type_is_user_defined(parent_type))
|
|
|
|
|
{
|
|
|
|
|
|