I realized the problem.
if (((SPRepr *) css)->attributeList() == NULL) {
^^^^^^^^^^ The explicit C-style cast here makes deep assumptions about structure layout which were broken when the layout of SPReprs changed. I'm surprised it didn't break more spectacularly...
The resulting SPRepr * ends up pointing to the wrong place in the object, and getting the wrong vtable entry (or even random memory instead of a vtable). The backtrace from the PPC crash was probably accurate -- the wrong method really was getting called.
The quick and dirty fix for this particular case would be to rename the SPCSSRepr class in repr-css.cpp, then turn the forward declaration of SPCSSRepr in repr.h into a typedef SPRepr, so SPCSSRepr and SPRepr are the same type. At that point, the sp_repr_css_* functions end up taking SPRepr *s directly, so there wouldn't be any address fixup issues.
[ the somewhat more correct fix would be to set up SPCSSRepr the same way as has been done for SPReprDoc, with its own public abstract class that derives from SPRepr, and a non-public implementation class that derives from both SimpleNode and the abstract class ]
We may begin to encounter problems with C casts more frequently as we begin to use more C++ features. C-style casts just aren't safe in C++, and will often shoot you in the foot without any compiler warnings.
I have been doing my best to clean these sorts of things up in advance (which is why we've not seen other breakage so far), but I do occasionally miss them, as I did with the CSSRepr stuff. In new code, it's better to use the C++ casting operators, when you need to use casts at all (C++ should require them far less than C if you're doing things right).
-mental