Fix for SF bug #642358: only provide a new with a __dict__ or
__weaklist__ descriptor if we added __dict__ or __weaklist__,
respectively.  With unit test.
diff --git a/Objects/typeobject.c b/Objects/typeobject.c
index 2de5395..e88f5f5 100644
--- a/Objects/typeobject.c
+++ b/Objects/typeobject.c
@@ -1353,9 +1353,9 @@
 	return result;
 }
 
-static PyGetSetDef subtype_getsets[] = {
-	/* Not all objects have these attributes!
-	   The descriptor's __get__ method may raise AttributeError. */
+/* Three variants on the subtype_getsets list. */
+
+static PyGetSetDef subtype_getsets_full[] = {
 	{"__dict__", subtype_dict, subtype_setdict,
 	 PyDoc_STR("dictionary for instance variables (if defined)")},
 	{"__weakref__", subtype_getweakref, NULL,
@@ -1363,6 +1363,18 @@
 	{0}
 };
 
+static PyGetSetDef subtype_getsets_dict_only[] = {
+	{"__dict__", subtype_dict, subtype_setdict,
+	 PyDoc_STR("dictionary for instance variables (if defined)")},
+	{0}
+};
+
+static PyGetSetDef subtype_getsets_weakref_only[] = {
+	{"__weakref__", subtype_getweakref, NULL,
+	 PyDoc_STR("list of weak references to the object (if defined)")},
+	{0}
+};
+
 /* bozo: __getstate__ that raises TypeError */
 
 static PyObject *
@@ -1810,7 +1822,15 @@
 	type->tp_basicsize = slotoffset;
 	type->tp_itemsize = base->tp_itemsize;
 	type->tp_members = et->members;
-	type->tp_getset = subtype_getsets;
+
+	if (type->tp_weaklistoffset && type->tp_dictoffset)
+		type->tp_getset = subtype_getsets_full;
+	else if (type->tp_weaklistoffset && !type->tp_dictoffset)
+		type->tp_getset = subtype_getsets_weakref_only;
+	else if (!type->tp_weaklistoffset && type->tp_dictoffset)
+		type->tp_getset = subtype_getsets_dict_only;
+	else
+		type->tp_getset = NULL;
 
 	/* Special case some slots */
 	if (type->tp_dictoffset != 0 || nslots > 0) {