#2989: add PyType_Modified().
diff --git a/Doc/c-api/type.rst b/Doc/c-api/type.rst
index 762c003..e4e2e38 100644
--- a/Doc/c-api/type.rst
+++ b/Doc/c-api/type.rst
@@ -37,7 +37,16 @@
 
 .. cfunction:: unsigned int PyType_ClearCache(void)
 
-   Clears the internal lookup cache. Return the current version tag.
+   Clear the internal lookup cache. Return the current version tag.
+
+   .. versionadded:: 2.6
+
+
+.. cfunction:: void PyType_Modified(PyTypeObject *type)
+
+   Invalidate the internal lookup cache for the type and all of its
+   subtypes.  This function must be called after any manual
+   modification of the attributes or base classes of the type.
 
    .. versionadded:: 2.6
 
diff --git a/Include/object.h b/Include/object.h
index 2bdeb32..e0f5650 100644
--- a/Include/object.h
+++ b/Include/object.h
@@ -460,6 +460,7 @@
 					       PyObject *, PyObject *);
 PyAPI_FUNC(PyObject *) _PyType_Lookup(PyTypeObject *, PyObject *);
 PyAPI_FUNC(unsigned int) PyType_ClearCache(void);
+PyAPI_FUNC(void) PyType_Modified(PyTypeObject *);
 
 /* Generic operations on objects */
 PyAPI_FUNC(int) PyObject_Print(PyObject *, FILE *, int);
diff --git a/Misc/NEWS b/Misc/NEWS
index 1decc90..e5f251a 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -239,7 +239,9 @@
 C API
 -----
 
-- The PyBytes functions have been renamed to PyByteArray
+- Add ``PyType_Modified()`` as a public API to clear the type cache.
+
+- The PyBytes functions have been renamed to PyByteArray.
 
 - The PyString functions have been renamed to PyBytes. A batch of
   defines were added so that the linker still sees the original
diff --git a/Objects/typeobject.c b/Objects/typeobject.c
index 2ea3d29..151ea69 100644
--- a/Objects/typeobject.c
+++ b/Objects/typeobject.c
@@ -32,7 +32,6 @@
 
 static struct method_cache_entry method_cache[1 << MCACHE_SIZE_EXP];
 static unsigned int next_version_tag = 0;
-static void type_modified(PyTypeObject *);
 
 unsigned int
 PyType_ClearCache(void)
@@ -47,12 +46,12 @@
 	}
 	next_version_tag = 0;
 	/* mark all version tags as invalid */
-	type_modified(&PyBaseObject_Type);
+	PyType_Modified(&PyBaseObject_Type);
 	return cur_version_tag;
 }
 
-static void
-type_modified(PyTypeObject *type)
+void
+PyType_Modified(PyTypeObject *type)
 {
 	/* Invalidate any cached data for the specified type and all
 	   subclasses.  This function is called after the base
@@ -86,7 +85,7 @@
 			ref = PyList_GET_ITEM(raw, i);
 			ref = PyWeakref_GET_OBJECT(ref);
 			if (ref != Py_None) {
-				type_modified((PyTypeObject *)ref);
+				PyType_Modified((PyTypeObject *)ref);
 			}
 		}
 	}
@@ -172,7 +171,7 @@
 			Py_INCREF(Py_None);
 		}
 		/* mark all version tags as invalid */
-		type_modified(&PyBaseObject_Type);
+		PyType_Modified(&PyBaseObject_Type);
 		return 1;
 	}
 	bases = type->tp_bases;
@@ -300,7 +299,7 @@
 		return -1;
 	}
 
-	type_modified(type);
+	PyType_Modified(type);
 
 	return PyDict_SetItemString(type->tp_dict, "__module__", value);
 }
@@ -328,7 +327,7 @@
 	int res = PyDict_SetItemString(type->tp_dict,
 				       "__abstractmethods__", value);
 	if (res == 0) {
-		type_modified(type);
+		PyType_Modified(type);
 		if (value && PyObject_IsTrue(value)) {
 			type->tp_flags |= Py_TPFLAGS_IS_ABSTRACT;
 		}
@@ -1621,7 +1620,7 @@
 	   from the custom MRO */
 	type_mro_modified(type, type->tp_bases);
 
-	type_modified(type);
+	PyType_Modified(type);
 
 	return 0;
 }
@@ -6092,7 +6091,7 @@
 	   update_subclasses() recursion below, but carefully:
 	   they each have their own conditions on which to stop
 	   recursing into subclasses. */
-	type_modified(type);
+	PyType_Modified(type);
 
 	init_slotdefs();
 	pp = ptrs;