From 0dbbb18171d58482553d1c76e13ff50e56776ac0 Mon Sep 17 00:00:00 2001 From: Daniel Kolesa Date: Fri, 3 Nov 2017 15:30:10 +0100 Subject: [PATCH] eolian: disallow ptr() on things that are already pointer-like This disallows deeply nested pointers, you can only explicitly ptr() on types that are strictly value types. For a few cases where it was necessary to override this behavior, you can use legacy(ptr(x)) as a temporary measure. --- src/lib/ector/cairo/ector_cairo_surface.eo | 2 +- src/lib/elementary/elm_calendar.eo | 2 +- src/lib/elementary/elm_dayselector.eo | 2 +- src/lib/elementary/elm_map.eo | 2 +- src/lib/eolian/database_type.c | 14 +----- src/lib/eolian/database_validate.c | 11 +++++ src/lib/eolian/eo_parser.c | 51 ++++++++++++++-------- src/lib/eolian/eolian_database.h | 1 + 8 files changed, 49 insertions(+), 36 deletions(-) diff --git a/src/lib/ector/cairo/ector_cairo_surface.eo b/src/lib/ector/cairo/ector_cairo_surface.eo index 31f68e400c..7967c4d348 100644 --- a/src/lib/ector/cairo/ector_cairo_surface.eo +++ b/src/lib/ector/cairo/ector_cairo_surface.eo @@ -1,4 +1,4 @@ -type @extern cairo_t: void_ptr; [[cairo_t type]] +struct @extern cairo_t; [[cairo_t type]] class Ector.Cairo.Surface (Efl.Object, Ector.Surface) { diff --git a/src/lib/elementary/elm_calendar.eo b/src/lib/elementary/elm_calendar.eo index d08765d312..2b734b30fe 100644 --- a/src/lib/elementary/elm_calendar.eo +++ b/src/lib/elementary/elm_calendar.eo @@ -169,7 +169,7 @@ class Elm.Calendar (Efl.Ui.Layout, Efl.Ui.Focus.Composition, Elm.Interface.Atspi get { } values { - weekdays: ptr(string); [[Array of seven strings to be used as weekday names. + weekdays: legacy(ptr(string)); [[Array of seven strings to be used as weekday names. Warning: It must have 7 elements, or it will access invalid memory. Warning: The strings must be $null terminated ('@\0').]] } diff --git a/src/lib/elementary/elm_dayselector.eo b/src/lib/elementary/elm_dayselector.eo index 0bc85ad001..c5135da6ea 100644 --- a/src/lib/elementary/elm_dayselector.eo +++ b/src/lib/elementary/elm_dayselector.eo @@ -107,7 +107,7 @@ class Elm.Dayselector (Efl.Ui.Layout) */ params { - @in weekdays: ptr(string) @nullable; [[Array of seven strings to be used as weekday names. + @in weekdays: legacy(ptr(string)) @nullable; [[Array of seven strings to be used as weekday names. Warning: It must have 7 elements, or it will access invalid memory. Warning: The strings must be NULL terminated ('@\0').]] } diff --git a/src/lib/elementary/elm_map.eo b/src/lib/elementary/elm_map.eo index 7f5376ad85..908444da84 100644 --- a/src/lib/elementary/elm_map.eo +++ b/src/lib/elementary/elm_map.eo @@ -431,7 +431,7 @@ class Elm.Map (Elm.Widget, Elm.Interface_Scrollable, At least available sources of name type are "Nominatim". ]] - return: ptr(string); [[The char pointer array of source names.]] + return: legacy(ptr(string)); [[The char pointer array of source names.]] params { @in type: Elm.Map.Source_Type; [[Source type.]] } diff --git a/src/lib/eolian/database_type.c b/src/lib/eolian/database_type.c index 1afbbac14a..c71a45452b 100644 --- a/src/lib/eolian/database_type.c +++ b/src/lib/eolian/database_type.c @@ -67,18 +67,6 @@ database_enum_add(Eolian_Typedecl *tp) database_decl_add(tp->full_name, EOLIAN_DECL_ENUM, tp->base.file, tp); } -static const Eina_Bool _ownable_types[] = { - EINA_FALSE, /* unknown */ - EINA_FALSE, /* void */ - EINA_FALSE, /* regular */ - EINA_TRUE, /* complex */ - EINA_TRUE, /* pointer */ - EINA_TRUE, /* class */ - EINA_TRUE, /* static array */ - EINA_TRUE, /* terminated array */ - EINA_FALSE /* undefined */ -}; - Eina_Bool database_type_is_ownable(const Eolian_Type *tp) { @@ -101,7 +89,7 @@ database_type_is_ownable(const Eolian_Type *tp) } return (ct[strlen(ct) - 1] == '*'); } - return _ownable_types[tp->type]; + return (tp->type == EOLIAN_TYPE_CLASS); } static void diff --git a/src/lib/eolian/database_validate.c b/src/lib/eolian/database_validate.c index ecfb806b0b..3651d7ead2 100644 --- a/src/lib/eolian/database_validate.c +++ b/src/lib/eolian/database_validate.c @@ -172,6 +172,17 @@ _validate_type(Eolian_Type *tp) return _obj_error(&tp->base, buf); } + if (tp->is_ptr && !tp->legacy) + { + tp->is_ptr = EINA_FALSE; + Eina_Bool still_ownable = database_type_is_ownable(tp); + tp->is_ptr = EINA_TRUE; + if (still_ownable) + { + return _obj_error(&tp->base, "cannot take a pointer to pointer type"); + } + } + switch (tp->type) { case EOLIAN_TYPE_VOID: diff --git a/src/lib/eolian/eo_parser.c b/src/lib/eolian/eo_parser.c index 0ec492b9a3..da03709c38 100644 --- a/src/lib/eolian/eo_parser.c +++ b/src/lib/eolian/eo_parser.c @@ -456,14 +456,14 @@ parse_expr(Eo_Lexer *ls) return parse_expr_bin(ls, 1); } -static Eolian_Type *parse_type_void(Eo_Lexer *ls, Eina_Bool allow_ref); +static Eolian_Type *parse_type_void(Eo_Lexer *ls); static Eolian_Type * -parse_type(Eo_Lexer *ls, Eina_Bool allow_ref) +parse_type(Eo_Lexer *ls) { Eolian_Type *ret; eo_lexer_context_push(ls); - ret = parse_type_void(ls, allow_ref); + ret = parse_type_void(ls); if (ret->type == EOLIAN_TYPE_VOID) { eo_lexer_context_restore(ls); @@ -512,7 +512,7 @@ parse_struct(Eo_Lexer *ls, const char *name, Eina_Bool is_extern, def->field_list = eina_list_append(def->field_list, fdef); eo_lexer_get(ls); check_next(ls, ':'); - tp = parse_type(ls, EINA_TRUE); + tp = parse_type(ls); FILL_BASE(fdef->base, ls, fline, fcol); fdef->type = tp; fdef->name = eina_stringshare_ref(fname); @@ -687,7 +687,7 @@ _parse_dep(Eo_Lexer *ls, const char *fname, const char *name) } static Eolian_Type * -parse_type_void(Eo_Lexer *ls, Eina_Bool allow_ref) +parse_type_void(Eo_Lexer *ls) { Eolian_Type *def; Eina_Strbuf *buf; @@ -701,7 +701,7 @@ parse_type_void(Eo_Lexer *ls, Eina_Bool allow_ref) pline = ls->line_number; pcol = ls->column; check_next(ls, '('); - def = parse_type_void(ls, allow_ref); + def = parse_type_void(ls); FILL_BASE(def->base, ls, line, col); def->is_const = EINA_TRUE; check_match(ls, ')', '(', pline, pcol); @@ -714,12 +714,25 @@ parse_type_void(Eo_Lexer *ls, Eina_Bool allow_ref) pline = ls->line_number; pcol = ls->column; check_next(ls, '('); - def = parse_type_void(ls, EINA_FALSE); + def = parse_type_void(ls); FILL_BASE(def->base, ls, line, col); def->is_ptr = EINA_TRUE; check_match(ls, ')', '(', pline, pcol); return def; } + case KW_legacy: + { + int pline, pcol; + eo_lexer_get(ls); + pline = ls->line_number; + pcol = ls->column; + check_next(ls, '('); + def = parse_type_void(ls); + FILL_BASE(def->base, ls, line, col); + def->legacy = EINA_TRUE; + check_match(ls, ')', '(', pline, pcol); + return def; + } case KW_free: { int pline, pcolumn; @@ -727,7 +740,7 @@ parse_type_void(Eo_Lexer *ls, Eina_Bool allow_ref) pline = ls->line_number; pcolumn = ls->column; check_next(ls, '('); - def = parse_type_void(ls, allow_ref); + def = parse_type_void(ls); check_next(ls, ','); check(ls, TOK_VALUE); def->freefunc = eina_stringshare_ref(ls->t.value.s); @@ -768,23 +781,23 @@ parse_type_void(Eo_Lexer *ls, Eina_Bool allow_ref) int bline = ls->line_number, bcol = ls->column; check_next(ls, '<'); if (tpid == KW_future) - def->base_type = parse_type_void(ls, EINA_FALSE); + def->base_type = parse_type_void(ls); else - def->base_type = parse_type(ls, EINA_FALSE); + def->base_type = parse_type(ls); pop_type(ls); if ((def->base_type->owned = (ls->t.kw == KW_at_owned))) eo_lexer_get(ls); if (tpid == KW_hash) { check_next(ls, ','); - def->base_type->next_type = parse_type(ls, EINA_FALSE); + def->base_type->next_type = parse_type(ls); pop_type(ls); if ((def->base_type->next_type->owned = (ls->t.kw == KW_at_owned))) eo_lexer_get(ls); } else if((tpid == KW_future) && test_next(ls, ',')) { - def->base_type->next_type = parse_type_void(ls, EINA_FALSE); + def->base_type->next_type = parse_type_void(ls); pop_type(ls); } check_match(ls, '>', '<', bline, bcol); @@ -854,7 +867,7 @@ parse_typedef(Eo_Lexer *ls) } eo_lexer_context_pop(ls); check_next(ls, ':'); - def->base_type = parse_type(ls, EINA_FALSE); + def->base_type = parse_type(ls); pop_type(ls); check_next(ls, ';'); FILL_DOC(ls, def, doc); @@ -890,7 +903,7 @@ parse_variable(Eo_Lexer *ls, Eina_Bool global) } eo_lexer_context_pop(ls); check_next(ls, ':'); - def->base_type = parse_type(ls, EINA_FALSE); + def->base_type = parse_type(ls); pop_type(ls); /* constants are required to have a value */ if (!global) @@ -926,9 +939,9 @@ parse_return(Eo_Lexer *ls, Eo_Ret_Def *ret, Eina_Bool allow_void, eo_lexer_get(ls); check_next(ls, ':'); if (allow_void) - ret->type = parse_type_void(ls, EINA_TRUE); + ret->type = parse_type_void(ls); else - ret->type = parse_type(ls, EINA_TRUE); + ret->type = parse_type(ls); ret->doc = NULL; ret->default_ret_val = NULL; ret->warn_unused = EINA_FALSE; @@ -995,9 +1008,9 @@ parse_param(Eo_Lexer *ls, Eina_List **params, Eina_Bool allow_inout, eo_lexer_get(ls); check_next(ls, ':'); if (par->param_dir == EOLIAN_OUT_PARAM || par->param_dir == EOLIAN_INOUT_PARAM) - par->type = parse_type_void(ls, EINA_TRUE); + par->type = parse_type_void(ls); else - par->type = parse_type(ls, EINA_TRUE); + par->type = parse_type(ls); pop_type(ls); if ((is_vals || (par->param_dir == EOLIAN_OUT_PARAM)) && (ls->t.token == '(')) { @@ -1801,7 +1814,7 @@ end: if (ls->t.token == ':') { eo_lexer_get(ls); - ev->type = parse_type(ls, EINA_TRUE); + ev->type = parse_type(ls); ev->type->owned = has_owned; pop_type(ls); } diff --git a/src/lib/eolian/eolian_database.h b/src/lib/eolian/eolian_database.h index 05c153b8f2..a8c1dbb637 100644 --- a/src/lib/eolian/eolian_database.h +++ b/src/lib/eolian/eolian_database.h @@ -177,6 +177,7 @@ struct _Eolian_Type Eina_Bool is_const :1; Eina_Bool is_ptr :1; Eina_Bool owned :1; + Eina_Bool legacy :1; }; struct _Eolian_Typedecl