diff options
author | William S Fulton <wsf@fultondesigns.co.uk> | 2023-01-12 08:38:17 +0000 |
---|---|---|
committer | William S Fulton <wsf@fultondesigns.co.uk> | 2023-02-17 08:22:55 +0000 |
commit | cac16bf94dc041d5f28e2e0fdfa1ae880d801d58 (patch) | |
tree | 930902e4dd899696438f44e1cfa3b61c3413749e | |
parent | 728f89adad42cc5f19900d54905382c22b0284d6 (diff) | |
download | swig-cac16bf94dc041d5f28e2e0fdfa1ae880d801d58.tar.gz |
Rewrite does_parm_match used in template partial specialization
Re-implement this function in preparation for fixing bugs in this
function. This rewrite should result in no change in the way it
previously worked for now.
-rw-r--r-- | Examples/test-suite/template_partial_specialization.i | 4 | ||||
-rw-r--r-- | Source/CParse/templ.c | 78 |
2 files changed, 38 insertions, 44 deletions
diff --git a/Examples/test-suite/template_partial_specialization.i b/Examples/test-suite/template_partial_specialization.i index 9727b52f8..4a0458a74 100644 --- a/Examples/test-suite/template_partial_specialization.i +++ b/Examples/test-suite/template_partial_specialization.i @@ -130,9 +130,6 @@ namespace AA { // thinks X is in AA namespace namespace Space { } template<typename T> struct Vector { -#ifdef SWIG - %template() Space::VectorHelper<T>; -#endif void gook(T i) {} void geeko(double d) {} void geeky(int d) {} @@ -142,7 +139,6 @@ template<typename T> struct Vector<T *> { }; */ //} -%} %template(VectorIntPtr) Space::Vector<int *>; // should fail as Vector is in global namespace // is this a regression - no fails in 1.3.40 too diff --git a/Source/CParse/templ.c b/Source/CParse/templ.c index 7ab91c145..718e5ddb8 100644 --- a/Source/CParse/templ.c +++ b/Source/CParse/templ.c @@ -630,57 +630,53 @@ typedef enum { ExactNoMatch = -2, PartiallySpecializedNoMatch = -1, PartiallySpe * template parameter type. Typedef reduce 'partial_parm_type' to see if it matches 'type'. * * type - template parameter type to match against - * partial_parm_type - partially specialized template type - a possible match - * partial_parm_type_base - base type of partial_parm_type + * partial_parm_type - specialized template type, for example, r.$1 (partially specialized) or r.int (fully specialized) + * partial_parm - partially specialized template parameter name, such as, $1 or $2 or $3, etc * tscope - template scope * specialization_priority - (output) contains a value indicating how good the match is * (higher is better) only set if return is set to PartiallySpecializedMatch or ExactMatch. * ----------------------------------------------------------------------------- */ -static EMatch does_parm_match(SwigType *type, SwigType *partial_parm_type, const char *partial_parm_type_base, Symtab *tscope, int *specialization_priority) { +static EMatch does_parm_match(SwigType *type, SwigType *partial_parm_type, const char *partial_parm, Symtab *tscope, int *specialization_priority) { static const int EXACT_MATCH_PRIORITY = 99999; /* a number bigger than the length of any conceivable type */ - int matches; - int substitutions; - EMatch match; SwigType *ty = Swig_symbol_typedef_reduce(type, tscope); - String *base = SwigType_base(ty); - SwigType *t = Copy(partial_parm_type); - substitutions = Replaceid(t, partial_parm_type_base, base); /* eg: Replaceid("p.$1", "$1", "int") returns t="p.int" */ - matches = Equal(ty, t); + SwigType *pp_prefix = SwigType_prefix(partial_parm_type); + int pp_len = Len(pp_prefix); + EMatch match = Strstr(partial_parm_type, partial_parm) == 0 ? ExactNoMatch : PartiallySpecializedNoMatch; *specialization_priority = -1; - if (substitutions == 1) { - /* we have a non-explicit specialized parameter (in partial_parm_type) because a substitution for $1, $2... etc has taken place */ - SwigType *tt = Copy(partial_parm_type); - int len; - /* - check for match to partial specialization type, for example, all of the following could match the type in the %template: - template <typename T> struct XX {}; - template <typename T> struct XX<T &> {}; // r.$1 - template <typename T> struct XX<T const&> {}; // r.q(const).$1 - template <typename T> struct XX<T *const&> {}; // r.q(const).p.$1 - %template(XXX) XX<int *const&>; // r.q(const).p.int - - where type="r.q(const).p.int" will match either of tt="r.", tt="r.q(const)" tt="r.q(const).p" - */ - Replaceid(tt, partial_parm_type_base, ""); /* remove the $1, $2 etc, eg tt="p.$1" => "p." */ - len = Len(tt); - if (Strncmp(tt, ty, len) == 0) { + + if (Equal(ty, partial_parm_type)) { + match = ExactMatch; + *specialization_priority = EXACT_MATCH_PRIORITY; /* exact matches always take precedence */ + } else if (match == PartiallySpecializedNoMatch) { + if ((pp_len > 0 && Strncmp(ty, pp_prefix, pp_len) == 0)) { + /* + type starts with pp_prefix, so it is a partial specialization type match, for example, + all of the following could match the type in the %template: + template <typename T> struct XX {}; + template <typename T> struct XX<T &> {}; // r.$1 + template <typename T> struct XX<T const&> {}; // r.q(const).$1 + template <typename T> struct XX<T *const&> {}; // r.q(const).p.$1 + %template(XXX) XX<int *const&>; // r.q(const).p.int + + where type="r.q(const).p.int" will match either of pp_prefix="r.", pp_prefix="r.q(const)." pp_prefix="r.q(const).p." + */ match = PartiallySpecializedMatch; - *specialization_priority = len; - } else { - match = PartiallySpecializedNoMatch; + *specialization_priority = pp_len; + } else if (pp_len == 0 && Equal(partial_parm_type, partial_parm)) { + /* + type without a prefix match, as in $1 for int + template <typename T, typename U> struct XX {}; + template <typename T, typename U> struct XX<T, U &> {}; // $1,r.$2 + %template(XXX) XX<int, double&>; // int,r.double + */ + match = PartiallySpecializedMatch; + *specialization_priority = pp_len; } - Delete(tt); - } else { - match = matches ? ExactMatch : ExactNoMatch; - if (matches) - *specialization_priority = EXACT_MATCH_PRIORITY; /* exact matches always take precedence */ } /* Printf(stdout, " does_parm_match %2d %5d [%s] [%s]\n", match, *specialization_priority, type, partial_parm_type); */ - Delete(t); - Delete(base); Delete(ty); return match; } @@ -721,6 +717,7 @@ static Node *template_locate(String *name, Parm *instantiated_parms, String *sym templ = Swig_symbol_clookup(name, 0); if (templ) { + /* TODO: check that this is not a specialization (might be a user error specializing a template before a primary template), but note https://stackoverflow.com/questions/9757642/wrapping-specialised-c-template-class-with-swig */ if (template_debug) { Printf(stdout, " found primary template <%s> '%s'\n", ParmList_str_defaultargs(Getattr(templ, "templateparms")), Getattr(templ, "name")); } @@ -902,9 +899,10 @@ static Node *template_locate(String *name, Parm *instantiated_parms, String *sym * T * * An ambiguous example when attempting to match as either specialization could match: %template() X<int *, double *>; - * template<typename T1, typename T2> X class {}; // primary template - * template<typename T1> X<T1, double *> class {}; // specialization (1) - * template<typename T2> X<int *, T2> class {}; // specialization (2) + * template<typename T1, typename T2> class X {}; // primary template + * template<typename T1> class X<T1, double *> {}; // specialization (1) + * template<typename T2> class X<int *, T2> {}; // specialization (2) + * */ if (template_debug) { int row, col; |