[glibmm] gmmproc: _WRAP_PROPERTY: Check the data type
- From: Kjell Ahlstedt <kjellahl src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glibmm] gmmproc: _WRAP_PROPERTY: Check the data type
- Date: Thu, 31 Jan 2019 12:43:46 +0000 (UTC)
commit 203063d1b7a8bcc9bb0ffb9e8bbbfe5d5832a944
Author: Kjell Ahlstedt <kjellahlstedt gmail com>
Date: Thu Jan 31 13:41:01 2019 +0100
gmmproc: _WRAP_PROPERTY: Check the data type
* glib/glibmm/value_custom.h: Add template class
Glib::Traits::ValueCompatibleWithWrapProperty<> that checks if the template
parameter names a type that can be used with _WRAP_PROPERTY
and _WRAP_CHILD_PROPERTY.
* tools/m4/property.m4:
* tools/pm/Output.pm:
* tools/pm/WrapParser.pm: _WRAP_PROPERTY and _WRAP_CHILD_PROPERTY generate
a static_assert() that checks if the data type is acceptable. The generation
of the static_assert() can be suppressed with the new no_type_check parameter.
glib/glibmm/value_custom.h | 35 +++++++++++++++++++++++++++++++++++
tools/m4/property.m4 | 10 ++++++++--
tools/pm/Output.pm | 44 ++++++++++++++++++++++++++++++++------------
tools/pm/WrapParser.pm | 17 ++++++++++++-----
4 files changed, 87 insertions(+), 19 deletions(-)
---
diff --git a/glib/glibmm/value_custom.h b/glib/glibmm/value_custom.h
index 7c23a8d2..e5c19895 100644
--- a/glib/glibmm/value_custom.h
+++ b/glib/glibmm/value_custom.h
@@ -99,6 +99,10 @@ template <class T, typename Enable = void>
class Value : public ValueBase_Boxed
{
public:
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+ // Used in class Glib::Traits::ValueCompatibleWithWrapProperty.
+ using dont_use_with_wrap_property_ = int;
+#endif
using CppType = T;
static GType value_type() G_GNUC_CONST;
@@ -283,6 +287,37 @@ Value<T, Enable>::value_copy_func(const GValue* src_value, GValue* dest_value)
dest_value->data[0].v_pointer = new (std::nothrow) T(source);
}
+namespace Traits
+{
+/** Helper class for testing if Glib::Value<T> would instantiate a Glib::Value
+ * that can be used in _WRAP_PROPERTY and _WRAP_CHILD_PROPERTY.
+ *
+ * Some instantiations of Glib::Value, such as instantiations of the primary
+ * template, generate code which is useless but compilable when generated by
+ * _WRAP_PROPERTY and _WRAP_CHILD_PROPERTY.
+ */
+template <typename T>
+class ValueCompatibleWithWrapProperty
+{
+private:
+ struct big
+ {
+ int memory[64];
+ };
+
+ static big check_type(...);
+
+ // If Glib::Value<X>::dont_use_with_wrap_property_ is not a type, this check_type()
+ // overload is ignored because of the SFINAE rule (Substitution Failure Is Not An Error).
+ template <typename X>
+ static typename Glib::Value<X>::dont_use_with_wrap_property_ check_type(X* obj);
+
+public:
+ static const bool value = sizeof(check_type(static_cast<T*>(nullptr))) == sizeof(big);
+};
+
+} // namespace Traits
+
#endif /* DOXYGEN_SHOULD_SKIP_THIS */
} // namespace Glib
diff --git a/tools/m4/property.m4 b/tools/m4/property.m4
index 1709affa..c4544ded 100644
--- a/tools/m4/property.m4
+++ b/tools/m4/property.m4
@@ -4,8 +4,8 @@ dnl Code generation sections for properties
dnl
dnl
-dnl $1 $2 $3 $4 $5 $6
-dnl _PROPERTY_PROXY(name, name_underscored, cpp_type, proxy_suffix, deprecated, docs)
+dnl $1 $2 $3 $4 $5 $6 $7
+dnl _PROPERTY_PROXY(name, name_underscored, cpp_type, proxy_suffix, deprecated, docs, check_type)
dnl proxy_suffix could be "", "_WriteOnly" or "_ReadOnly"
dnl The method will be const if the propertyproxy is _ReadOnly.
dnl
@@ -24,6 +24,12 @@ ifelse($4,_ReadOnly,get,`ifelse($4,_WriteOnly,set,get or set)') the value of the
__PROXY_TYPE__ property_$2`'() ifelse($4,_ReadOnly, const,);
_PUSH(SECTION_CC_PROPERTYPROXIES)
ifelse(`$5',,,`_DEPRECATE_IFDEF_START
+')dnl
+ifelse(`$7',,,`dnl
+static_assert(`$7'<_QUOTE($3)>::value,
+ "Type _QUOTE($3) cannot be used in _WRAP_PROPERTY. "
+ "There is no suitable template specialization of Glib::Value<>.");
+
')dnl
__PROXY_TYPE__ __CPPNAME__::property_$2`'() ifelse($4,_ReadOnly, const,)
{
diff --git a/tools/pm/Output.pm b/tools/pm/Output.pm
index 5fcfc9d6..a7bdc8cf 100644
--- a/tools/pm/Output.pm
+++ b/tools/pm/Output.pm
@@ -860,11 +860,12 @@ sub output_wrap_gerror($$$$$$$$$$$$$)
}
# _PROPERTY_PROXY(name, cpp_type) and _CHILD_PROPERTY_PROXY(name, cpp_type)
-# void output_wrap_any_property($filename, $line_num, $name, $cpp_type, $c_class, $deprecated,
$deprecation_docs, $objProperty, $proxy_macro)
+# void output_wrap_any_property($filename, $line_num, $name, $cpp_type, $c_class,
+# $deprecated, $deprecation_docs, $newin, $bNoTypeCheck, $objProperty, $proxy_macro)
sub output_wrap_any_property($$$$$$$$$$)
{
my ($self, $filename, $line_num, $name, $cpp_type, $c_class, $deprecated,
- $deprecation_docs, $newin, $objProperty, $proxy_macro) = @_;
+ $deprecation_docs, $newin, $bNoTypeCheck, $objProperty, $proxy_macro) = @_;
my $objDefsParser = $$self{objDefsParser};
@@ -950,19 +951,34 @@ sub output_wrap_any_property($$$$$$$$$$)
$documentation .= $default_value;
}
+ # Possibly generate a static_assert(), asserting that the generated code
+ # will include a Glib::Value instantiation which is compatible with
+ # _WRAP_PROPERTY and _WRAP_CHILD_PROPERTY.
+ # This test is skipped for some types that are known to have suitable
+ # Glib::Value<> instantiations, or if the no_type_check parameter is specified.
+ my $check_type = "";
+ if (!$bNoTypeCheck)
+ {
+ my @good_types = qw(bool int guint float double std::string Glib::ustring
+ Widget* Gtk::Widget*);
+ push(@good_types, "unsigned int");
+ $check_type = "Glib::Traits::ValueCompatibleWithWrapProperty" if (!grep {$cpp_type eq $_} @good_types);
+ }
+
#Declaration:
if($deprecated ne "")
{
$self->append("\n_DEPRECATE_IFDEF_START\n");
}
- my $str = sprintf("$proxy_macro(%s,%s,%s,%s,%s,`%s')dnl\n",
+ my $str = sprintf("$proxy_macro(%s,%s,%s,%s,%s,`%s',`%s')dnl\n",
$name,
$name_underscored,
$cpp_type,
$proxy_suffix,
$deprecated,
- $documentation
+ $documentation,
+ $check_type
);
$self->append($str);
$self->append("\n");
@@ -971,13 +987,15 @@ sub output_wrap_any_property($$$$$$$$$$)
# then add a second const accessor for a read-only propertyproxy:
if( ($proxy_suffix ne "_ReadOnly") && ($objProperty->get_readable()) )
{
- my $str = sprintf("$proxy_macro(%s,%s,%s,%s,%s,`%s')dnl\n",
+ $check_type = ""; # Don't check twice.
+ my $str = sprintf("$proxy_macro(%s,%s,%s,%s,%s,`%s',`%s')dnl\n",
$name,
$name_underscored,
$cpp_type,
"_ReadOnly",
$deprecated,
- $documentation
+ $documentation,
+ $check_type
);
$self->append($str);
}
@@ -990,11 +1008,11 @@ sub output_wrap_any_property($$$$$$$$$$)
# _PROPERTY_PROXY(name, cpp_type)
# void output_wrap_property($filename, $line_num, $name, $cpp_type, $file_deprecated,
-# $deprecated, $deprecation_docs)
+# $deprecated, $deprecation_docs, $newin, $bNoTypeCheck)
sub output_wrap_property($$$$$$$$$$)
{
my ($self, $filename, $line_num, $name, $cpp_type, $c_class, $file_deprecated,
- $deprecated, $deprecation_docs, $newin) = @_;
+ $deprecated, $deprecation_docs, $newin, $bNoTypeCheck) = @_;
my $objProperty = GtkDefs::lookup_property($c_class, $name);
if($objProperty eq 0) #If the lookup failed:
@@ -1007,17 +1025,18 @@ sub output_wrap_property($$$$$$$$$$)
$deprecated, $name, "property", "PROPERTY");
$self->output_wrap_any_property($filename, $line_num, $name, $cpp_type, $c_class,
- $deprecated, $deprecation_docs, $newin, $objProperty, "_PROPERTY_PROXY");
+ $deprecated, $deprecation_docs, $newin, $bNoTypeCheck, $objProperty,
+ "_PROPERTY_PROXY");
}
}
# _CHILD_PROPERTY_PROXY(name, cpp_type)
# void output_wrap_child_property($filename, $line_num, $name, $cpp_type, $file_deprecated,
-# $deprecated, $deprecation_docs)
+# $deprecated, $deprecation_docs, $newin, $bNoTypeCheck)
sub output_wrap_child_property($$$$$$$$$$)
{
my ($self, $filename, $line_num, $name, $cpp_type, $c_class, $file_deprecated,
- $deprecated, $deprecation_docs, $newin) = @_;
+ $deprecated, $deprecation_docs, $newin, $bNoTypeCheck) = @_;
my $objChildProperty = GtkDefs::lookup_child_property($c_class, $name);
if($objChildProperty eq 0) #If the lookup failed:
@@ -1030,7 +1049,8 @@ sub output_wrap_child_property($$$$$$$$$$)
$deprecated, $name, "child property", "CHILD_PROPERTY");
$self->output_wrap_any_property($filename, $line_num, $name, $cpp_type, $c_class,
- $deprecated, $deprecation_docs, $newin, $objChildProperty, "_CHILD_PROPERTY_PROXY");
+ $deprecated, $deprecation_docs, $newin, $bNoTypeCheck, $objChildProperty,
+ "_CHILD_PROPERTY_PROXY");
}
}
diff --git a/tools/pm/WrapParser.pm b/tools/pm/WrapParser.pm
index 36adfc4f..20af0f03 100644
--- a/tools/pm/WrapParser.pm
+++ b/tools/pm/WrapParser.pm
@@ -1600,6 +1600,7 @@ sub on_wrap_any_property($)
my $argDeprecated = "";
my $deprecation_docs = "";
my $newin = "";
+ my $bNoTypeCheck = 0;
while($#args >= 2) # If the optional arguments are there.
{
my $argRef = string_trim(pop @args);
@@ -1617,10 +1618,14 @@ sub on_wrap_any_property($)
{
$newin = string_unquote(string_trim($1));
}
+ elsif($argRef eq "no_type_check")
+ {
+ $bNoTypeCheck = 1;
+ }
}
return ($filename, $line_num, $argPropertyName, $argCppType,
- $argDeprecated, $deprecation_docs, $newin);
+ $argDeprecated, $deprecation_docs, $newin, $bNoTypeCheck);
}
sub on_wrap_property($)
@@ -1631,10 +1636,11 @@ sub on_wrap_property($)
return unless ($self->check_for_eof());
my ($filename, $line_num, $argPropertyName, $argCppType, $argDeprecated,
- $deprecation_docs, $newin) = $self->on_wrap_any_property();
+ $deprecation_docs, $newin, $bNoTypeCheck) = $self->on_wrap_any_property();
$objOutputter->output_wrap_property($filename, $line_num, $argPropertyName,
- $argCppType, $$self{c_class}, $$self{deprecated}, $argDeprecated, $deprecation_docs, $newin);
+ $argCppType, $$self{c_class}, $$self{deprecated}, $argDeprecated, $deprecation_docs,
+ $newin, $bNoTypeCheck);
}
sub on_wrap_child_property($)
@@ -1645,10 +1651,11 @@ sub on_wrap_child_property($)
return unless ($self->check_for_eof());
my ($filename, $line_num, $argPropertyName, $argCppType, $argDeprecated,
- $deprecation_docs, $newin) = $self->on_wrap_any_property();
+ $deprecation_docs, $newin, $bNoTypeCheck) = $self->on_wrap_any_property();
$objOutputter->output_wrap_child_property($filename, $line_num, $argPropertyName,
- $argCppType, $$self{c_class}, $$self{deprecated}, $argDeprecated, $deprecation_docs, $newin);
+ $argCppType, $$self{c_class}, $$self{deprecated}, $argDeprecated, $deprecation_docs,
+ $newin, $bNoTypeCheck);
}
sub output_wrap_check($$$$$$)
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]