diff options
author | Zeev Suraski <zeev@php.net> | 2004-02-04 16:30:15 +0000 |
---|---|---|
committer | Zeev Suraski <zeev@php.net> | 2004-02-04 16:30:15 +0000 |
commit | c5d842279c592cc2637d2c355761741cc03ab2a0 (patch) | |
tree | 2f03655e980744594b73b9a142beb3a5d139cecf /Zend/zend_execute_API.c | |
parent | 723641590a376fea3ae3fe503785cc037ca304ef (diff) | |
download | php-git-c5d842279c592cc2637d2c355761741cc03ab2a0.tar.gz |
Reinstate early-binding for classes.
Note that this is available for downwards compatibility only - and it doesn't
work if you use new features (namely, interfaces). Generally, people should
declare their classes before using them, but we just didn't want hell to break
loose (c)
Diffstat (limited to 'Zend/zend_execute_API.c')
-rw-r--r-- | Zend/zend_execute_API.c | 45 |
1 files changed, 45 insertions, 0 deletions
diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c index 3267829f7d..c443678f47 100644 --- a/Zend/zend_execute_API.c +++ b/Zend/zend_execute_API.c @@ -1225,6 +1225,51 @@ ZEND_API void zend_clear_exception(TSRMLS_D) } +#define MAX_ABSTRACT_INFO_CNT 3 +#define MAX_ABSTRACT_INFO_FMT "%s%s%s%s" +#define DISPLAY_ABSTRACT_FN(idx) \ + ai.afn[idx] ? ZEND_FN_SCOPE_NAME(ai.afn[idx]) : "", \ + ai.afn[idx] ? "::" : "", \ + ai.afn[idx] ? ai.afn[idx]->common.function_name : "", \ + ai.afn[idx] && ai.afn[idx+1] ? ", " : (ai.afn[idx] && ai.cnt >= MAX_ABSTRACT_INFO_CNT ? ", ..." : "") + +typedef struct _zend_abstract_info { + zend_function *afn[MAX_ABSTRACT_INFO_CNT+1]; + int cnt; +} zend_abstract_info; + + +static int zend_verify_abstract_class_function(zend_function *fn, zend_abstract_info *ai TSRMLS_DC) +{ + if (fn->common.fn_flags & ZEND_ACC_ABSTRACT) { + if (ai->cnt < MAX_ABSTRACT_INFO_CNT) { + ai->afn[ai->cnt] = fn; + } + ai->cnt++; + } + return 0; +} + + +void zend_verify_abstract_class(zend_class_entry *ce TSRMLS_DC) +{ + zend_abstract_info ai; + + if ((ce->ce_flags & ZEND_ACC_ABSTRACT) && !(ce->ce_flags & ZEND_ACC_ABSTRACT_CLASS)) { + memset(&ai, 0, sizeof(ai)); + + zend_hash_apply_with_argument(&ce->function_table, (apply_func_arg_t) zend_verify_abstract_class_function, &ai TSRMLS_CC); + + zend_error(E_ERROR, "Class %s contains %d abstract methods and must therefore be declared abstract (" MAX_ABSTRACT_INFO_FMT MAX_ABSTRACT_INFO_FMT MAX_ABSTRACT_INFO_FMT ")", + ce->name, ai.cnt, + DISPLAY_ABSTRACT_FN(0), + DISPLAY_ABSTRACT_FN(1), + DISPLAY_ABSTRACT_FN(2) + ); + } +} + + /* * Local variables: * tab-width: 4 |