[perl-Glib-Object-Introspection/ppc64-fixes] Correctly detect too few args given to constructors



commit 11b3ac4f30eb5bf4f5d995ea124d45c06823e456
Author: Torsten Schönfeld <kaffeetisch gmx de>
Date:   Tue Sep 16 19:54:52 2014 +0200

    Correctly detect too few args given to constructors
    
    When calling a C constructor that does not expect any arguments, the Perl
    wrapper expects only the class name as an argument, following the usual
    "Package->new" convention.  Incorrectly using "Package::new" instead previously
    resulted in a confusing error message due to an unsigned integer overflow.

 GObjectIntrospection.xs |    1 +
 gperl-i11n-invoke-c.c   |   28 +++++++++++++---------------
 t/arg-checks.t          |    6 +++++-
 3 files changed, 19 insertions(+), 16 deletions(-)
---
diff --git a/GObjectIntrospection.xs b/GObjectIntrospection.xs
index 2f72c2b..afcc98a 100644
--- a/GObjectIntrospection.xs
+++ b/GObjectIntrospection.xs
@@ -146,6 +146,7 @@ typedef struct {
        GIArgument * out_args;
        gboolean * is_automatic_arg;
 
+       guint constructor_offset;
        guint method_offset;
        guint stack_offset;
        gint dynamic_stack_offset;
diff --git a/gperl-i11n-invoke-c.c b/gperl-i11n-invoke-c.c
index 3ace75c..38f7a3e 100644
--- a/gperl-i11n-invoke-c.c
+++ b/gperl-i11n-invoke-c.c
@@ -71,9 +71,10 @@ invoke_c_code (GICallableInfo *info,
                is_skipped = g_arg_info_is_skip (arg_info);
 #endif
                perl_stack_pos = i
-                               + iinfo.method_offset
-                               + iinfo.stack_offset
-                               + iinfo.dynamic_stack_offset;
+                              + iinfo.constructor_offset
+                              + iinfo.method_offset
+                              + iinfo.stack_offset
+                              + iinfo.dynamic_stack_offset;
                ffi_stack_pos = i
                              + iinfo.method_offset;
 
@@ -310,21 +311,14 @@ _prepare_c_invocation_info (GPerlI11nCInvocationInfo *iinfo,
        iinfo->target_function = function;
 
        iinfo->stack_offset = internal_stack_offset;
+       iinfo->n_given_args = items - iinfo->stack_offset;
+       iinfo->n_invoke_args = iinfo->base.n_args;
 
        iinfo->is_constructor = FALSE;
        if (iinfo->base.is_function) {
                iinfo->is_constructor =
                        g_function_info_get_flags (info) & GI_FUNCTION_IS_CONSTRUCTOR;
        }
-       if (iinfo->is_constructor) {
-               /* If we call a constructor, we skip the initial package name
-                * resulting from the "Package->new" syntax. */
-               iinfo->stack_offset++;
-       }
-
-       iinfo->n_given_args = items - iinfo->stack_offset;
-
-       iinfo->n_invoke_args = iinfo->base.n_args;
 
        /* FIXME: can a vfunc not throw? */
        iinfo->throws = FALSE;
@@ -370,6 +364,10 @@ _prepare_c_invocation_info (GPerlI11nCInvocationInfo *iinfo,
                iinfo->is_automatic_arg = gperl_alloc_temp (sizeof (gboolean) * n);
        }
 
+       /* If we call a constructor, we skip the initial package name resulting
+        * from the "Package->new" syntax.  If we call a method, we handle the
+        * invocant separately. */
+       iinfo->constructor_offset = iinfo->is_constructor ? 1 : 0;
        iinfo->method_offset = iinfo->is_method ? 1 : 0;
        iinfo->dynamic_stack_offset = 0;
 
@@ -403,7 +401,7 @@ _prepare_c_invocation_info (GPerlI11nCInvocationInfo *iinfo,
        }
 
        /* Make another pass to count the expected args. */
-       iinfo->n_expected_args = iinfo->method_offset;
+       iinfo->n_expected_args = iinfo->constructor_offset + iinfo->method_offset;
        iinfo->n_nullable_args = 0;
        for (i = 0 ; i < iinfo->base.n_args ; i++) {
                GIArgInfo * arg_info = iinfo->base.arg_infos[i];
@@ -492,12 +490,12 @@ _check_n_args (GPerlI11nCInvocationInfo *iinfo)
                if (iinfo->n_given_args < (iinfo->n_expected_args - iinfo->n_nullable_args)) {
                        caller = _format_target (iinfo);
                        ccroak ("%s: passed too few parameters "
-                               "(expected %d, got %d)",
+                               "(expected %u, got %u)",
                                caller, iinfo->n_expected_args, iinfo->n_given_args);
                } else if (iinfo->n_given_args > iinfo->n_expected_args) {
                        caller = _format_target (iinfo);
                        cwarn ("*** %s: passed too many parameters "
-                              "(expected %d, got %d); ignoring excess",
+                              "(expected %u, got %u); ignoring excess",
                               caller, iinfo->n_expected_args, iinfo->n_given_args);
                }
                if (caller)
diff --git a/t/arg-checks.t b/t/arg-checks.t
index e9955c9..dcc21cb 100644
--- a/t/arg-checks.t
+++ b/t/arg-checks.t
@@ -5,15 +5,19 @@ BEGIN { require './t/inc/setup.pl' };
 use strict;
 use warnings;
 
-plan tests => 5;
+plan tests => 8;
 
 {
   is (Regress::test_int8 (-127), -127);
+  isa_ok (Regress::TestObj->constructor, 'Regress::TestObj');
 }
 
 {
   is (eval { Regress::test_int8 () }, undef);
   like ($@, qr/too few/);
+
+  is (eval { Regress::TestObj::constructor }, undef);
+  like ($@, qr/too few/);
 }
 
 {


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]