eolian: stricter checks for const() validity
authorDaniel Kolesa <d.kolesa@samsung.com>
Thu, 26 Sep 2019 13:58:17 +0000 (15:58 +0200)
committerJongmin Lee <jm105.lee@samsung.com>
Thu, 26 Sep 2019 21:39:04 +0000 (06:39 +0900)
src/lib/ecore/efl_loop.eo
src/lib/eolian/database_expr.c
src/lib/eolian/database_type.c
src/lib/eolian/database_validate.c
src/lib/eolian/eo_parser.c
src/lib/eolian/eolian_database.h

index 0f17c31..4f800a6 100644 (file)
@@ -3,7 +3,7 @@ struct Efl.Loop_Arguments {
 
      @since 1.22
    ]]
-   argv: const(array<const(stringshare)>); [[Array with loop arguments]]
+   argv: const(array<stringshare>); [[Array with loop arguments]]
    initialization: bool; [[Set to $true when the program should initialize its internal state.
                            This happens once per process instance.]]
 }
index 978f281..38794a2 100644 (file)
@@ -613,7 +613,7 @@ database_expr_eval_type(const Eolian_Unit *unit, Eolian_Expression *expr,
           return database_expr_eval(unit, expr, EOLIAN_MASK_NULL, cb, data);
         case EOLIAN_TYPE_REGULAR:
           {
-              if (database_type_is_ownable(unit, type, EINA_FALSE))
+              if (database_type_is_ownable(unit, type, EINA_FALSE, NULL))
                  return database_expr_eval(unit, expr, EOLIAN_MASK_NULL, cb, data);
               int  kw = eo_lexer_keyword_str_to_id(type->base.name);
               if (!kw || kw < KW_byte || kw >= KW_void)
index 52973fb..53d531c 100644 (file)
@@ -63,8 +63,9 @@ database_enum_add(Eolian_Unit *unit, Eolian_Typedecl *tp)
 }
 
 Eina_Bool
-database_type_is_ownable(const Eolian_Unit *unit, const Eolian_Type *tp, Eina_Bool allow_void)
+database_type_is_ownable(const Eolian_Unit *unit, const Eolian_Type *tp, Eina_Bool allow_void, const Eolian_Type **otp)
 {
+   if (otp) *otp = tp;
    if (tp->is_ptr)
      return EINA_TRUE;
    if (tp->type == EOLIAN_TYPE_REGULAR)
@@ -79,7 +80,7 @@ database_type_is_ownable(const Eolian_Unit *unit, const Eolian_Type *tp, Eina_Bo
              if (tpp->type == EOLIAN_TYPEDECL_FUNCTION_POINTER)
                return EINA_TRUE;
              if (tpp->type == EOLIAN_TYPEDECL_ALIAS)
-               return database_type_is_ownable(unit, tpp->base_type, allow_void);
+               return database_type_is_ownable(unit, tpp->base_type, allow_void, otp);
              return EINA_FALSE;
           }
         return (ct[strlen(ct) - 1] == '*');
@@ -107,7 +108,7 @@ database_type_to_str(const Eolian_Type *tp,
      || tp->type == EOLIAN_TYPE_CLASS
      || tp->type == EOLIAN_TYPE_VOID)
      && tp->is_const
-     && ((ctype != EOLIAN_C_TYPE_RETURN) || by_ref || database_type_is_ownable(NULL, tp, EINA_FALSE)))
+     && ((ctype != EOLIAN_C_TYPE_RETURN) || by_ref || database_type_is_ownable(NULL, tp, EINA_FALSE, NULL)))
      {
         eina_strbuf_append(buf, "const ");
      }
index 87d51ac..b80d418 100644 (file)
@@ -103,9 +103,11 @@ _validate_doc(Eolian_Documentation *doc)
    return _validate(&doc->base);
 }
 
-static Eina_Bool _validate_type(Validate_State *vals, Eolian_Type *tp);
+static Eina_Bool _validate_type(Validate_State *vals, Eolian_Type *tp,
+                                Eina_Bool by_ref, Eina_Bool is_ret);
 static Eina_Bool _validate_type_by_ref(Validate_State *vals, Eolian_Type *tp,
-                                       Eina_Bool by_ref, Eina_Bool move);
+                                       Eina_Bool by_ref, Eina_Bool move,
+                                       Eina_Bool is_ret);
 static Eina_Bool _validate_expr(Eolian_Expression *expr,
                                 const Eolian_Type *tp,
                                 Eolian_Expression_Mask msk,
@@ -124,7 +126,8 @@ static Eina_Bool
 _sf_map_cb(const Eina_Hash *hash EINA_UNUSED, const void *key EINA_UNUSED,
            const Eolian_Struct_Type_Field *sf, Cb_Ret *sc)
 {
-   sc->succ = _validate_type_by_ref(sc->vals, sf->type, sf->by_ref, sf->move);
+   sc->succ = _validate_type_by_ref(sc->vals, sf->type, sf->by_ref,
+                                    sf->move, EINA_FALSE);
 
    if (!sc->succ)
      return EINA_FALSE;
@@ -166,7 +169,7 @@ _validate_typedecl(Validate_State *vals, Eolian_Typedecl *tp)
    switch (tp->type)
      {
       case EOLIAN_TYPEDECL_ALIAS:
-        if (!_validate_type(vals, tp->base_type))
+        if (!_validate_type(vals, tp->base_type, EINA_FALSE, EINA_FALSE))
           return _reset_stable(vals, was_stable, EINA_FALSE);
         if (tp->base_type->ownable)
           tp->ownable = EINA_TRUE;
@@ -215,7 +218,7 @@ static Eina_Bool
 _validate_by_ref(Eolian_Type *tp, Eina_Bool by_ref, Eina_Bool move)
 {
    Eina_Bool maybe_ownable =
-     database_type_is_ownable(tp->base.unit, tp, EINA_FALSE);
+     database_type_is_ownable(tp->base.unit, tp, EINA_FALSE, NULL);
 
    /* only allow value types when @by_ref */
    if (by_ref && maybe_ownable)
@@ -244,16 +247,17 @@ _validate_by_ref(Eolian_Type *tp, Eina_Bool by_ref, Eina_Bool move)
 
 static Eina_Bool
 _validate_type_by_ref(Validate_State *vals, Eolian_Type *tp,
-                      Eina_Bool by_ref, Eina_Bool move)
+                      Eina_Bool by_ref, Eina_Bool move, Eina_Bool is_ret)
 {
-   if (!_validate_type(vals, tp))
+   if (!_validate_type(vals, tp, by_ref, is_ret))
      return EINA_FALSE;
 
    return _validate_by_ref(tp, by_ref, move);
 }
 
 static Eina_Bool
-_validate_type(Validate_State *vals, Eolian_Type *tp)
+_validate_type(Validate_State *vals, Eolian_Type *tp, Eina_Bool by_ref,
+               Eina_Bool is_ret)
 {
    const Eolian_Unit *src = tp->base.unit;
 
@@ -265,7 +269,7 @@ _validate_type(Validate_State *vals, Eolian_Type *tp)
              return EINA_FALSE;
           }
         tp->is_ptr = EINA_FALSE;
-        Eina_Bool still_ownable = database_type_is_ownable(src, tp, EINA_FALSE);
+        Eina_Bool still_ownable = database_type_is_ownable(src, tp, EINA_FALSE, NULL);
         tp->is_ptr = EINA_TRUE;
         if (still_ownable)
           {
@@ -274,6 +278,38 @@ _validate_type(Validate_State *vals, Eolian_Type *tp)
           }
      }
 
+   if (tp->is_const && !tp->is_ptr)
+     {
+        if (database_type_is_ownable(src, tp, EINA_FALSE, NULL))
+          {
+             int kw = eo_lexer_keyword_str_to_id(tp->base.name);
+             switch (kw)
+               {
+                case KW_string:
+                case KW_mstring:
+                case KW_stringshare:
+                  _eo_parser_log(&tp->base, "string types cannot be const");
+                  return EINA_FALSE;
+                default:
+                  {
+                     if (!is_ret)
+                       break;
+                     const char *ct = eo_lexer_get_c_type(kw);
+                     if (ct && ct[strlen(ct) - 1] != '*')
+                       {
+                          _eo_parser_log(&tp->base, "return const requires a C pointer");
+                          return EINA_FALSE;
+                       }
+                  }
+               }
+            }
+        else if (!by_ref && is_ret)
+          {
+             _eo_parser_log(&tp->base, "value returns cannot be const");
+             return EINA_FALSE;
+          }
+     }
+
    switch (tp->type)
      {
       case EOLIAN_TYPE_VOID:
@@ -309,7 +345,7 @@ _validate_type(Validate_State *vals, Eolian_Type *tp)
                                          tp->base.name);
                           return EINA_FALSE;
                        }
-                     if (!_validate_type_by_ref(vals, itp, EINA_FALSE, itp->move))
+                     if (!_validate_type_by_ref(vals, itp, EINA_FALSE, itp->move, EINA_FALSE))
                        return EINA_FALSE;
                      itp = itp->next_type;
                   }
@@ -398,7 +434,7 @@ _validate_type(Validate_State *vals, Eolian_Type *tp)
                 return EINA_FALSE;
              }
            tp->base.c_name = eina_stringshare_ref(tp->error->base.c_name);
-           if (tp->next_type && !_validate_type(vals, tp->next_type))
+           if (tp->next_type && !_validate_type(vals, tp->next_type, EINA_FALSE, EINA_FALSE))
              return EINA_FALSE;
            return _validate(&tp->base);
         }
@@ -429,7 +465,7 @@ _validate_expr(Eolian_Expression *expr, const Eolian_Type *tp,
 static Eina_Bool
 _validate_param(Validate_State *vals, Eolian_Function_Parameter *param)
 {
-   if (!_validate_type_by_ref(vals, param->type, param->by_ref, param->move))
+   if (!_validate_type_by_ref(vals, param->type, param->by_ref, param->move, EINA_FALSE))
      return EINA_FALSE;
 
    if (param->value && !_validate_expr(param->value, param->type, 0, param->by_ref))
@@ -472,11 +508,11 @@ _validate_function(Validate_State *vals, Eolian_Function *func, Eina_Hash *nhash
    Eina_Bool was_stable = _set_stable(vals, !func->base.is_beta && vals->stable);
 
    if (func->get_ret_type && !_validate_type_by_ref(vals, func->get_ret_type,
-       func->get_return_by_ref, func->get_return_move))
+       func->get_return_by_ref, func->get_return_move, EINA_TRUE))
      return _reset_stable(vals, was_stable, EINA_FALSE);
 
    if (func->set_ret_type && !_validate_type_by_ref(vals, func->set_ret_type,
-       func->set_return_by_ref, func->set_return_move))
+       func->set_return_by_ref, func->set_return_move, EINA_TRUE))
      return _reset_stable(vals, was_stable, EINA_FALSE);
 
    if (func->get_ret_val && !_validate_expr(func->get_ret_val,
@@ -587,7 +623,7 @@ _validate_event(Validate_State *vals, Eolian_Event *event, Eina_Hash *nhash)
 
    Eina_Bool was_stable = _set_stable(vals, !event->base.is_beta && vals->stable);
 
-   if (!_validate_type(vals, event->type))
+   if (!_validate_type(vals, event->type, EINA_FALSE, EINA_FALSE))
      return _reset_stable(vals, was_stable, EINA_FALSE);
 
    /* if this is an alias we need the lowest type in the stack, this is
@@ -612,7 +648,7 @@ _validate_event(Validate_State *vals, Eolian_Event *event, Eina_Hash *nhash)
          * this is FIXME, and decision wasn't reached before 1.22
          * it is a simple search-replace anyway
          */
-        if (database_type_is_ownable(tp->base.unit, tp, EINA_FALSE))
+        if (database_type_is_ownable(tp->base.unit, tp, EINA_FALSE, NULL))
           {
              switch (kwid)
                {
@@ -1495,7 +1531,7 @@ _validate_constant(Validate_State *vals, Eolian_Constant *var)
 
    Eina_Bool was_stable = _set_stable(vals, !var->base.is_beta && vals->stable);
 
-   if (!_validate_type(vals, var->base_type))
+   if (!_validate_type(vals, var->base_type, EINA_FALSE, EINA_FALSE))
      return _reset_stable(vals, was_stable, EINA_FALSE);
 
    if (!_validate_expr(var->value, var->base_type, 0, EINA_FALSE))
index d30d285..72f5ad2 100644 (file)
@@ -436,14 +436,14 @@ parse_expr(Eo_Lexer *ls)
    return parse_expr_bin(ls, 1);
 }
 
-static Eolian_Type *parse_type_void(Eo_Lexer *ls, Eina_Bool allow_ptr);
+static Eolian_Type *parse_type_void(Eo_Lexer *ls, Eina_Bool allow_ptr, Eina_Bool allow_const);
 
 static Eolian_Type *
-parse_type(Eo_Lexer *ls, Eina_Bool allow_ptr)
+parse_type(Eo_Lexer *ls, Eina_Bool allow_ptr, Eina_Bool allow_const)
 {
    Eolian_Type *ret;
    eo_lexer_context_push(ls);
-   ret = parse_type_void(ls, allow_ptr);
+   ret = parse_type_void(ls, allow_ptr, allow_const);
    if (ret->type == EOLIAN_TYPE_VOID)
      {
         eo_lexer_context_restore(ls);
@@ -513,7 +513,7 @@ parse_struct(Eo_Lexer *ls, const char *name, Eina_Bool is_extern,
         eolian_object_ref(&fdef->base);
         eo_lexer_get(ls);
         check_next(ls, ':');
-        tp = parse_type(ls, EINA_TRUE);
+        tp = parse_type(ls, EINA_TRUE, EINA_TRUE);
         FILL_BASE(fdef->base, ls, fline, fcol, STRUCT_FIELD);
         fdef->type = eo_lexer_type_release(ls, tp);
         fdef->base.name = eina_stringshare_ref(fname);
@@ -689,7 +689,7 @@ parse_type_error(Eo_Lexer *ls)
 }
 
 static Eolian_Type *
-parse_type_void(Eo_Lexer *ls, Eina_Bool allow_ptr)
+parse_type_void(Eo_Lexer *ls, Eina_Bool allow_ptr, Eina_Bool allow_const)
 {
    Eolian_Type *def;
    Eina_Strbuf *buf;
@@ -698,12 +698,14 @@ parse_type_void(Eo_Lexer *ls, Eina_Bool allow_ptr)
      {
       case KW_const:
         {
+           if (!allow_const)
+             break;
            int pline, pcol;
            eo_lexer_get(ls);
            pline = ls->line_number;
            pcol = ls->column;
            check_next(ls, '(');
-           def = parse_type_void(ls, allow_ptr);
+           def = parse_type_void(ls, allow_ptr, EINA_FALSE);
            FILL_BASE(def->base, ls, line, col, TYPE);
            def->is_const = EINA_TRUE;
            check_match(ls, ')', '(', pline, pcol);
@@ -718,7 +720,7 @@ parse_type_void(Eo_Lexer *ls, Eina_Bool allow_ptr)
            pline = ls->line_number;
            pcol = ls->column;
            check_next(ls, '(');
-           def = parse_type_void(ls, EINA_FALSE);
+           def = parse_type_void(ls, EINA_FALSE, allow_const);
            FILL_BASE(def->base, ls, line, col, TYPE);
            def->is_ptr = EINA_TRUE;
            check_match(ls, ')', '(', pline, pcol);
@@ -768,9 +770,9 @@ parse_type_void(Eo_Lexer *ls, Eina_Bool allow_ptr)
                   int bline = ls->line_number, bcol = ls->column;
                   check_next(ls, '<');
                   if (tpid == KW_future)
-                    def->base_type = eo_lexer_type_release(ls, parse_type_void(ls, EINA_TRUE));
+                    def->base_type = eo_lexer_type_release(ls, parse_type_void(ls, EINA_TRUE, EINA_TRUE));
                   else
-                    def->base_type = eo_lexer_type_release(ls, parse_type(ls, EINA_TRUE));
+                    def->base_type = eo_lexer_type_release(ls, parse_type(ls, EINA_TRUE, EINA_TRUE));
                   /* view-only types are not allowed to own the contents */
                   if (tpid == KW_array || tpid == KW_hash || tpid == KW_list || tpid == KW_future)
                     if ((def->base_type->move = ls->t.kw == KW_at_move))
@@ -779,7 +781,7 @@ parse_type_void(Eo_Lexer *ls, Eina_Bool allow_ptr)
                     {
                        check_next(ls, ',');
                        def->base_type->next_type =
-                         eo_lexer_type_release(ls, parse_type(ls, EINA_TRUE));
+                         eo_lexer_type_release(ls, parse_type(ls, EINA_TRUE, EINA_TRUE));
                        if ((def->base_type->next_type->move = ls->t.kw == KW_at_move))
                          eo_lexer_get(ls);
                     }
@@ -872,7 +874,7 @@ tags_done:
      }
    eo_lexer_context_pop(ls);
    check_next(ls, ':');
-   def->base_type = eo_lexer_type_release(ls, parse_type(ls, EINA_FALSE));
+   def->base_type = eo_lexer_type_release(ls, parse_type(ls, EINA_FALSE, EINA_FALSE));
    check_next(ls, ';');
    FILL_DOC(ls, def, doc);
    eo_lexer_dtor_pop(ls);
@@ -929,7 +931,7 @@ tags_done:
      }
    eo_lexer_context_pop(ls);
    check_next(ls, ':');
-   def->base_type = eo_lexer_type_release(ls, parse_type(ls, EINA_TRUE));
+   def->base_type = eo_lexer_type_release(ls, parse_type(ls, EINA_FALSE, EINA_FALSE));
    /* constants are required to have a value */
    check(ls, '=');
    ls->expr_mode = EINA_TRUE;
@@ -1025,9 +1027,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, EINA_TRUE, EINA_TRUE);
    else
-     ret->type = parse_type(ls, EINA_TRUE);
+     ret->type = parse_type(ls, EINA_TRUE, EINA_TRUE);
    ret->doc = NULL;
    ret->default_ret_val = NULL;
    ret->no_unused = EINA_FALSE;
@@ -1106,11 +1108,11 @@ parse_param(Eo_Lexer *ls, Eina_List **params, Eina_Bool allow_inout,
        if (par->param_dir == EOLIAN_OUT_PARAM || par->param_dir == EOLIAN_INOUT_PARAM)
          {
             /* void is allowed for out/inout for beta-api for now to make a voidptr */
-            par->type = eo_lexer_type_release(ls, parse_type_void(ls, EINA_TRUE));
+            par->type = eo_lexer_type_release(ls, parse_type_void(ls, EINA_TRUE, EINA_TRUE));
             goto type_done;
          }
      }
-   par->type = eo_lexer_type_release(ls, parse_type(ls, EINA_TRUE));
+   par->type = eo_lexer_type_release(ls, parse_type(ls, EINA_TRUE, EINA_TRUE));
 type_done:
    if ((is_vals || (par->param_dir == EOLIAN_OUT_PARAM)) && (ls->t.token == '('))
      {
@@ -1906,7 +1908,7 @@ parse_event(Eo_Lexer *ls)
      }
 end:
    check_next(ls, ':');
-   ev->type = eo_lexer_type_release(ls, parse_type_void(ls, EINA_TRUE));
+   ev->type = eo_lexer_type_release(ls, parse_type_void(ls, EINA_TRUE, EINA_TRUE));
    check(ls, ';');
    eo_lexer_get(ls);
    FILL_DOC(ls, ev, doc);
index ffe8067..895a7ff 100644 (file)
@@ -432,7 +432,7 @@ void database_typedecl_to_str(const Eolian_Typedecl *tp, Eina_Strbuf *buf);
 
 Eolian_Typedecl *database_type_decl_find(const Eolian_Unit *src, const Eolian_Type *tp);
 
-Eina_Bool database_type_is_ownable(const Eolian_Unit *unit, const Eolian_Type *tp, Eina_Bool allow_void);
+Eina_Bool database_type_is_ownable(const Eolian_Unit *unit, const Eolian_Type *tp, Eina_Bool allow_void, const Eolian_Type **otp);
 
 /* expressions */