[AST] Pack the bit-fields of FunctionProtoType into Type.
Move the bit-fields of FunctionProtoType into FunctionTypeBitfields.
This cuts the size of FunctionProtoType by a pointer. Additionally use
llvm::TrailingObjects instead of manually doing the casts + arithmetic.
This patch is bigger then what could be expected for the following reasons:
1. As discussed before in D50631 it would be nice if there was some space left
in FunctionTypeBitfields for future additions. This patch introduces an
extra structure FunctionTypeExtraBitfields which is supposed to hold
uncommon bits and is stored in a trailing object. The number of exception
types NumExceptions is moved to this struct. As of this patch this trailing
struct will only be allocated if we have > 0 types in a dynamic exception
specification.
2. TrailingObjects cannot handle repeated types. Therefore the QualType
representing an exception type is wrapped in a struct ExceptionType.
The ExceptionType * is then reinterpret_cast'd to QualType *.
3. TrailingObjects needs the definition of the various trailing classes.
Therefore ExtParameterInfo, ExceptionType and FunctionTypeExtraBitfields
are put in FunctionType.
Differential Revision: https://reviews.llvm.org/D52738
Reviewed By: rjmccall
llvm-svn: 343579
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index 21bdc09..8e7b747 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -3697,30 +3697,19 @@
assert(!NewIP && "Shouldn't be in the map!"); (void)NewIP;
}
- // FunctionProtoType objects are allocated with extra bytes after
- // them for three variable size arrays at the end:
- // - parameter types
- // - exception types
- // - extended parameter information
- // Instead of the exception types, there could be a noexcept
- // expression, or information used to resolve the exception
- // specification.
- size_t Size =
- sizeof(FunctionProtoType) + NumArgs * sizeof(QualType) +
- FunctionProtoType::getExceptionSpecSize(
- EPI.ExceptionSpec.Type, EPI.ExceptionSpec.Exceptions.size());
+ // Compute the needed size to hold this FunctionProtoType and the
+ // various trailing objects.
+ auto ESH = FunctionProtoType::getExceptionSpecSize(
+ EPI.ExceptionSpec.Type, EPI.ExceptionSpec.Exceptions.size());
+ size_t Size = FunctionProtoType::totalSizeToAlloc<
+ QualType, FunctionType::FunctionTypeExtraBitfields,
+ FunctionType::ExceptionType, Expr *, FunctionDecl *,
+ FunctionProtoType::ExtParameterInfo>(
+ NumArgs, FunctionProtoType::hasExtraBitfields(EPI.ExceptionSpec.Type),
+ ESH.NumExceptionType, ESH.NumExprPtr, ESH.NumFunctionDeclPtr,
+ EPI.ExtParameterInfos ? NumArgs : 0);
- // Put the ExtParameterInfos last. If all were equal, it would make
- // more sense to put these before the exception specification, because
- // it's much easier to skip past them compared to the elaborate switch
- // required to skip the exception specification. However, all is not
- // equal; ExtParameterInfos are used to model very uncommon features,
- // and it's better not to burden the more common paths.
- if (EPI.ExtParameterInfos) {
- Size += NumArgs * sizeof(FunctionProtoType::ExtParameterInfo);
- }
-
- auto *FTP = (FunctionProtoType *) Allocate(Size, TypeAlignment);
+ auto *FTP = (FunctionProtoType *)Allocate(Size, TypeAlignment);
FunctionProtoType::ExtProtoInfo newEPI = EPI;
new (FTP) FunctionProtoType(ResultTy, ArgArray, Canonical, newEPI);
Types.push_back(FTP);