From b882256ddb159e7169a30052f0c9fb2999f83b7a Mon Sep 17 00:00:00 2001 From: David Kastrup Date: Thu, 7 May 2015 00:30:18 +0200 Subject: [PATCH] Issue 4376: Add LY_ASSERT_DERIVED_SMOB macro When LY_ASSERT_SMOB is called with a class that is actually derived from some smobified base class providing is_smob and unsmob, the resulting check and error message are inaccurate. This patch uses dynamic_cast to implement a separate LY_ASSERT_DERIVED_SMOB attaining sensible behavior in that case. When no derivation is involved, the performance impact is minimal. --- lily/include/lily-guile-macros.hh | 19 ++++++++++++++++++- lily/lily-guile.cc | 17 +++++++++++++++++ 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/lily/include/lily-guile-macros.hh b/lily/include/lily-guile-macros.hh index 355bd58139..10520d6dc9 100644 --- a/lily/include/lily-guile-macros.hh +++ b/lily/include/lily-guile-macros.hh @@ -235,6 +235,23 @@ void ly_check_name (const string &cxx, const string &fname); } \ } -#define LY_ASSERT_SMOB(klass, var, number) LY_ASSERT_TYPE(klass::is_smob, var, number) +void ly_wrong_smob_arg (bool pred (SCM), SCM var, int number, const char *fun); + +// Could be just implemented using LY_ASSERT_TYPE, but this variant +// saves a slight amount of code + +#define LY_ASSERT_SMOB(klass, var, number) \ + { \ + if (!klass::is_smob (var)) \ + ly_wrong_smob_arg (klass::is_smob, var, number, __FUNCTION__); \ + } + +// This variant is for the case where klass::unsmob might actually be +// situated in a base class of klass +#define LY_ASSERT_DERIVED_SMOB(klass, var, number) \ + { \ + if (!derived_unsmob (var)) \ + ly_wrong_smob_arg (klass::is_smob, var, number, __FUNCTION__); \ + } #endif /* LILY_GUILE_MACROS_HH */ diff --git a/lily/lily-guile.cc b/lily/lily-guile.cc index 6f7bf37f70..d8d8d10edb 100644 --- a/lily/lily-guile.cc +++ b/lily/lily-guile.cc @@ -449,6 +449,23 @@ type_check_assignment (SCM sym, SCM val, SCM type_symbol) return true; } +void +ly_wrong_smob_arg (bool pred (SCM), SCM var, int number, const char *fun) +{ + string type = predicate_to_typename ((void *) pred); + if (pred (var)) + { + // Uh oh. derived_unsmob delivered 0, yet + // T::is_smob delivers true. This means that T::is_smob is a + // matching check from a base class of T, but var is of an + // incompatible derived type. + type = string (_ ("Wrong kind of ")).append (type); + } + scm_wrong_type_arg_msg (mangle_cxx_identifier (fun).c_str (), + number, var, type.c_str ()); +} + + /* some SCM abbrevs zijn deze nou handig? -- 2.39.2