restricted c header imports
This commit is contained in:
@@ -409,6 +409,62 @@ add_call_resolution_diagnostic :: proc(checker: ^Checker, expr: ast.Expr, target
|
||||
return source.addf(checker.diagnostics, expr.span, "unresolved function '%s'", symbol_text(checker, expr.name))
|
||||
}
|
||||
|
||||
find_unsupported :: proc(checker: ^Checker, pkg: ast.Package_Id, name: symbol.Id) -> (ast.Unsupported, bool) {
|
||||
for item in checker.ast_module.unsupported {
|
||||
if item.pkg == pkg && item.name == name {
|
||||
return item, true
|
||||
}
|
||||
}
|
||||
return {}, false
|
||||
}
|
||||
|
||||
add_unsupported_diagnostic :: proc(checker: ^Checker, span: source.Span, pkg: ast.Package_Id, name: symbol.Id) -> source.Diagnostic_Id {
|
||||
if item, ok := find_unsupported(checker, pkg, name); ok {
|
||||
return source.addf(
|
||||
checker.diagnostics,
|
||||
span,
|
||||
"C declaration '%s' is unavailable: %s",
|
||||
symbol_text(checker, name),
|
||||
item.reason,
|
||||
)
|
||||
}
|
||||
return source.INVALID_DIAGNOSTIC
|
||||
}
|
||||
|
||||
add_unsupported_type_diagnostic :: proc(
|
||||
checker: ^Checker,
|
||||
span: source.Span,
|
||||
value: types.Type,
|
||||
depth := 0,
|
||||
) -> source.Diagnostic_Id {
|
||||
if depth > 64 {
|
||||
return source.INVALID_DIAGNOSTIC
|
||||
}
|
||||
item, ok := types.node(&checker.module.types, value)
|
||||
if !ok {
|
||||
return source.INVALID_DIAGNOSTIC
|
||||
}
|
||||
if item.kind == .Alias {
|
||||
return add_unsupported_diagnostic(checker, span, ast.Package_Id(item.pkg), symbol.Id(item.name))
|
||||
}
|
||||
if types.is_valid(item.child) {
|
||||
return add_unsupported_type_diagnostic(checker, span, item.child, depth+1)
|
||||
}
|
||||
return source.INVALID_DIAGNOSTIC
|
||||
}
|
||||
|
||||
function_signatures_equal :: proc(left, right: ast.Function) -> bool {
|
||||
if left.result != right.result || len(left.params) != len(right.params) {
|
||||
return false
|
||||
}
|
||||
for param, index in left.params {
|
||||
if param.type != right.params[index].type {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
contains_name :: proc(names: []symbol.Id, name: symbol.Id) -> bool {
|
||||
for existing in names {
|
||||
if existing == name {
|
||||
@@ -454,9 +510,17 @@ mark_expr_imports_used :: proc(checker: ^Checker, expr_id: ast.Expr_Id, file: as
|
||||
|
||||
validate_declarations :: proc(checker: ^Checker) {
|
||||
for function, function_id in checker.ast_module.functions {
|
||||
if len(function.unsupported_reason) > 0 {
|
||||
continue
|
||||
}
|
||||
locals: [dynamic]symbol.Id
|
||||
locals.allocator = checker.allocator
|
||||
for param in function.params {
|
||||
if diagnostic := add_unsupported_type_diagnostic(checker, param.span, type_from_syntax(param.type));
|
||||
diagnostic != source.INVALID_DIAGNOSTIC {
|
||||
checker.template_diagnostics[function_id] = diagnostic
|
||||
continue
|
||||
}
|
||||
if param.type == types.VOID {
|
||||
source.add(
|
||||
checker.diagnostics,
|
||||
@@ -482,6 +546,10 @@ validate_declarations :: proc(checker: ^Checker) {
|
||||
)
|
||||
}
|
||||
}
|
||||
if diagnostic := add_unsupported_type_diagnostic(checker, function.span, type_from_syntax(function.result));
|
||||
diagnostic != source.INVALID_DIAGNOSTIC {
|
||||
checker.template_diagnostics[function_id] = diagnostic
|
||||
}
|
||||
if types.contains_c_struct_by_value(type_from_syntax(function.result), &checker.module.types) {
|
||||
checker.template_diagnostics[function_id] = source.addf(
|
||||
checker.diagnostics,
|
||||
@@ -500,6 +568,10 @@ validate_declarations :: proc(checker: ^Checker) {
|
||||
}
|
||||
if !function.has_body && function.c_abi {
|
||||
for param in function.params {
|
||||
if add_unsupported_type_diagnostic(checker, param.span, type_from_syntax(param.type)) !=
|
||||
source.INVALID_DIAGNOSTIC {
|
||||
continue
|
||||
}
|
||||
if !types.is_c_signature_type(type_from_syntax(param.type), &checker.module.types) {
|
||||
checker.template_diagnostics[function_id] = source.addf(
|
||||
checker.diagnostics,
|
||||
@@ -510,7 +582,8 @@ validate_declarations :: proc(checker: ^Checker) {
|
||||
}
|
||||
}
|
||||
result := type_from_syntax(function.result)
|
||||
if !types.is_c_signature_type(result, &checker.module.types, true) {
|
||||
if add_unsupported_type_diagnostic(checker, function.span, result) == source.INVALID_DIAGNOSTIC &&
|
||||
!types.is_c_signature_type(result, &checker.module.types, true) {
|
||||
checker.template_diagnostics[function_id] = source.addf(
|
||||
checker.diagnostics,
|
||||
function.span,
|
||||
@@ -547,6 +620,9 @@ validate_declarations :: proc(checker: ^Checker) {
|
||||
if other_id == function_id || other.has_body || !other.c_abi || other.name != function.name {
|
||||
continue
|
||||
}
|
||||
if function.imported && other.imported && function_signatures_equal(function, other) {
|
||||
continue
|
||||
}
|
||||
checker.template_diagnostics[function_id] = source.addf(
|
||||
checker.diagnostics,
|
||||
function.span,
|
||||
@@ -901,6 +977,11 @@ infer_expr :: proc(
|
||||
_ = pop(&stack)
|
||||
continue
|
||||
}
|
||||
if len(checker.ast_module.functions[template].unsupported_reason) > 0 {
|
||||
last = types.INVALID
|
||||
_ = pop(&stack)
|
||||
continue
|
||||
}
|
||||
if checker.template_diagnostics[template] != source.INVALID_DIAGNOSTIC {
|
||||
declared := type_from_syntax(checker.ast_module.functions[template].result)
|
||||
last = declared if is_runtime_type(checker, declared) || types.is_void(declared) else types.INVALID
|
||||
@@ -1185,8 +1266,15 @@ coerce_expr :: proc(
|
||||
return expr_id
|
||||
}
|
||||
if types.can_weaken_pointer(actual, expected, &checker.module.types) {
|
||||
checker.module.exprs[expr_id].type = expected
|
||||
return expr_id
|
||||
return add_hir_expr(checker, hir.Expr{
|
||||
kind=.Weaken_Pointer,
|
||||
span=span,
|
||||
type=expected,
|
||||
left=expr_id,
|
||||
target=hir.INVALID_REF,
|
||||
right=hir.INVALID_EXPR,
|
||||
diagnostic=source.INVALID_DIAGNOSTIC,
|
||||
})
|
||||
}
|
||||
if types.is_optional(expected, &checker.module.types) {
|
||||
child := types.child_type(expected, &checker.module.types)
|
||||
@@ -1754,7 +1842,10 @@ build_expr :: proc(
|
||||
target=hir.global_ref(hir_global), left = hir.INVALID_EXPR, right = hir.INVALID_EXPR, diagnostic = source.INVALID_DIAGNOSTIC,
|
||||
})
|
||||
} else {
|
||||
id := add_name_resolution_diagnostic(checker, expr, target_pkg)
|
||||
id := add_unsupported_diagnostic(checker, expr.span, target_pkg, expr.name)
|
||||
if id == source.INVALID_DIAGNOSTIC {
|
||||
id = add_name_resolution_diagnostic(checker, expr, target_pkg)
|
||||
}
|
||||
last = invalid_hir_expr(checker, expr.span, id)
|
||||
}
|
||||
}
|
||||
@@ -1775,7 +1866,22 @@ build_expr :: proc(
|
||||
}
|
||||
template := find_template(checker, expr.name, target_pkg)
|
||||
if template == ast.INVALID_FUNCTION {
|
||||
id := add_call_resolution_diagnostic(checker, expr, target_pkg)
|
||||
id := add_unsupported_diagnostic(checker, expr.span, target_pkg, expr.name)
|
||||
if id == source.INVALID_DIAGNOSTIC {
|
||||
id = add_call_resolution_diagnostic(checker, expr, target_pkg)
|
||||
}
|
||||
last = invalid_hir_expr(checker, expr.span, id)
|
||||
_ = pop(&stack)
|
||||
continue
|
||||
}
|
||||
if len(checker.ast_module.functions[template].unsupported_reason) > 0 {
|
||||
id := source.addf(
|
||||
checker.diagnostics,
|
||||
expr.span,
|
||||
"C declaration '%s' is unavailable: %s",
|
||||
symbol_text(checker, expr.name),
|
||||
checker.ast_module.functions[template].unsupported_reason,
|
||||
)
|
||||
last = invalid_hir_expr(checker, expr.span, id)
|
||||
_ = pop(&stack)
|
||||
continue
|
||||
|
||||
Reference in New Issue
Block a user