/// Decl - This represents one declaration (or definition), e.g. a variable,
/// typedef, function, struct, etc.
///
+/// Note: There are objects tacked on before the *beginning* of Decl
+/// (and its subclasses) in its Decl::operator new(). Proper alignment
+/// of all subclasses (not requiring more than DeclObjAlignment) is
+/// asserted in DeclBase.cpp.
class Decl {
public:
+ /// \brief Alignment guaranteed when allocating Decl and any subtypes.
+ enum { DeclObjAlignment = llvm::AlignOf<uint64_t>::Alignment };
+
/// \brief Lists the kind of concrete classes of Decl.
enum Kind {
#define DECL(DERIVED, BASE) DERIVED,
/// \brief Stores a list of template parameters for a TemplateDecl and its
/// derived classes.
-class TemplateParameterList {
+class LLVM_ALIGNAS(/*alignof(void*)*/ LLVM_PTR_SIZE) TemplateParameterList {
/// The location of the 'template' keyword.
SourceLocation TemplateLoc;
/// friend void foo<>(T);
/// };
/// \endcode
-class DependentFunctionTemplateSpecializationInfo {
- struct CA {
- /// The number of potential template candidates.
- unsigned NumTemplates;
+class LLVM_ALIGNAS(/*alignof(uint64_t)*/ 8)
+ DependentFunctionTemplateSpecializationInfo {
+ /// The number of potential template candidates.
+ unsigned NumTemplates;
- /// The number of template arguments.
- unsigned NumArgs;
- };
-
- union {
- // Force sizeof to be a multiple of sizeof(void*) so that the
- // trailing data is aligned.
- void *Aligner;
- struct CA d;
- };
+ /// The number of template arguments.
+ unsigned NumArgs;
/// The locations of the left and right angle brackets.
SourceRange AngleLocs;
FunctionTemplateDecl * const *getTemplates() const {
- return reinterpret_cast<FunctionTemplateDecl*const*>(this+1);
+ return reinterpret_cast<FunctionTemplateDecl *const *>(
+ &getTemplateArgs()[NumArgs]);
}
public:
/// \brief Returns the number of function templates that this might
/// be a specialization of.
- unsigned getNumTemplates() const {
- return d.NumTemplates;
- }
+ unsigned getNumTemplates() const { return NumTemplates; }
/// \brief Returns the i'th template candidate.
FunctionTemplateDecl *getTemplate(unsigned I) const {
/// \brief Returns the explicit template arguments that were given.
const TemplateArgumentLoc *getTemplateArgs() const {
- return reinterpret_cast<const TemplateArgumentLoc*>(
- &getTemplates()[getNumTemplates()]);
+ return reinterpret_cast<const TemplateArgumentLoc *>(this + 1);
}
/// \brief Returns the number of explicit template arguments that were given.
- unsigned getNumTemplateArgs() const {
- return d.NumArgs;
- }
+ unsigned getNumTemplateArgs() const { return NumArgs; }
/// \brief Returns the nth template argument.
const TemplateArgumentLoc &getTemplateArg(unsigned I) const {
void VisitLambdaExpr(PTR(LambdaExpr) LE) {
// Only visit the capture initializers, and not the body.
- for (LambdaExpr::capture_init_iterator I = LE->capture_init_begin(),
- E = LE->capture_init_end();
+ for (LambdaExpr::const_capture_init_iterator I = LE->capture_init_begin(),
+ E = LE->capture_init_end();
I != E; ++I)
if (*I)
this->Visit(*I);
/// DeclRefExprBits.RefersToEnclosingVariableOrCapture
/// Specifies when this declaration reference expression (validly)
/// refers to an enclosed local or a captured variable.
-class DeclRefExpr : public Expr {
+class LLVM_ALIGNAS(/*alignof(uint64_t)*/ 8) DeclRefExpr : public Expr {
/// \brief The declaration that we are referencing.
ValueDecl *D;
if (!hasTemplateKWAndArgsInfo())
return nullptr;
- if (hasFoundDecl())
+ if (hasFoundDecl()) {
return reinterpret_cast<ASTTemplateKWAndArgsInfo *>(
- &getInternalFoundDecl() + 1);
+ llvm::alignAddr(&getInternalFoundDecl() + 1,
+ llvm::alignOf<ASTTemplateKWAndArgsInfo>()));
+ }
- if (hasQualifier())
+ if (hasQualifier()) {
return reinterpret_cast<ASTTemplateKWAndArgsInfo *>(
- &getInternalQualifierLoc() + 1);
+ llvm::alignAddr(&getInternalQualifierLoc() + 1,
+ llvm::alignOf<ASTTemplateKWAndArgsInfo>()));
+ }
return reinterpret_cast<ASTTemplateKWAndArgsInfo *>(this + 1);
}
/// MemberExpr - [C99 6.5.2.3] Structure and Union Members. X->F and X.F.
///
-class MemberExpr : public Expr {
+class LLVM_ALIGNAS(/*alignof(uint64_t)*/ 8) MemberExpr : public Expr {
/// Extra data stored in some member expressions.
- struct MemberNameQualifier {
+ struct LLVM_ALIGNAS(/*alignof(uint64_t)*/ 8) MemberNameQualifier {
/// \brief The nested-name-specifier that qualifies the name, including
/// source-location information.
NestedNameSpecifierLoc QualifierLoc;
ExplicitResultType(false), HasArrayIndexVars(true) {
getStoredStmts()[NumCaptures] = nullptr;
}
-
- Stmt **getStoredStmts() const {
- return reinterpret_cast<Stmt **>(const_cast<LambdaExpr *>(this) + 1);
+
+ Stmt **getStoredStmts() { return reinterpret_cast<Stmt **>(this + 1); }
+
+ Stmt *const *getStoredStmts() const {
+ return reinterpret_cast<Stmt *const *>(this + 1);
}
-
+
/// \brief Retrieve the mapping from captures to the first array index
/// variable.
- unsigned *getArrayIndexStarts() const {
+ unsigned *getArrayIndexStarts() {
return reinterpret_cast<unsigned *>(getStoredStmts() + NumCaptures + 1);
}
+ const unsigned *getArrayIndexStarts() const {
+ return reinterpret_cast<const unsigned *>(getStoredStmts() + NumCaptures +
+ 1);
+ }
+
/// \brief Retrieve the complete set of array-index variables.
- VarDecl **getArrayIndexVars() const {
+ VarDecl **getArrayIndexVars() {
unsigned ArrayIndexSize = llvm::RoundUpToAlignment(
sizeof(unsigned) * (NumCaptures + 1), llvm::alignOf<VarDecl *>());
return reinterpret_cast<VarDecl **>(
reinterpret_cast<char *>(getArrayIndexStarts()) + ArrayIndexSize);
}
+ VarDecl *const *getArrayIndexVars() const {
+ unsigned ArrayIndexSize = llvm::RoundUpToAlignment(
+ sizeof(unsigned) * (NumCaptures + 1), llvm::alignOf<VarDecl *>());
+ return reinterpret_cast<VarDecl *const *>(
+ reinterpret_cast<const char *>(getArrayIndexStarts()) + ArrayIndexSize);
+ }
+
public:
/// \brief Construct a new lambda expression.
static LambdaExpr *Create(const ASTContext &C,
/// arguments.
typedef Expr **capture_init_iterator;
+ /// \brief Const iterator that walks over the capture initialization
+ /// arguments.
+ typedef Expr *const *const_capture_init_iterator;
+
/// \brief Retrieve the initialization expressions for this lambda's captures.
- llvm::iterator_range<capture_init_iterator> capture_inits() const {
+ llvm::iterator_range<capture_init_iterator> capture_inits() {
return llvm::iterator_range<capture_init_iterator>(capture_init_begin(),
capture_init_end());
}
+ /// \brief Retrieve the initialization expressions for this lambda's captures.
+ llvm::iterator_range<const_capture_init_iterator> capture_inits() const {
+ return llvm::iterator_range<const_capture_init_iterator>(
+ capture_init_begin(), capture_init_end());
+ }
+
/// \brief Retrieve the first initialization argument for this
/// lambda expression (which initializes the first capture field).
- capture_init_iterator capture_init_begin() const {
+ capture_init_iterator capture_init_begin() {
return reinterpret_cast<Expr **>(getStoredStmts());
}
+ /// \brief Retrieve the first initialization argument for this
+ /// lambda expression (which initializes the first capture field).
+ const_capture_init_iterator capture_init_begin() const {
+ return reinterpret_cast<Expr *const *>(getStoredStmts());
+ }
+
/// \brief Retrieve the iterator pointing one past the last
/// initialization argument for this lambda expression.
- capture_init_iterator capture_init_end() const {
- return capture_init_begin() + NumCaptures;
+ capture_init_iterator capture_init_end() {
+ return capture_init_begin() + NumCaptures;
}
- /// \brief Retrieve the set of index variables used in the capture
+ /// \brief Retrieve the iterator pointing one past the last
+ /// initialization argument for this lambda expression.
+ const_capture_init_iterator capture_init_end() const {
+ return capture_init_begin() + NumCaptures;
+ }
+
+ /// \brief Retrieve the set of index variables used in the capture
/// initializer of an array captured by copy.
///
- /// \param Iter The iterator that points at the capture initializer for
+ /// \param Iter The iterator that points at the capture initializer for
/// which we are extracting the corresponding index variables.
- ArrayRef<VarDecl *> getCaptureInitIndexVars(capture_init_iterator Iter) const;
-
+ ArrayRef<VarDecl *>
+ getCaptureInitIndexVars(const_capture_init_iterator Iter) const;
+
/// \brief Retrieve the source range covering the lambda introducer,
/// which contains the explicit capture list surrounded by square
/// brackets ([...]).
/// \brief A reference to an overloaded function set, either an
/// \c UnresolvedLookupExpr or an \c UnresolvedMemberExpr.
-class OverloadExpr : public Expr {
+class LLVM_ALIGNAS(/*alignof(uint64_t)*/ 8) OverloadExpr : public Expr {
/// \brief The common name of these declarations.
DeclarationNameInfo NameInfo;
/// qualifier (X<T>::) and the name of the entity being referenced
/// ("value"). Such expressions will instantiate to a DeclRefExpr once the
/// declaration can be found.
-class DependentScopeDeclRefExpr : public Expr {
+class LLVM_ALIGNAS(/*alignof(uint64_t)*/ 8) DependentScopeDeclRefExpr
+ : public Expr {
/// \brief The nested-name-specifier that qualifies this unresolved
/// declaration name.
NestedNameSpecifierLoc QualifierLoc;
/// Like UnresolvedMemberExprs, these can be either implicit or
/// explicit accesses. It is only possible to get one of these with
/// an implicit access if a qualifier is provided.
-class CXXDependentScopeMemberExpr : public Expr {
+class LLVM_ALIGNAS(/*alignof(uint64_t)*/ 8) CXXDependentScopeMemberExpr
+ : public Expr {
/// \brief The expression for the base pointer or class reference,
/// e.g., the \c x in x.f. Can be null in implicit accesses.
Stmt *Base;
/// In the final AST, an explicit access always becomes a MemberExpr.
/// An implicit access may become either a MemberExpr or a
/// DeclRefExpr, depending on whether the member is static.
-class UnresolvedMemberExpr : public OverloadExpr {
+class LLVM_ALIGNAS(/*alignof(uint64_t)*/ 8) UnresolvedMemberExpr
+ : public OverloadExpr {
/// \brief Whether this member expression used the '->' operator or
/// the '.' operator.
bool IsArrow : 1;
}
};
+inline ASTTemplateKWAndArgsInfo *OverloadExpr::getTemplateKWAndArgsInfo() {
+ if (!HasTemplateKWAndArgsInfo)
+ return nullptr;
+ if (isa<UnresolvedLookupExpr>(this))
+ return reinterpret_cast<ASTTemplateKWAndArgsInfo *>(
+ cast<UnresolvedLookupExpr>(this) + 1);
+ else
+ return reinterpret_cast<ASTTemplateKWAndArgsInfo *>(
+ cast<UnresolvedMemberExpr>(this) + 1);
+}
+
/// \brief Represents a C++11 noexcept expression (C++ [expr.unary.noexcept]).
///
/// The noexcept expression tests whether a given expression might throw. Its
}
};
-inline ASTTemplateKWAndArgsInfo *OverloadExpr::getTemplateKWAndArgsInfo() {
- if (!HasTemplateKWAndArgsInfo) return nullptr;
- if (isa<UnresolvedLookupExpr>(this))
- return reinterpret_cast<ASTTemplateKWAndArgsInfo*>
- (cast<UnresolvedLookupExpr>(this) + 1);
- else
- return reinterpret_cast<ASTTemplateKWAndArgsInfo*>
- (cast<UnresolvedMemberExpr>(this) + 1);
-}
/// \brief Represents an expression that computes the length of a parameter
/// pack.
child_range children() {
// Note: we're taking advantage of the layout of the KeyValuePair struct
// here. If that struct changes, this code will need to change as well.
+ static_assert(sizeof(KeyValuePair) == sizeof(Stmt *) * 2,
+ "KeyValuePair is expected size");
return child_range(reinterpret_cast<Stmt **>(this + 1),
reinterpret_cast<Stmt **>(this + 1) + NumElements * 2);
}
/// \brief Construct an empty captured statement.
CapturedStmt(EmptyShell Empty, unsigned NumCaptures);
- Stmt **getStoredStmts() const {
- return reinterpret_cast<Stmt **>(const_cast<CapturedStmt *>(this) + 1);
+ Stmt **getStoredStmts() { return reinterpret_cast<Stmt **>(this + 1); }
+
+ Stmt *const *getStoredStmts() const {
+ return reinterpret_cast<Stmt *const *>(this + 1);
}
Capture *getStoredCaptures() const;
/// \brief Retrieve the statement being captured.
Stmt *getCapturedStmt() { return getStoredStmts()[NumCaptures]; }
- const Stmt *getCapturedStmt() const {
- return const_cast<CapturedStmt *>(this)->getCapturedStmt();
- }
+ const Stmt *getCapturedStmt() const { return getStoredStmts()[NumCaptures]; }
/// \brief Retrieve the outlined function declaration.
CapturedDecl *getCapturedDecl() { return CapDeclAndKind.getPointer(); }
const CapturedDecl *getCapturedDecl() const {
- return const_cast<CapturedStmt *>(this)->getCapturedDecl();
+ return CapDeclAndKind.getPointer();
}
/// \brief Set the outlined function declaration.
typedef Expr **capture_init_iterator;
typedef llvm::iterator_range<capture_init_iterator> capture_init_range;
- capture_init_range capture_inits() const {
+ /// \brief Const iterator that walks over the capture initialization
+ /// arguments.
+ typedef Expr *const *const_capture_init_iterator;
+ typedef llvm::iterator_range<const_capture_init_iterator>
+ const_capture_init_range;
+
+ capture_init_range capture_inits() {
return capture_init_range(capture_init_begin(), capture_init_end());
}
+ const_capture_init_range capture_inits() const {
+ return const_capture_init_range(capture_init_begin(), capture_init_end());
+ }
+
/// \brief Retrieve the first initialization argument.
- capture_init_iterator capture_init_begin() const {
+ capture_init_iterator capture_init_begin() {
return reinterpret_cast<Expr **>(getStoredStmts());
}
+ const_capture_init_iterator capture_init_begin() const {
+ return reinterpret_cast<Expr *const *>(getStoredStmts());
+ }
+
/// \brief Retrieve the iterator pointing one past the last initialization
/// argument.
- capture_init_iterator capture_init_end() const {
+ capture_init_iterator capture_init_end() {
+ return capture_init_begin() + NumCaptures;
+ }
+
+ const_capture_init_iterator capture_init_end() const {
return capture_init_begin() + NumCaptures;
}
assert(hasAnyConsumedParams());
// Find the end of the exceptions.
- Expr *const *eh_end = reinterpret_cast<Expr *const *>(param_type_end());
- if (getExceptionSpecType() != EST_ComputedNoexcept)
- eh_end += NumExceptions;
- else
+ Expr *const *eh_end = reinterpret_cast<Expr *const *>(exception_end());
+ if (getExceptionSpecType() == EST_ComputedNoexcept)
eh_end += 1; // NoexceptExpr
+ // The memory layout of these types isn't handled here, so
+ // hopefully this is never called for them?
+ assert(getExceptionSpecType() != EST_Uninstantiated &&
+ getExceptionSpecType() != EST_Unevaluated);
return reinterpret_cast<const bool*>(eh_end);
}
const ExtProtoInfo &EPI, const ASTContext &Context);
};
-
/// \brief Represents the dependent type named by a dependently-scoped
/// typename using declaration, e.g.
/// using typename Base<T>::foo;
/// TemplateArguments, followed by a QualType representing the
/// non-canonical aliased type when the template is a type alias
/// template.
-class TemplateSpecializationType
- : public Type, public llvm::FoldingSetNode {
+class LLVM_ALIGNAS(/*alignof(uint64_t)*/ 8) TemplateSpecializationType
+ : public Type,
+ public llvm::FoldingSetNode {
/// The name of the template being specialized. This is
/// either a TemplateName::Template (in which case it is a
/// ClassTemplateDecl*, a TemplateTemplateParmDecl*, or a
/// Represents a template specialization type whose template cannot be
/// resolved, e.g.
/// A<T>::template B<T>
-class DependentTemplateSpecializationType :
- public TypeWithKeyword, public llvm::FoldingSetNode {
+class LLVM_ALIGNAS(/*alignof(uint64_t)*/ 8) DependentTemplateSpecializationType
+ : public TypeWithKeyword,
+ public llvm::FoldingSetNode {
/// The nested name specifier containing the qualifier.
NestedNameSpecifier *NNS;
/// \brief Return the TypeLoc for a type source info.
inline TypeLoc TypeSourceInfo::getTypeLoc() const {
+ // TODO: is this alignment already sufficient?
return TypeLoc(Ty, const_cast<void*>(static_cast<const void*>(this + 1)));
}
AttributeList *NextInPool;
/// Arguments, if any, are stored immediately following the object.
- ArgsUnion *getArgsBuffer() {
- return reinterpret_cast<ArgsUnion*>(this+1);
- }
+ ArgsUnion *getArgsBuffer() { return reinterpret_cast<ArgsUnion *>(this + 1); }
ArgsUnion const *getArgsBuffer() const {
- return reinterpret_cast<ArgsUnion const *>(this+1);
+ return reinterpret_cast<ArgsUnion const *>(this + 1);
}
enum AvailabilitySlot {
const TemplateArgumentListInfo &TemplateArgs) {
assert(TemplateOrSpecialization.isNull());
size_t Size = sizeof(DependentFunctionTemplateSpecializationInfo);
- Size += Templates.size() * sizeof(FunctionTemplateDecl*);
Size += TemplateArgs.size() * sizeof(TemplateArgumentLoc);
+ Size += Templates.size() * sizeof(FunctionTemplateDecl *);
void *Buffer = Context.Allocate(Size);
DependentFunctionTemplateSpecializationInfo *Info =
new (Buffer) DependentFunctionTemplateSpecializationInfo(Templates,
static_assert(sizeof(*this) % llvm::AlignOf<void *>::Alignment == 0,
"Trailing data is unaligned!");
- d.NumTemplates = Ts.size();
- d.NumArgs = TArgs.size();
+ NumTemplates = Ts.size();
+ NumArgs = TArgs.size();
FunctionTemplateDecl **TsArray =
const_cast<FunctionTemplateDecl**>(getTemplates());
getASTContext().getExternalSource()->updateOutOfDateIdentifier(II);
}
+#define DECL(DERIVED, BASE) \
+ static_assert(Decl::DeclObjAlignment >= \
+ llvm::AlignOf<DERIVED##Decl>::Alignment, \
+ "Alignment sufficient after objects prepended to " #DERIVED);
+#define ABSTRACT_DECL(DECL)
+#include "clang/AST/DeclNodes.inc"
+
void *Decl::operator new(std::size_t Size, const ASTContext &Context,
unsigned ID, std::size_t Extra) {
// Allocate an extra 8 bytes worth of storage, which ensures that the
- // resulting pointer will still be 8-byte aligned.
+ // resulting pointer will still be 8-byte aligned.
+ static_assert(sizeof(unsigned) * 2 >= DeclObjAlignment,
+ "Decl won't be misaligned");
void *Start = Context.Allocate(Size + Extra + 8);
void *Result = (char*)Start + 8;
// With local visibility enabled, we track the owning module even for local
// declarations.
if (Ctx.getLangOpts().ModulesLocalVisibility) {
- void *Buffer = ::operator new(sizeof(Module *) + Size + Extra, Ctx);
+ // Ensure required alignment of the resulting object by adding extra
+ // padding at the start if required.
+ size_t ExtraAlign =
+ llvm::OffsetToAlignment(sizeof(Module *), DeclObjAlignment);
+ char *Buffer = reinterpret_cast<char *>(
+ ::operator new(ExtraAlign + sizeof(Module *) + Size + Extra, Ctx));
+ Buffer += ExtraAlign;
return new (Buffer) Module*(nullptr) + 1;
}
return ::operator new(Size + Extra, Ctx);
Size += sizeof(NestedNameSpecifierLoc);
if (FoundD)
Size += sizeof(NamedDecl *);
- if (TemplateArgs)
+ if (TemplateArgs) {
+ Size = llvm::RoundUpToAlignment(Size,
+ llvm::alignOf<ASTTemplateKWAndArgsInfo>());
Size += ASTTemplateKWAndArgsInfo::sizeFor(TemplateArgs->size());
- else if (TemplateKWLoc.isValid())
+ } else if (TemplateKWLoc.isValid()) {
+ Size = llvm::RoundUpToAlignment(Size,
+ llvm::alignOf<ASTTemplateKWAndArgsInfo>());
Size += ASTTemplateKWAndArgsInfo::sizeFor(0);
+ }
void *Mem = Context.Allocate(Size, llvm::alignOf<DeclRefExpr>());
return new (Mem) DeclRefExpr(Context, QualifierLoc, TemplateKWLoc, D,
Size += sizeof(NestedNameSpecifierLoc);
if (HasFoundDecl)
Size += sizeof(NamedDecl *);
- if (HasTemplateKWAndArgsInfo)
+ if (HasTemplateKWAndArgsInfo) {
+ Size = llvm::RoundUpToAlignment(Size,
+ llvm::alignOf<ASTTemplateKWAndArgsInfo>());
Size += ASTTemplateKWAndArgsInfo::sizeFor(NumTemplateArgs);
+ }
void *Mem = Context.Allocate(Size, llvm::alignOf<DeclRefExpr>());
return new (Mem) DeclRefExpr(EmptyShell());
SourceLocation ColonOrEqualLoc,
bool UsesColonSyntax, Expr *Init) {
void *Mem = C.Allocate(sizeof(DesignatedInitExpr) +
- sizeof(Stmt *) * (IndexExprs.size() + 1), 8);
+ sizeof(Stmt *) * (IndexExprs.size() + 1),
+ llvm::alignOf<DesignatedInitExpr>());
return new (Mem) DesignatedInitExpr(C, C.VoidTy, NumDesignators, Designators,
ColonOrEqualLoc, UsesColonSyntax,
IndexExprs, Init);
return capture_range(implicit_capture_begin(), implicit_capture_end());
}
-ArrayRef<VarDecl *>
-LambdaExpr::getCaptureInitIndexVars(capture_init_iterator Iter) const {
+ArrayRef<VarDecl *>
+LambdaExpr::getCaptureInitIndexVars(const_capture_init_iterator Iter) const {
assert(HasArrayIndexVars && "No array index-var data?");
unsigned Index = Iter - capture_init_begin();
assert(Index < getLambdaClass()->getLambdaData().NumCaptures &&
"Capture index out-of-range");
- VarDecl **IndexVars = getArrayIndexVars();
- unsigned *IndexStarts = getArrayIndexStarts();
+ VarDecl *const *IndexVars = getArrayIndexVars();
+ const unsigned *IndexStarts = getArrayIndexStarts();
return llvm::makeArrayRef(IndexVars + IndexStarts[Index],
IndexVars + IndexStarts[Index + 1]);
}
}
CompoundStmt *LambdaExpr::getBody() const {
+ // FIXME: this mutation in getBody is bogus. It should be
+ // initialized in ASTStmtReader::VisitLambdaExpr, but for reasons I
+ // don't understand, that doesn't work.
if (!getStoredStmts()[NumCaptures])
- getStoredStmts()[NumCaptures] = getCallOperator()->getBody();
-
+ *const_cast<clang::Stmt **>(&getStoredStmts()[NumCaptures]) =
+ getCallOperator()->getBody();
+
return reinterpret_cast<CompoundStmt *>(getStoredStmts()[NumCaptures]);
}
CXXTryStmt *CXXTryStmt::Create(const ASTContext &C, SourceLocation tryLoc,
Stmt *tryBlock, ArrayRef<Stmt*> handlers) {
std::size_t Size = sizeof(CXXTryStmt);
- Size += ((handlers.size() + 1) * sizeof(Stmt));
+ Size += ((handlers.size() + 1) * sizeof(Stmt *));
void *Mem = C.Allocate(Size, llvm::alignOf<CXXTryStmt>());
return new (Mem) CXXTryStmt(tryLoc, tryBlock, handlers);
CXXTryStmt *CXXTryStmt::Create(const ASTContext &C, EmptyShell Empty,
unsigned numHandlers) {
std::size_t Size = sizeof(CXXTryStmt);
- Size += ((numHandlers + 1) * sizeof(Stmt));
+ Size += ((numHandlers + 1) * sizeof(Stmt *));
void *Mem = C.Allocate(Size, llvm::alignOf<CXXTryStmt>());
return new (Mem) CXXTryStmt(Empty, numHandlers);
C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *));
return new (Mem) OMPTeamsDirective(NumClauses);
}
-
/// Push an entry of the given size onto this protected-scope stack.
char *EHScopeStack::allocate(size_t Size) {
+ Size = llvm::RoundUpToAlignment(Size, ScopeStackAlignment);
if (!StartOfBuffer) {
unsigned Capacity = 1024;
while (Capacity < Size) Capacity *= 2;
return StartOfData;
}
+void EHScopeStack::deallocate(size_t Size) {
+ StartOfData += llvm::RoundUpToAlignment(Size, ScopeStackAlignment);
+}
+
bool EHScopeStack::containsOnlyLifetimeMarkers(
EHScopeStack::stable_iterator Old) const {
for (EHScopeStack::iterator it = begin(); stabilize(it) != Old; it++) {
void *EHScopeStack::pushCleanup(CleanupKind Kind, size_t Size) {
- assert(((Size % sizeof(void*)) == 0) && "cleanup type is misaligned");
char *Buffer = allocate(EHCleanupScope::getSizeForCleanupSize(Size));
bool IsNormalCleanup = Kind & NormalCleanup;
bool IsEHCleanup = Kind & EHCleanup;
EHCleanupScope &Cleanup = cast<EHCleanupScope>(*begin());
InnermostNormalCleanup = Cleanup.getEnclosingNormalCleanup();
InnermostEHScope = Cleanup.getEnclosingEHScope();
- StartOfData += Cleanup.getAllocatedSize();
+ deallocate(Cleanup.getAllocatedSize());
// Destroy the cleanup.
Cleanup.Destroy();
assert(!empty() && "popping exception stack when not empty");
EHFilterScope &filter = cast<EHFilterScope>(*begin());
- StartOfData += EHFilterScope::getSizeForNumFilters(filter.getNumFilters());
+ deallocate(EHFilterScope::getSizeForNumFilters(filter.getNumFilters()));
InnermostEHScope = filter.getEnclosingEHScope();
}
};
/// A cleanup scope which generates the cleanup blocks lazily.
-class EHCleanupScope : public EHScope {
+class LLVM_ALIGNAS(/*alignof(uint64_t)*/ 8) EHCleanupScope : public EHScope {
/// The nearest normal cleanup scope enclosing this one.
EHScopeStack::stable_iterator EnclosingNormal;
return (Scope->getKind() == Cleanup);
}
};
+// NOTE: there's a bunch of different data classes tacked on after an
+// EHCleanupScope. It is asserted (in EHScopeStack::pushCleanup*) that
+// they don't require greater alignment than ScopeStackAlignment. So,
+// EHCleanupScope ought to have alignment equal to that -- not more
+// (would be misaligned by the stack allocator), and not less (would
+// break the appended classes).
+static_assert(llvm::AlignOf<EHCleanupScope>::Alignment ==
+ EHScopeStack::ScopeStackAlignment,
+ "EHCleanupScope expected alignment");
/// An exceptions scope which filters exceptions thrown through it.
/// Only exceptions matching the filter types will be permitted to be
EHScope &operator*() const { return *get(); }
iterator &operator++() {
+ size_t Size;
switch (get()->getKind()) {
case EHScope::Catch:
- Ptr += EHCatchScope::getSizeForNumHandlers(
- static_cast<const EHCatchScope*>(get())->getNumHandlers());
+ Size = EHCatchScope::getSizeForNumHandlers(
+ static_cast<const EHCatchScope *>(get())->getNumHandlers());
break;
case EHScope::Filter:
- Ptr += EHFilterScope::getSizeForNumFilters(
- static_cast<const EHFilterScope*>(get())->getNumFilters());
+ Size = EHFilterScope::getSizeForNumFilters(
+ static_cast<const EHFilterScope *>(get())->getNumFilters());
break;
case EHScope::Cleanup:
- Ptr += static_cast<const EHCleanupScope*>(get())
- ->getAllocatedSize();
+ Size = static_cast<const EHCleanupScope *>(get())->getAllocatedSize();
break;
case EHScope::Terminate:
- Ptr += EHTerminateScope::getSize();
+ Size = EHTerminateScope::getSize();
break;
}
-
+ Ptr += llvm::RoundUpToAlignment(Size, ScopeStackAlignment);
return *this;
}
EHCatchScope &scope = cast<EHCatchScope>(*begin());
InnermostEHScope = scope.getEnclosingEHScope();
- StartOfData += EHCatchScope::getSizeForNumHandlers(scope.getNumHandlers());
+ deallocate(EHCatchScope::getSizeForNumHandlers(scope.getNumHandlers()));
}
inline void EHScopeStack::popTerminate() {
EHTerminateScope &scope = cast<EHTerminateScope>(*begin());
InnermostEHScope = scope.getEnclosingEHScope();
- StartOfData += EHTerminateScope::getSize();
+ deallocate(EHTerminateScope::getSize());
}
inline EHScopeStack::iterator EHScopeStack::find(stable_iterator sp) const {
MakeAddrLValue(Slot.getAddr(), E->getType(), Slot.getAlignment());
CXXRecordDecl::field_iterator CurField = E->getLambdaClass()->field_begin();
- for (LambdaExpr::capture_init_iterator i = E->capture_init_begin(),
- e = E->capture_init_end();
+ for (LambdaExpr::const_capture_init_iterator i = E->capture_init_begin(),
+ e = E->capture_init_end();
i != e; ++i, ++CurField) {
// Emit initialization
LValue LV = EmitLValueForFieldInitialization(SlotLV, *CurField);
CreateMemTemp(RecordTy, "agg.captured"), RecordTy);
RecordDecl::field_iterator CurField = RD->field_begin();
- for (CapturedStmt::capture_init_iterator I = S.capture_init_begin(),
- E = S.capture_init_end();
+ for (CapturedStmt::const_capture_init_iterator I = S.capture_init_begin(),
+ E = S.capture_init_end();
I != E; ++I, ++CurField) {
LValue LV = EmitLValueForFieldInitialization(SlotLV, *CurField);
if (CurField->hasCapturedVLAType()) {
/// and catch blocks.
class EHScopeStack {
public:
+ enum { ScopeStackAlignment = llvm::AlignOf<uint64_t>::Alignment };
+
/// A saved depth on the scope stack. This is necessary because
/// pushing scopes onto the stack invalidates iterators.
class stable_iterator {
SmallVector<BranchFixup, 8> BranchFixups;
char *allocate(size_t Size);
+ void deallocate(size_t Size);
void *pushCleanup(CleanupKind K, size_t DataSize);
/// Push a lazily-created cleanup on the stack.
template <class T, class... As> void pushCleanup(CleanupKind Kind, As... A) {
+ static_assert(llvm::AlignOf<T>::Alignment <= ScopeStackAlignment,
+ "Cleanup's alignment is too large.");
void *Buffer = pushCleanup(Kind, sizeof(T));
Cleanup *Obj = new (Buffer) T(A...);
(void) Obj;
/// Push a lazily-created cleanup on the stack. Tuple version.
template <class T, class... As>
void pushCleanupTuple(CleanupKind Kind, std::tuple<As...> A) {
+ static_assert(llvm::AlignOf<T>::Alignment <= ScopeStackAlignment,
+ "Cleanup's alignment is too large.");
void *Buffer = pushCleanup(Kind, sizeof(T));
Cleanup *Obj = new (Buffer) T(std::move(A));
(void) Obj;
/// stack is modified.
template <class T, class... As>
T *pushCleanupWithExtra(CleanupKind Kind, size_t N, As... A) {
+ static_assert(llvm::AlignOf<T>::Alignment <= ScopeStackAlignment,
+ "Cleanup's alignment is too large.");
void *Buffer = pushCleanup(Kind, sizeof(T) + T::getExtraSize(N));
return new (Buffer) T(N, A...);
}
case Expr::LambdaExprClass: {
const LambdaExpr *Lambda = cast<LambdaExpr>(E);
CanThrowResult CT = CT_Cannot;
- for (LambdaExpr::capture_init_iterator Cap = Lambda->capture_init_begin(),
- CapEnd = Lambda->capture_init_end();
+ for (LambdaExpr::const_capture_init_iterator
+ Cap = Lambda->capture_init_begin(),
+ CapEnd = Lambda->capture_init_end();
Cap != CapEnd; ++Cap)
CT = mergeCanThrow(CT, canThrow(*Cap));
return CT;