Store the optional array size expression, optional initialization expression and optional
placement new arguments in a trailing array. Additionally store the range for the parenthesized
type-id in a trailing object if needed since in the vast majority of cases the type is not parenthesized
(not a single new expression in the translation unit of SemaDecl.cpp has a parenthesized type-id).
This saves 2 pointers per CXXNewExpr in all cases, and 2 pointers + 8 bytes per CXXNewExpr
in the common case where the type is not parenthesized.
If you ever want a somewhat bigger refactoring project that might provide major wins on C++ code, one idea I've had for awhile is to largely eliminate TypeSourceInfo from the AST in favor of storing a TypeLoc in most places. A TSI is basically a TL that stores the location data in a trailing array; it was convenient as a way to retrofit type-location information into the AST without massive changes, and it saves a pointer (at the cost of an extra indirection) when the TSI can be shared between parent nodes. But I think the TSI can rarely be shared between parent nodes (pretty much just template instantiation of a non-dependent type), and the structure forces the location data to be copied when the type changes (e.g. during template instantiation) even if the location data would be the same. It also means we can't use a preallocated zero buffer in getTrivialTypeSourceInfo with a null SourceLocation, and instead we have to allocate and initialize an appropriately-sized zero'ed trailing array.
The win wouldn't be as large as it could be because FunctionProtoTypeLoc includes ParmVarDecls, which get cloned during template instantiation and therefore would always require a new type-location buffer when e.g. instantiating a function temploid. But it might still be quite significant.