diff --git a/src/pike_compiler.h b/src/pike_compiler.h index b661db1d8931abc5b02040718d687d2cce59882a..001c8571dc064573ccec4c547cc35919024aea37 100644 --- a/src/pike_compiler.h +++ b/src/pike_compiler.h @@ -2,7 +2,7 @@ || This file is part of Pike. For copyright information see COPYRIGHT. || Pike is distributed under GPL, LGPL and MPL. See the file COPYING || for more information. -|| $Id: pike_compiler.h,v 1.10 2008/05/02 10:56:06 grubba Exp $ +|| $Id: pike_compiler.h,v 1.11 2008/05/03 20:06:06 grubba Exp $ */ #ifndef PIKE_COMPILER_H @@ -80,5 +80,7 @@ struct compilation #define PC_GET_DEFAULT_MODULE_FUN_NUM 5 #define PC_CHANGE_COMPILER_COMPATIBILITY_FUN_NUM 6 #define PC_HANDLE_INHERIT_FUN_NUM 7 +#define PC_POP_TYPE_ATTRIBUTE_FUN_NUM 8 +#define PC_PUSH_TYPE_ATTRIBUTE_FUN_NUM 9 #endif /* !PIKE_COMPILER_H */ diff --git a/src/pike_types.c b/src/pike_types.c index 9f873066fba5c2125fc0b9873057923d3d152a44..1059b8ebb2f98fdd8a44fc0f7961cc79ee25c9cc 100644 --- a/src/pike_types.c +++ b/src/pike_types.c @@ -2,7 +2,7 @@ || This file is part of Pike. For copyright information see COPYRIGHT. || Pike is distributed under GPL, LGPL and MPL. See the file COPYING || for more information. -|| $Id: pike_types.c,v 1.323 2008/05/02 04:15:14 mast Exp $ +|| $Id: pike_types.c,v 1.324 2008/05/03 20:06:07 grubba Exp $ */ #include "global.h" @@ -3683,6 +3683,7 @@ static int low_pike_types_le2(struct pike_type *a, struct pike_type *b, int array_cnt, unsigned int flags) #endif /* PIKE_TYPE_DEBUG */ { + struct compilation *c = MAYBE_THIS_COMPILATION; int ret; recurse: @@ -3751,29 +3752,23 @@ static int low_pike_types_le2(struct pike_type *a, struct pike_type *b, b = b->cdr; goto recurse; } -#if 0 - if (!flags & LE_USE_HANDLERS) { + if (!c) { a = a->cdr; goto recurse; } -#endif /* 0 */ if (!low_pike_types_le(a->cdr, b, array_cnt, flags)) return 0; -#if 0 ref_push_string((struct pike_string *)a->car); ref_push_type_value(a->cdr); ref_push_type_value(b); - push_int(1); - if (safe_apply_handler("handle_attribute", error_handler, compat_handler, - 4, 0)) { - if ((Pike_sp[-1].type == T_INT) && - (Pike_sp[-1].subtype == NUMBER_NUMBER) && - (!Pike_sp[-1].u.integer)) { - pop_stack(); - return 0; - } + safe_apply_current2(PC_POP_TYPE_ATTRIBUTE_FUN_NUM, 3, + "pop_type_attribute"); + if ((Pike_sp[-1].type == T_INT) && + (Pike_sp[-1].subtype == NUMBER_NUMBER) && + (!Pike_sp[-1].u.integer)) { pop_stack(); + return 0; } -#endif /* 0 */ + pop_stack(); return 1; case T_NOT: @@ -3909,29 +3904,23 @@ static int low_pike_types_le2(struct pike_type *a, struct pike_type *b, goto recurse; case PIKE_T_ATTRIBUTE: -#if 0 - if (!flags & LE_USE_HANDLERS) { + if (!c) { b = b->cdr; goto recurse; } -#endif /* 0 */ if (!low_pike_types_le(a, b->cdr, array_cnt, flags)) return 0; -#if 0 ref_push_string((struct pike_string *)b->car); ref_push_type_value(a); ref_push_type_value(b->cdr); - push_int(2); - if (safe_apply_handler("handle_attribute", error_handler, compat_handler, - 4, 0)) { - if ((Pike_sp[-1].type == T_INT) && - (Pike_sp[-1].subtype == NUMBER_NUMBER) && - (!Pike_sp[-1].u.integer)) { - pop_stack(); - return 0; - } + safe_apply_current2(PC_PUSH_TYPE_ATTRIBUTE_FUN_NUM, 3, + "push_type_attribute"); + if ((Pike_sp[-1].type == T_INT) && + (Pike_sp[-1].subtype == NUMBER_NUMBER) && + (!Pike_sp[-1].u.integer)) { pop_stack(); + return 0; } -#endif /* 0 */ + pop_stack(); return 1; case PIKE_T_SCOPE: #ifdef TYPE_GROUPING diff --git a/src/program.c b/src/program.c index 72858ca5b90f823b78ba9eae4a23044984fe5c0e..4299516b90bda8c85e9e341b058e5dc44c834c4e 100644 --- a/src/program.c +++ b/src/program.c @@ -2,7 +2,7 @@ || This file is part of Pike. For copyright information see COPYRIGHT. || Pike is distributed under GPL, LGPL and MPL. See the file COPYING || for more information. -|| $Id: program.c,v 1.685 2008/05/03 15:54:13 grubba Exp $ +|| $Id: program.c,v 1.686 2008/05/03 20:06:06 grubba Exp $ */ #include "global.h" @@ -8393,6 +8393,100 @@ static void f_compilation_handle_inherit(INT32 args) } } +/*! @decl int(0..1) pop_type_attribute(string attribute, @ + *! type a, type b) + *! + *! Type attribute handler. + *! + *! Called during type checking when @expr{a <= b@} and + *! @[a] had the type attribute @[attribute] before the + *! comparison. + *! + *! The default implementation implements the "deprecated" + *! attribute. + *! + *! @returns + *! Returns @expr{1@} if the type check should be allowed + *! (ie @expr{__attribute__(attribute, a) <= b@}), and + *! @expr{0@} (zero) otherwise. + *! + *! @seealso + *! @[push_type_attribute()] + */ +static void f_compilation_pop_type_attribute(INT32 args) +{ + struct pike_string *attr; + struct svalue *a, *b; + struct compilation *c = THIS_COMPILATION; + struct pike_string *deprecated_string; + + get_all_args("pop_type_attribute", args, "%W%*%*", &attr, &a, &b); + + if (Pike_compiler->compiler_pass == 2) { + MAKE_CONST_STRING(deprecated_string, "deprecated"); + if (attr == deprecated_string) { + push_int(REPORT_WARNING); + ref_push_string(c->lex.current_file); + push_int(c->lex.current_line); + push_constant_text("type_check"); + push_constant_text("Using deprecated %O value."); + push_svalue(a); + apply_current(PC_REPORT_FUN_NUM, 6); + args++; + } + } + pop_n_elems(args); + push_int(1); +} + +/*! @decl int(0..1) push_type_attribute(string attribute, @ + *! type a, type b) + *! + *! Type attribute handler. + *! + *! Called during type checking when @expr{a <= b@} and + *! @[b] had the type attribute @[attribute] before the + *! comparison. + *! + *! The default implementation implements the "deprecated" + *! attribute. + *! + *! @returns + *! Returns @expr{1@} if the type check should be allowed + *! (ie @expr{a <= __attribute__(attribute, b)@}), and + *! @expr{0@} (zero) otherwise. + *! + *! @seealso + *! @[pop_type_attribute()] + */ +static void f_compilation_push_type_attribute(INT32 args) +{ + struct pike_string *attr; + struct svalue *a, *b; + struct compilation *c = THIS_COMPILATION; + struct pike_string *deprecated_string; + + get_all_args("push_type_attribute", args, "%W%*%*", &attr, &a, &b); + + if (Pike_compiler->compiler_pass == 2) { + MAKE_CONST_STRING(deprecated_string, "deprecated"); + if (attr == deprecated_string && + !((a->type == PIKE_T_TYPE) && (a->u.type == zero_type_string))) { + /* Don't warn about setting deprecated values to zero. */ + push_int(REPORT_WARNING); + ref_push_string(c->lex.current_file); + push_int(c->lex.current_line); + push_constant_text("type_check"); + push_constant_text("Using deprecated %O value."); + push_svalue(b); + apply_current(PC_REPORT_FUN_NUM, 6); + args++; + } + } + pop_n_elems(args); + push_int(1); +} + static void f_compilation__sprintf(INT32 args) { struct compilation *c = THIS_COMPILATION; @@ -8664,6 +8758,12 @@ static void compile_compiler(void) ADD_FUNCTION("handle_inherit", f_compilation_handle_inherit, tFunc(tStr, tPrg(tObj)), 0); + ADD_FUNCTION("pop_type_attribute", f_compilation_pop_type_attribute, + tFunc(tStr tType(tMix) tType(tMix), tInt01), 0); + + ADD_FUNCTION("push_type_attribute", f_compilation_push_type_attribute, + tFunc(tStr tType(tMix) tType(tMix), tInt01), 0); + ADD_FUNCTION("_sprintf", f_compilation__sprintf, tFunc(tInt tOr(tMap(tStr, tMix), tVoid), tStr), ID_STATIC); diff --git a/src/testsuite.in b/src/testsuite.in index 00b9687f1a86eee758ed82421d064c168ca817f6..753b192c35d8fc85c915632c117bce06377b3436 100644 --- a/src/testsuite.in +++ b/src/testsuite.in @@ -1,5 +1,5 @@ START_MARKER -test_true([["$Id: testsuite.in,v 1.803 2008/05/03 15:51:50 grubba Exp $"]]); +test_true([["$Id: testsuite.in,v 1.804 2008/05/03 20:06:07 grubba Exp $"]]); // This triggered a bug only if run sufficiently early. test_compile_any([[#pike 7.2]]) @@ -11131,6 +11131,39 @@ test_compile_error_any(class A {nomask int f(){}} class B {inherit A; int f;}) test_compile_any(class A {local int f(){}} class B {inherit A; int f;}) test_compile_any(class A {inline int f(){}} class B {inherit A; int f;}) +// - attributes +test_compile_any( + class A { __deprecated__ int foo(int x) { return x; } }; +) +test_compile_warning( + class A { __deprecated__ int foo(int x) { return x; } }; + A()->foo(0); +) +test_compile_warning( + class A { __deprecated__ int foo(int x) { return x; } }; + function bar = A()->foo; +) +test_compile_warning( + class A { __deprecated__(int) foo(int x) { return x; } }; +) +test_compile_any( + class A { __deprecated__(int) foo(int x) { return (__deprecated__(int))x; } }; +) +test_compile_warning( + class A { int foo(__deprecated__(int)|void x) { return x; } }; +) +test_compile_warning( + class A { int foo(__deprecated__(int)|void x) { return (int)x; } }; +) +test_compile_warning( + class A { int foo(__deprecated__(int)|void x) { return (int)x; } }; + A()->foo(0); +) +test_compile_any( + class A { int foo(__deprecated__(int)|void x) { return (int)x; } }; + A()->foo(); +) + // - modifiers, compile time access properties test_compile_error_any(class A {} class B {inherit A; int q; void g(){q=v;}})