Commit 203063d1 authored by Kjell Ahlstedt's avatar Kjell Ahlstedt

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.
parent bae8d173
......@@ -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
......
......@@ -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,)
{
......
......@@ -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");
}
}
......
......@@ -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($$$$$$)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment