From 906b207e5835d89b971af26ca267b158658cbffe Mon Sep 17 00:00:00 2001 From: Enzo Date: Thu, 20 May 2021 08:17:44 +0200 Subject: [PATCH] checker: deprecate using V strings in C function calls (#10140) --- doc/docs.md | 2 +- examples/c_interop_wkhtmltopdf.v | 2 +- examples/sokol/fonts.v | 2 +- examples/sokol/freetype_raven.v | 2 +- vlib/gg/text_rendering.v | 16 ++++++++-------- vlib/glm/glm.v | 2 +- vlib/net/http/backend_nix.c.v | 2 +- vlib/net/openssl/c.v | 2 +- vlib/v/checker/checker.v | 10 ++++++++++ vlib/v/gen/c/fn.v | 2 +- vlib/v/gen/c/str.v | 6 ------ vlib/v/tests/cstrings_test.v | 2 -- vlib/v/util/quote.v | 2 +- 13 files changed, 27 insertions(+), 25 deletions(-) diff --git a/doc/docs.md b/doc/docs.md index 59c1861a92..789c4f972c 100644 --- a/doc/docs.md +++ b/doc/docs.md @@ -3506,7 +3506,7 @@ fn my_callback(arg voidptr, howmany int, cvalues &&char, cnames &&char) int { fn main() { db := &C.sqlite3(0) // this means `sqlite3* db = 0` // passing a string literal to a C function call results in a C string, not a V string - C.sqlite3_open('users.db', &db) + C.sqlite3_open(c'users.db', &db) // C.sqlite3_open(db_path.str, &db) query := 'select count(*) from users' stmt := &C.sqlite3_stmt(0) diff --git a/examples/c_interop_wkhtmltopdf.v b/examples/c_interop_wkhtmltopdf.v index e969f0d01e..5d210e0bcc 100644 --- a/examples/c_interop_wkhtmltopdf.v +++ b/examples/c_interop_wkhtmltopdf.v @@ -62,7 +62,7 @@ fn main() { converter := C.wkhtmltopdf_create_converter(global_settings) println('wkhtmltopdf_create_converter: ${voidptr(converter)}') // convert - mut result := C.wkhtmltopdf_set_object_setting(object_settings, 'page', 'http://www.google.com.br') + mut result := C.wkhtmltopdf_set_object_setting(object_settings, c'page', c'http://www.google.com.br') println('wkhtmltopdf_set_object_setting: $result [page = http://www.google.com.br]') C.wkhtmltopdf_add_object(converter, object_settings, 0) println('wkhtmltopdf_add_object') diff --git a/examples/sokol/fonts.v b/examples/sokol/fonts.v index 8ec0f0893d..1cf21704c0 100644 --- a/examples/sokol/fonts.v +++ b/examples/sokol/fonts.v @@ -48,7 +48,7 @@ fn init(mut state AppState) { // or use DroidSerif-Regular.ttf if bytes := os.read_bytes(os.resource_abs_path('../assets/fonts/RobotoMono-Regular.ttf')) { println('loaded font: $bytes.len') - state.font_normal = C.fonsAddFontMem(state.fons, 'sans', bytes.data, bytes.len, + state.font_normal = C.fonsAddFontMem(state.fons, c'sans', bytes.data, bytes.len, false) } } diff --git a/examples/sokol/freetype_raven.v b/examples/sokol/freetype_raven.v index 8c14881c92..d65b01f411 100644 --- a/examples/sokol/freetype_raven.v +++ b/examples/sokol/freetype_raven.v @@ -101,7 +101,7 @@ fn init(user_data voidptr) { // or use DroidSerif-Regular.ttf if bytes := os.read_bytes(os.resource_abs_path('../assets/fonts/RobotoMono-Regular.ttf')) { println('loaded font: $bytes.len') - state.font_normal = C.fonsAddFontMem(state.fons, 'sans', bytes.data, bytes.len, + state.font_normal = C.fonsAddFontMem(state.fons, c'sans', bytes.data, bytes.len, false) } } diff --git a/vlib/gg/text_rendering.v b/vlib/gg/text_rendering.v index 93871774a5..456e0cfeb4 100644 --- a/vlib/gg/text_rendering.v +++ b/vlib/gg/text_rendering.v @@ -68,13 +68,13 @@ fn new_ft(c FTConfig) ?&FT { return &FT{ fons: fons - font_normal: C.fonsAddFontMem(fons, 'sans', bytes_normal.data, bytes_normal.len, + font_normal: C.fonsAddFontMem(fons, c'sans', bytes_normal.data, bytes_normal.len, false) - font_bold: C.fonsAddFontMem(fons, 'sans', bytes_bold.data, bytes_bold.len, + font_bold: C.fonsAddFontMem(fons, c'sans', bytes_bold.data, bytes_bold.len, false) - font_mono: C.fonsAddFontMem(fons, 'sans', bytes_mono.data, bytes_mono.len, + font_mono: C.fonsAddFontMem(fons, c'sans', bytes_mono.data, bytes_mono.len, false) - font_italic: C.fonsAddFontMem(fons, 'sans', bytes_italic.data, bytes_italic.len, + font_italic: C.fonsAddFontMem(fons, c'sans', bytes_italic.data, bytes_italic.len, false) scale: c.scale } @@ -129,10 +129,10 @@ fn new_ft(c FTConfig) ?&FT { fons := sfons.create(512, 512, 1) return &FT{ fons: fons - font_normal: C.fonsAddFontMem(fons, 'sans', bytes.data, bytes.len, false) - font_bold: C.fonsAddFontMem(fons, 'sans', bytes_bold.data, bytes_bold.len, false) - font_mono: C.fonsAddFontMem(fons, 'sans', bytes_mono.data, bytes_mono.len, false) - font_italic: C.fonsAddFontMem(fons, 'sans', bytes_italic.data, bytes_italic.len, + font_normal: C.fonsAddFontMem(fons, c'sans', bytes.data, bytes.len, false) + font_bold: C.fonsAddFontMem(fons, c'sans', bytes_bold.data, bytes_bold.len, false) + font_mono: C.fonsAddFontMem(fons, c'sans', bytes_mono.data, bytes_mono.len, false) + font_italic: C.fonsAddFontMem(fons, c'sans', bytes_italic.data, bytes_italic.len, false) scale: c.scale } diff --git a/vlib/glm/glm.v b/vlib/glm/glm.v index 5836176458..fd08a61b3d 100644 --- a/vlib/glm/glm.v +++ b/vlib/glm/glm.v @@ -116,7 +116,7 @@ fn (a Vec3) print() { x := a.x y := a.y z := a.z - C.printf('vec3{%f,%f,%f}\n', x, y, z) + C.printf(c'vec3{%f,%f,%f}\n', x, y, z) // println('vec3{$x,$y,$z}') } diff --git a/vlib/net/http/backend_nix.c.v b/vlib/net/http/backend_nix.c.v index 47631e9e1e..1243442a0d 100644 --- a/vlib/net/http/backend_nix.c.v +++ b/vlib/net/http/backend_nix.c.v @@ -16,7 +16,7 @@ fn (req &Request) ssl_do(port int, method Method, host_name string, path string) C.SSL_CTX_set_verify_depth(ctx, 4) flags := C.SSL_OP_NO_SSLv2 | C.SSL_OP_NO_SSLv3 | C.SSL_OP_NO_COMPRESSION C.SSL_CTX_set_options(ctx, flags) - mut res := C.SSL_CTX_load_verify_locations(ctx, 'random-org-chain.pem', 0) + mut res := C.SSL_CTX_load_verify_locations(ctx, c'random-org-chain.pem', 0) web := C.BIO_new_ssl_connect(ctx) addr := host_name + ':' + port.str() res = C.BIO_set_conn_hostname(web, addr.str) diff --git a/vlib/net/openssl/c.v b/vlib/net/openssl/c.v index 06f35fd383..c9e477465e 100644 --- a/vlib/net/openssl/c.v +++ b/vlib/net/openssl/c.v @@ -5,7 +5,7 @@ module openssl // openssl from libssl-dev. If there is no local openssl, // the next flag is harmless, since it will still use the // (older) system openssl. -#flag linux -I/usr/local/include/openssl -L/usr/local/lib +#flag linux -I/usr/local/include/openssl -L/usr/local/lib #flag windows -l libssl -l libcrypto #flag -lssl -lcrypto #flag linux -ldl -lpthread diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index 4c9740422a..dde23e40bd 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -89,6 +89,7 @@ mut: inside_println_arg bool inside_decl_rhs bool need_recheck_generic_fns bool // need recheck generic fns because there are cascaded nested generic fn + is_c_call bool // remove once C.c_call("string") deprecation is removed } pub fn new_checker(table &ast.Table, pref &pref.Preferences) Checker { @@ -2165,6 +2166,11 @@ fn (mut c Checker) array_builtin_method_call(mut call_expr ast.CallExpr, left_ty } pub fn (mut c Checker) fn_call(mut call_expr ast.CallExpr) ast.Type { + was_c_call := c.is_c_call + c.is_c_call = call_expr.language == .c + defer { + c.is_c_call = was_c_call + } fn_name := call_expr.name if fn_name == 'main' { c.error('the `main` function cannot be called in the program', call_expr.pos) @@ -4737,6 +4743,10 @@ pub fn (mut c Checker) expr(node ast.Expr) ast.Type { // string literal starts with "c": `C.printf(c'hello')` return ast.byte_type.set_nr_muls(1) } + if node.language != .c && c.is_c_call { + c.warn("automatic string to C-string conversion is deprecated and will be removed on 2021-06-19, use `c''` and set the C function parameter type to `&u8`", + node.pos) + } return ast.string_type } ast.StringInterLiteral { diff --git a/vlib/v/gen/c/fn.v b/vlib/v/gen/c/fn.v index 3daeb2e313..42c4d02c66 100644 --- a/vlib/v/gen/c/fn.v +++ b/vlib/v/gen/c/fn.v @@ -829,8 +829,8 @@ fn (mut g Gen) fn_call(node ast.CallExpr) { } if node.language == .c { // Skip "C." - g.is_c_call = true name = util.no_dots(name[2..]) + g.is_c_call = true } else { name = c_name(name) } diff --git a/vlib/v/gen/c/str.v b/vlib/v/gen/c/str.v index 59999f6108..0a8b0976e5 100644 --- a/vlib/v/gen/c/str.v +++ b/vlib/v/gen/c/str.v @@ -21,12 +21,6 @@ fn (mut g Gen) string_literal(node ast.StringLiteral) { // `C.printf("hi")` => `printf("hi");` g.write('"$escaped_val"') } else { - // TODO calculate the literal's length in V, it's a bit tricky with all the - // escape characters. - // Clang and GCC optimize `strlen("lorem ipsum")` to `11` - // g.write('tos4("$escaped_val", strlen("$escaped_val"))') - // g.write('tos4("$escaped_val", $it.val.len)') - // g.write('_SLIT("$escaped_val")') g.write('_SLIT("$escaped_val")') } } diff --git a/vlib/v/tests/cstrings_test.v b/vlib/v/tests/cstrings_test.v index c14a7a2d14..6cc9121ebf 100644 --- a/vlib/v/tests/cstrings_test.v +++ b/vlib/v/tests/cstrings_test.v @@ -1,10 +1,8 @@ fn test_cstring() { w := &char(c'world') hlen := unsafe { C.strlen(c'hello') } - hlen2 := unsafe { C.strlen('hello') } wlen := unsafe { C.strlen(w) } assert hlen == 5 - assert hlen2 == 5 assert wlen == 5 } diff --git a/vlib/v/util/quote.v b/vlib/v/util/quote.v index 1148040a3f..a05dadcb2c 100644 --- a/vlib/v/util/quote.v +++ b/vlib/v/util/quote.v @@ -12,7 +12,7 @@ pub fn smart_quote(str string, raw bool) string { if len == 0 { return str } - mut result := strings.new_builder(0) + mut result := strings.new_builder(len) mut pos := -1 mut last := '' // TODO: This should be a single char?