[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);
diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp
index 2e1aed2..1b4b84d 100644
--- a/clang/lib/AST/Type.cpp
+++ b/clang/lib/AST/Type.cpp
@@ -2833,24 +2833,28 @@
FunctionProtoType::FunctionProtoType(QualType result, ArrayRef<QualType> params,
QualType canonical,
const ExtProtoInfo &epi)
- : FunctionType(FunctionProto, result, canonical,
- result->isDependentType(),
+ : FunctionType(FunctionProto, result, canonical, result->isDependentType(),
result->isInstantiationDependentType(),
result->isVariablyModifiedType(),
- result->containsUnexpandedParameterPack(), epi.ExtInfo),
- NumParams(params.size()),
- NumExceptions(epi.ExceptionSpec.Exceptions.size()),
- ExceptionSpecType(epi.ExceptionSpec.Type),
- HasExtParameterInfos(epi.ExtParameterInfos != nullptr),
- Variadic(epi.Variadic), HasTrailingReturn(epi.HasTrailingReturn) {
- assert(NumParams == params.size() && "function has too many parameters");
-
+ result->containsUnexpandedParameterPack(), epi.ExtInfo) {
FunctionTypeBits.TypeQuals = epi.TypeQuals;
FunctionTypeBits.RefQualifier = epi.RefQualifier;
+ FunctionTypeBits.NumParams = params.size();
+ assert(getNumParams() == params.size() && "NumParams overflow!");
+ FunctionTypeBits.ExceptionSpecType = epi.ExceptionSpec.Type;
+ FunctionTypeBits.HasExtParameterInfos = !!epi.ExtParameterInfos;
+ FunctionTypeBits.Variadic = epi.Variadic;
+ FunctionTypeBits.HasTrailingReturn = epi.HasTrailingReturn;
+
+ // Fill in the extra trailing bitfields if present.
+ if (hasExtraBitfields(epi.ExceptionSpec.Type)) {
+ auto &ExtraBits = *getTrailingObjects<FunctionTypeExtraBitfields>();
+ ExtraBits.NumExceptionType = epi.ExceptionSpec.Exceptions.size();
+ }
// Fill in the trailing argument array.
- auto *argSlot = reinterpret_cast<QualType *>(this+1);
- for (unsigned i = 0; i != NumParams; ++i) {
+ auto *argSlot = getTrailingObjects<QualType>();
+ for (unsigned i = 0; i != getNumParams(); ++i) {
if (params[i]->isDependentType())
setDependent();
else if (params[i]->isInstantiationDependentType())
@@ -2862,9 +2866,11 @@
argSlot[i] = params[i];
}
+ // Fill in the exception type array if present.
if (getExceptionSpecType() == EST_Dynamic) {
- // Fill in the exception array.
- QualType *exnSlot = argSlot + NumParams;
+ assert(hasExtraBitfields() && "missing trailing extra bitfields!");
+ auto *exnSlot =
+ reinterpret_cast<QualType *>(getTrailingObjects<ExceptionType>());
unsigned I = 0;
for (QualType ExceptionType : epi.ExceptionSpec.Exceptions) {
// Note that, before C++17, a dependent exception specification does
@@ -2878,14 +2884,15 @@
exnSlot[I++] = ExceptionType;
}
- } else if (isComputedNoexcept(getExceptionSpecType())) {
+ }
+ // Fill in the Expr * in the exception specification if present.
+ else if (isComputedNoexcept(getExceptionSpecType())) {
assert(epi.ExceptionSpec.NoexceptExpr && "computed noexcept with no expr");
assert((getExceptionSpecType() == EST_DependentNoexcept) ==
epi.ExceptionSpec.NoexceptExpr->isValueDependent());
// Store the noexcept expression and context.
- auto **noexSlot = reinterpret_cast<Expr **>(argSlot + NumParams);
- *noexSlot = epi.ExceptionSpec.NoexceptExpr;
+ *getTrailingObjects<Expr *>() = epi.ExceptionSpec.NoexceptExpr;
if (epi.ExceptionSpec.NoexceptExpr->isValueDependent() ||
epi.ExceptionSpec.NoexceptExpr->isInstantiationDependent())
@@ -2893,10 +2900,12 @@
if (epi.ExceptionSpec.NoexceptExpr->containsUnexpandedParameterPack())
setContainsUnexpandedParameterPack();
- } else if (getExceptionSpecType() == EST_Uninstantiated) {
+ }
+ // Fill in the FunctionDecl * in the exception specification if present.
+ else if (getExceptionSpecType() == EST_Uninstantiated) {
// Store the function decl from which we will resolve our
// exception specification.
- auto **slot = reinterpret_cast<FunctionDecl **>(argSlot + NumParams);
+ auto **slot = getTrailingObjects<FunctionDecl *>();
slot[0] = epi.ExceptionSpec.SourceDecl;
slot[1] = epi.ExceptionSpec.SourceTemplate;
// This exception specification doesn't make the type dependent, because
@@ -2904,7 +2913,7 @@
} else if (getExceptionSpecType() == EST_Unevaluated) {
// Store the function decl from which we will resolve our
// exception specification.
- auto **slot = reinterpret_cast<FunctionDecl **>(argSlot + NumParams);
+ auto **slot = getTrailingObjects<FunctionDecl *>();
slot[0] = epi.ExceptionSpec.SourceDecl;
}
@@ -2921,10 +2930,10 @@
setDependent();
}
+ // Fill in the extra parameter info if present.
if (epi.ExtParameterInfos) {
- auto *extParamInfos =
- const_cast<ExtParameterInfo *>(getExtParameterInfosBuffer());
- for (unsigned i = 0; i != NumParams; ++i)
+ auto *extParamInfos = getTrailingObjects<ExtParameterInfo>();
+ for (unsigned i = 0; i != getNumParams(); ++i)
extParamInfos[i] = epi.ExtParameterInfos[i];
}
}
@@ -2970,7 +2979,7 @@
case EST_Dynamic:
// A dynamic exception specification is throwing unless every exception
// type is an (unexpanded) pack expansion type.
- for (unsigned I = 0, N = NumExceptions; I != N; ++I)
+ for (unsigned I = 0; I != getNumExceptions(); ++I)
if (!getExceptionType(I)->getAs<PackExpansionType>())
return CT_Can;
return CT_Dependent;
@@ -3045,8 +3054,8 @@
void FunctionProtoType::Profile(llvm::FoldingSetNodeID &ID,
const ASTContext &Ctx) {
- Profile(ID, getReturnType(), param_type_begin(), NumParams, getExtProtoInfo(),
- Ctx, isCanonicalUnqualified());
+ Profile(ID, getReturnType(), param_type_begin(), getNumParams(),
+ getExtProtoInfo(), Ctx, isCanonicalUnqualified());
}
QualType TypedefType::desugar() const {