summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorColin Walters <walters@verbum.org>2012-11-06 11:48:36 -0500
committerColin Walters <walters@verbum.org>2012-11-12 11:43:09 -0500
commitac7376e0b2671ac6cb12c69b0289e029a3c2302b (patch)
treedde072db0d69568ab9d027b35599ff28fcaaa20f
parent75148f33bbff9eed6164c0c02c584916fd127396 (diff)
downloadgobject-introspection-ac7376e0b2671ac6cb12c69b0289e029a3c2302b.tar.gz
scanner: Correctly handle large 64 bit integer constants
In C, positive integer constants are by default unsigned. This means an expression like 0x8000000000000000 will be "unsigned long long". In the actual scanner code, we were parsing them as "gint64", and storing them as gint64. This was incorrect; we need to parse them as guint64, and store the bits we get from that. This gives us an equivalent result to what the C compiler does. However, when we actually return the value as a Python "long" (arbitrary length integer), we need to treat the value as unsigned if the result indicated it was. https://bugzilla.gnome.org/show_bug.cgi?id=685022 Conflicts: tests/scanner/Regress-1.0-expected.gir tests/scanner/regress.h
-rw-r--r--giscanner/giscannermodule.c5
-rw-r--r--giscanner/scannerparser.y14
-rw-r--r--giscanner/sourcescanner.h1
-rw-r--r--tests/scanner/Regress-1.0-expected.gir15
-rw-r--r--tests/scanner/regress.h5
5 files changed, 34 insertions, 6 deletions
diff --git a/giscanner/giscannermodule.c b/giscanner/giscannermodule.c
index 0da20f18..4a854413 100644
--- a/giscanner/giscannermodule.c
+++ b/giscanner/giscannermodule.c
@@ -162,7 +162,10 @@ symbol_get_const_int (PyGISourceSymbol *self,
return Py_None;
}
- return PyLong_FromLongLong ((long long)self->symbol->const_int);
+ if (self->symbol->const_int_is_unsigned)
+ return PyLong_FromUnsignedLongLong ((unsigned long long)self->symbol->const_int);
+ else
+ return PyLong_FromLongLong ((long long)self->symbol->const_int);
}
static PyObject *
diff --git a/giscanner/scannerparser.y b/giscanner/scannerparser.y
index 06a10efa..cc495cc3 100644
--- a/giscanner/scannerparser.y
+++ b/giscanner/scannerparser.y
@@ -1,4 +1,4 @@
-/* GObject introspection: C parser
+/* GObject introspection: C parser -*- indent-tabs-mode: t; tab-width: 8 -*-
*
* Copyright (c) 1997 Sandro Sigala <ssigala@globalnet.it>
* Copyright (c) 2007-2008 Jürg Billeter <j@bitron.ch>
@@ -232,15 +232,19 @@ primary_expression
}
| INTEGER
{
+ char *rest;
+ guint64 value;
$$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST, scanner->current_filename, lineno);
$$->const_int_set = TRUE;
if (g_str_has_prefix (yytext, "0x") && strlen (yytext) > 2) {
- $$->const_int = g_ascii_strtoll (yytext + 2, NULL, 16);
+ value = g_ascii_strtoull (yytext + 2, &rest, 16);
} else if (g_str_has_prefix (yytext, "0") && strlen (yytext) > 1) {
- $$->const_int = g_ascii_strtoll (yytext + 1, NULL, 8);
+ value = g_ascii_strtoull (yytext + 1, &rest, 8);
} else {
- $$->const_int = g_ascii_strtoll (yytext, NULL, 10);
+ value = g_ascii_strtoull (yytext, &rest, 10);
}
+ $$->const_int = value;
+ $$->const_int_is_unsigned = (rest && (rest[0] == 'U'));
}
| CHARACTER
{
@@ -382,7 +386,7 @@ unary_expression
{
$$ = $3;
if ($$->const_int_set) {
- $$->base_type = gi_source_basic_type_new ("gint64");
+ $$->base_type = gi_source_basic_type_new ($$->const_int_is_unsigned ? "guint64" : "gint64");
}
}
| INTUL_CONST '(' unary_expression ')'
diff --git a/giscanner/sourcescanner.h b/giscanner/sourcescanner.h
index df16cf6a..a2834caf 100644
--- a/giscanner/sourcescanner.h
+++ b/giscanner/sourcescanner.h
@@ -126,6 +126,7 @@ struct _GISourceSymbol
gboolean const_int_set;
gboolean private;
gint64 const_int; /* 64-bit we can handle signed and unsigned 32-bit values */
+ gboolean const_int_is_unsigned;
char *const_string;
gboolean const_double_set;
double const_double;
diff --git a/tests/scanner/Regress-1.0-expected.gir b/tests/scanner/Regress-1.0-expected.gir
index 8d123f7a..1adc5caf 100644
--- a/tests/scanner/Regress-1.0-expected.gir
+++ b/tests/scanner/Regress-1.0-expected.gir
@@ -87,11 +87,26 @@ and/or use gtk-doc annotations. -->
<type name="gdouble" c:type="double"/>
</field>
</record>
+ <constant name="MAXUINT64"
+ value="18446744073709551615"
+ c:type="REGRESS_MAXUINT64">
+ <type name="guint64" c:type="guint64"/>
+ </constant>
+ <constant name="MININT64"
+ value="-9223372036854775808"
+ c:type="REGRESS_MININT64">
+ <type name="gint64" c:type="gint64"/>
+ </constant>
<constant name="Mixed_Case_Constant"
value="4423"
c:type="REGRESS_Mixed_Case_Constant">
<type name="gint" c:type="gint"/>
</constant>
+ <constant name="NEGATIVE_INT_CONSTANT"
+ value="-42"
+ c:type="REGRESS_NEGATIVE_INT_CONSTANT">
+ <type name="gint" c:type="gint"/>
+ </constant>
<constant name="STRING_CONSTANT"
value="Some String"
c:type="REGRESS_STRING_CONSTANT">
diff --git a/tests/scanner/regress.h b/tests/scanner/regress.h
index 635ea7bd..e1024b04 100644
--- a/tests/scanner/regress.h
+++ b/tests/scanner/regress.h
@@ -255,6 +255,7 @@ GQuark regress_atest_error_quark (void);
/* constants */
+#define REGRESS_NEGATIVE_INT_CONSTANT -42
#define REGRESS_INT_CONSTANT 4422
#define REGRESS_DOUBLE_CONSTANT 44.22
#define REGRESS_STRING_CONSTANT "Some String"
@@ -899,4 +900,8 @@ typedef struct {
double dummy2;
} RegressLikeGnomeKeyringPasswordSchema;
+/* https://bugzilla.gnome.org/show_bug.cgi?id=685022 */
+#define REGRESS_MININT64 ((gint64) G_GINT64_CONSTANT(0x8000000000000000))
+#define REGRESS_MAXUINT64 (G_GINT64_CONSTANT(0xffffffffffffffffU))
+
#endif /* __GITESTTYPES_H__ */