diff --git a/src/pike_compiler.h b/src/pike_compiler.h
index 001c8571dc064573ccec4c547cc35919024aea37..63226076619f6535d188e9e5b485bbc3d9b735e1 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.11 2008/05/03 20:06:06 grubba Exp $
+|| $Id: pike_compiler.h,v 1.12 2008/05/04 14:04:10 grubba Exp $
 */
 
 #ifndef PIKE_COMPILER_H
@@ -82,5 +82,6 @@ struct compilation
 #define PC_HANDLE_INHERIT_FUN_NUM			7
 #define PC_POP_TYPE_ATTRIBUTE_FUN_NUM			8
 #define PC_PUSH_TYPE_ATTRIBUTE_FUN_NUM			9
+#define PC_APPLY_TYPE_ATTRIBUTE_FUN_NUM			10
 
 #endif	/* !PIKE_COMPILER_H */
diff --git a/src/pike_types.c b/src/pike_types.c
index 1059b8ebb2f98fdd8a44fc0f7961cc79ee25c9cc..91822162f88b763184e2c7df2bf407db668b9f78 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.324 2008/05/03 20:06:07 grubba Exp $
+|| $Id: pike_types.c,v 1.325 2008/05/04 14:04:11 grubba Exp $
 */
 
 #include "global.h"
@@ -5717,6 +5717,7 @@ static struct pike_type *lower_new_check_call(struct pike_type *fun_type,
 #endif /* PIKE_TYPE_DEBUG */
 					      )
 {
+  struct compilation *c = MAYBE_THIS_COMPILATION;
   struct pike_type *res = NULL;
   struct pike_type *tmp;
   struct pike_type *tmp2;
@@ -5749,6 +5750,22 @@ static struct pike_type *lower_new_check_call(struct pike_type *fun_type,
 
   case PIKE_T_ATTRIBUTE:
     res = lower_new_check_call(fun_type->cdr, arg_type, flags, sval CHECK_CALL_ARGS);
+    if (!res) return NULL;
+    if (c) {
+      ref_push_string((struct pike_string *)fun_type->car);
+      ref_push_type_value(fun_type->cdr);
+      ref_push_type_value(arg_type);
+      safe_apply_current2(PC_APPLY_TYPE_ATTRIBUTE_FUN_NUM, 3,
+			  "apply_type_attribute");
+      if ((Pike_sp[-1].type == T_INT) &&
+	  (Pike_sp[-1].subtype == NUMBER_NUMBER) &&
+	  (!Pike_sp[-1].u.integer)) {
+	pop_stack();
+	free_type(res);
+	return NULL;
+      }
+      pop_stack();
+    }
     type_stack_mark();
     push_finished_type(res);
     push_type_attribute((struct pike_string *)fun_type->car);
@@ -5965,6 +5982,7 @@ static struct pike_type *lower_new_check_call(struct pike_type *fun_type,
 	struct compilation *c = MAYBE_THIS_COMPILATION;
 	/* Perform extra argument checking based on the attribute. */
 	/* FIXME: Support multiple attributes. */
+	/* FIXME: Ought to use PikeCompiler! */
 	ref_push_string((struct pike_string *)tmp2->car);
 	push_svalue(sval);
 	ref_push_type_value(tmp2->cdr);
@@ -6074,6 +6092,9 @@ struct pike_type *low_new_check_call(struct pike_type *fun_type,
     arg_type = arg_type->cdr;
     goto loop;
 
+    /* FIXME: PIKE_T_ATTRIBUTE's ought to propagate out to the basic types.
+     */
+
   case T_OR:
     if (!(tmp = low_new_check_call(fun_type, arg_type->car, flags, sval))) {
       if (flags & CALL_STRICT) {
diff --git a/src/program.c b/src/program.c
index 4299516b90bda8c85e9e341b058e5dc44c834c4e..706cddee6296c68c4a4ebc6157c10a91168d14fb 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.686 2008/05/03 20:06:06 grubba Exp $
+|| $Id: program.c,v 1.687 2008/05/04 14:04:10 grubba Exp $
 */
 
 #include "global.h"
@@ -8487,6 +8487,52 @@ static void f_compilation_push_type_attribute(INT32 args)
   push_int(1);
 }
 
+/*! @decl int(0..1) apply_type_attribute(string attribute, @
+ *!                                      type a, type b)
+ *!
+ *!   Type attribute handler.
+ *!
+ *!   Called during type checking when @[a] has been successfully
+ *!   had a partial evaluation with the argument @[b] and
+ *!   @[a] had the type attribute @[attribute] before the
+ *!   evaluation.
+ *!
+ *!   The default implementation implements the "deprecated"
+ *!   attribute.
+ *!
+ *! @returns
+ *!   Returns @expr{1@} if the type check should be allowed
+ *!   (ie @expr{__attribute__(attribute, a)(b)@}) is valid,
+ *!   and @expr{0@} (zero) otherwise.
+ *!
+ *! @seealso
+ *!   @[pop_type_attribute()], @[push_type_attribute()]
+ */
+static void f_compilation_apply_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("apply_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("Calling a deprecated value.");
+      apply_current(PC_REPORT_FUN_NUM, 5);
+      args++;
+    }
+  }
+  pop_n_elems(args);
+  push_int(1);
+}
+
 static void f_compilation__sprintf(INT32 args)
 {
   struct compilation *c = THIS_COMPILATION;
@@ -8764,6 +8810,9 @@ static void compile_compiler(void)
   ADD_FUNCTION("push_type_attribute", f_compilation_push_type_attribute,
 	       tFunc(tStr tType(tMix) tType(tMix), tInt01), 0);
 
+  ADD_FUNCTION("apply_type_attribute", f_compilation_apply_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);