Index: cfe/trunk/include/clang/AST/DeclBase.h =================================================================== --- cfe/trunk/include/clang/AST/DeclBase.h +++ cfe/trunk/include/clang/AST/DeclBase.h @@ -70,8 +70,15 @@ /// 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::Alignment }; + /// \brief Lists the kind of concrete classes of Decl. enum Kind { #define DECL(DERIVED, BASE) DERIVED, Index: cfe/trunk/include/clang/AST/DeclTemplate.h =================================================================== --- cfe/trunk/include/clang/AST/DeclTemplate.h +++ cfe/trunk/include/clang/AST/DeclTemplate.h @@ -43,7 +43,7 @@ /// \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; @@ -542,27 +542,20 @@ /// 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(this+1); + return reinterpret_cast( + &getTemplateArgs()[NumArgs]); } public: @@ -572,9 +565,7 @@ /// \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 { @@ -584,14 +575,11 @@ /// \brief Returns the explicit template arguments that were given. const TemplateArgumentLoc *getTemplateArgs() const { - return reinterpret_cast( - &getTemplates()[getNumTemplates()]); + return reinterpret_cast(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 { Index: cfe/trunk/include/clang/AST/EvaluatedExprVisitor.h =================================================================== --- cfe/trunk/include/clang/AST/EvaluatedExprVisitor.h +++ cfe/trunk/include/clang/AST/EvaluatedExprVisitor.h @@ -88,8 +88,8 @@ 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); Index: cfe/trunk/include/clang/AST/Expr.h =================================================================== --- cfe/trunk/include/clang/AST/Expr.h +++ cfe/trunk/include/clang/AST/Expr.h @@ -897,7 +897,7 @@ /// 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; @@ -1051,13 +1051,17 @@ if (!hasTemplateKWAndArgsInfo()) return nullptr; - if (hasFoundDecl()) + if (hasFoundDecl()) { return reinterpret_cast( - &getInternalFoundDecl() + 1); + llvm::alignAddr(&getInternalFoundDecl() + 1, + llvm::alignOf())); + } - if (hasQualifier()) + if (hasQualifier()) { return reinterpret_cast( - &getInternalQualifierLoc() + 1); + llvm::alignAddr(&getInternalQualifierLoc() + 1, + llvm::alignOf())); + } return reinterpret_cast(this + 1); } @@ -2301,9 +2305,9 @@ /// 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; Index: cfe/trunk/include/clang/AST/ExprCXX.h =================================================================== --- cfe/trunk/include/clang/AST/ExprCXX.h +++ cfe/trunk/include/clang/AST/ExprCXX.h @@ -1401,25 +1401,39 @@ ExplicitResultType(false), HasArrayIndexVars(true) { getStoredStmts()[NumCaptures] = nullptr; } - - Stmt **getStoredStmts() const { - return reinterpret_cast(const_cast(this) + 1); + + Stmt **getStoredStmts() { return reinterpret_cast(this + 1); } + + Stmt *const *getStoredStmts() const { + return reinterpret_cast(this + 1); } - + /// \brief Retrieve the mapping from captures to the first array index /// variable. - unsigned *getArrayIndexStarts() const { + unsigned *getArrayIndexStarts() { return reinterpret_cast(getStoredStmts() + NumCaptures + 1); } + const unsigned *getArrayIndexStarts() const { + return reinterpret_cast(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()); return reinterpret_cast( reinterpret_cast(getArrayIndexStarts()) + ArrayIndexSize); } + VarDecl *const *getArrayIndexVars() const { + unsigned ArrayIndexSize = llvm::RoundUpToAlignment( + sizeof(unsigned) * (NumCaptures + 1), llvm::alignOf()); + return reinterpret_cast( + reinterpret_cast(getArrayIndexStarts()) + ArrayIndexSize); + } + public: /// \brief Construct a new lambda expression. static LambdaExpr *Create(const ASTContext &C, @@ -1501,31 +1515,54 @@ /// 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_inits() const { + llvm::iterator_range capture_inits() { return llvm::iterator_range(capture_init_begin(), capture_init_end()); } + /// \brief Retrieve the initialization expressions for this lambda's captures. + llvm::iterator_range capture_inits() const { + return llvm::iterator_range( + 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(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(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 getCaptureInitIndexVars(capture_init_iterator Iter) const; - + ArrayRef + 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 ([...]). @@ -2302,7 +2339,7 @@ /// \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; @@ -2606,7 +2643,8 @@ /// qualifier (X::) 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; @@ -2951,7 +2989,8 @@ /// 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; @@ -3206,7 +3245,8 @@ /// 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; @@ -3330,6 +3370,17 @@ } }; +inline ASTTemplateKWAndArgsInfo *OverloadExpr::getTemplateKWAndArgsInfo() { + if (!HasTemplateKWAndArgsInfo) + return nullptr; + if (isa(this)) + return reinterpret_cast( + cast(this) + 1); + else + return reinterpret_cast( + cast(this) + 1); +} + /// \brief Represents a C++11 noexcept expression (C++ [expr.unary.noexcept]). /// /// The noexcept expression tests whether a given expression might throw. Its @@ -3451,15 +3502,6 @@ } }; -inline ASTTemplateKWAndArgsInfo *OverloadExpr::getTemplateKWAndArgsInfo() { - if (!HasTemplateKWAndArgsInfo) return nullptr; - if (isa(this)) - return reinterpret_cast - (cast(this) + 1); - else - return reinterpret_cast - (cast(this) + 1); -} /// \brief Represents an expression that computes the length of a parameter /// pack. Index: cfe/trunk/include/clang/AST/ExprObjC.h =================================================================== --- cfe/trunk/include/clang/AST/ExprObjC.h +++ cfe/trunk/include/clang/AST/ExprObjC.h @@ -341,6 +341,8 @@ 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(this + 1), reinterpret_cast(this + 1) + NumElements * 2); } Index: cfe/trunk/include/clang/AST/Stmt.h =================================================================== --- cfe/trunk/include/clang/AST/Stmt.h +++ cfe/trunk/include/clang/AST/Stmt.h @@ -2076,8 +2076,10 @@ /// \brief Construct an empty captured statement. CapturedStmt(EmptyShell Empty, unsigned NumCaptures); - Stmt **getStoredStmts() const { - return reinterpret_cast(const_cast(this) + 1); + Stmt **getStoredStmts() { return reinterpret_cast(this + 1); } + + Stmt *const *getStoredStmts() const { + return reinterpret_cast(this + 1); } Capture *getStoredCaptures() const; @@ -2096,14 +2098,12 @@ /// \brief Retrieve the statement being captured. Stmt *getCapturedStmt() { return getStoredStmts()[NumCaptures]; } - const Stmt *getCapturedStmt() const { - return const_cast(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(this)->getCapturedDecl(); + return CapDeclAndKind.getPointer(); } /// \brief Set the outlined function declaration. @@ -2164,18 +2164,36 @@ typedef Expr **capture_init_iterator; typedef llvm::iterator_range 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_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(getStoredStmts()); } + const_capture_init_iterator capture_init_begin() const { + return reinterpret_cast(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; } Index: cfe/trunk/include/clang/AST/Type.h =================================================================== --- cfe/trunk/include/clang/AST/Type.h +++ cfe/trunk/include/clang/AST/Type.h @@ -3118,11 +3118,13 @@ assert(hasAnyConsumedParams()); // Find the end of the exceptions. - Expr *const *eh_end = reinterpret_cast(param_type_end()); - if (getExceptionSpecType() != EST_ComputedNoexcept) - eh_end += NumExceptions; - else + Expr *const *eh_end = reinterpret_cast(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(eh_end); } @@ -3295,7 +3297,6 @@ const ExtProtoInfo &EPI, const ASTContext &Context); }; - /// \brief Represents the dependent type named by a dependently-scoped /// typename using declaration, e.g. /// using typename Base::foo; @@ -3936,8 +3937,9 @@ /// 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 @@ -4328,8 +4330,9 @@ /// Represents a template specialization type whose template cannot be /// resolved, e.g. /// A::template B -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; Index: cfe/trunk/include/clang/AST/TypeLoc.h =================================================================== --- cfe/trunk/include/clang/AST/TypeLoc.h +++ cfe/trunk/include/clang/AST/TypeLoc.h @@ -206,6 +206,7 @@ /// \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(static_cast(this + 1))); } Index: cfe/trunk/include/clang/Sema/AttributeList.h =================================================================== --- cfe/trunk/include/clang/Sema/AttributeList.h +++ cfe/trunk/include/clang/Sema/AttributeList.h @@ -137,11 +137,9 @@ AttributeList *NextInPool; /// Arguments, if any, are stored immediately following the object. - ArgsUnion *getArgsBuffer() { - return reinterpret_cast(this+1); - } + ArgsUnion *getArgsBuffer() { return reinterpret_cast(this + 1); } ArgsUnion const *getArgsBuffer() const { - return reinterpret_cast(this+1); + return reinterpret_cast(this + 1); } enum AvailabilitySlot { Index: cfe/trunk/lib/AST/Decl.cpp =================================================================== --- cfe/trunk/lib/AST/Decl.cpp +++ cfe/trunk/lib/AST/Decl.cpp @@ -3116,8 +3116,8 @@ 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, @@ -3132,8 +3132,8 @@ static_assert(sizeof(*this) % llvm::AlignOf::Alignment == 0, "Trailing data is unaligned!"); - d.NumTemplates = Ts.size(); - d.NumArgs = TArgs.size(); + NumTemplates = Ts.size(); + NumArgs = TArgs.size(); FunctionTemplateDecl **TsArray = const_cast(getTemplates()); Index: cfe/trunk/lib/AST/DeclBase.cpp =================================================================== --- cfe/trunk/lib/AST/DeclBase.cpp +++ cfe/trunk/lib/AST/DeclBase.cpp @@ -45,10 +45,19 @@ getASTContext().getExternalSource()->updateOutOfDateIdentifier(II); } +#define DECL(DERIVED, BASE) \ + static_assert(Decl::DeclObjAlignment >= \ + llvm::AlignOf::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; @@ -69,7 +78,13 @@ // 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( + ::operator new(ExtraAlign + sizeof(Module *) + Size + Extra, Ctx)); + Buffer += ExtraAlign; return new (Buffer) Module*(nullptr) + 1; } return ::operator new(Size + Extra, Ctx); Index: cfe/trunk/lib/AST/Expr.cpp =================================================================== --- cfe/trunk/lib/AST/Expr.cpp +++ cfe/trunk/lib/AST/Expr.cpp @@ -399,10 +399,15 @@ Size += sizeof(NestedNameSpecifierLoc); if (FoundD) Size += sizeof(NamedDecl *); - if (TemplateArgs) + if (TemplateArgs) { + Size = llvm::RoundUpToAlignment(Size, + llvm::alignOf()); Size += ASTTemplateKWAndArgsInfo::sizeFor(TemplateArgs->size()); - else if (TemplateKWLoc.isValid()) + } else if (TemplateKWLoc.isValid()) { + Size = llvm::RoundUpToAlignment(Size, + llvm::alignOf()); Size += ASTTemplateKWAndArgsInfo::sizeFor(0); + } void *Mem = Context.Allocate(Size, llvm::alignOf()); return new (Mem) DeclRefExpr(Context, QualifierLoc, TemplateKWLoc, D, @@ -420,8 +425,11 @@ Size += sizeof(NestedNameSpecifierLoc); if (HasFoundDecl) Size += sizeof(NamedDecl *); - if (HasTemplateKWAndArgsInfo) + if (HasTemplateKWAndArgsInfo) { + Size = llvm::RoundUpToAlignment(Size, + llvm::alignOf()); Size += ASTTemplateKWAndArgsInfo::sizeFor(NumTemplateArgs); + } void *Mem = Context.Allocate(Size, llvm::alignOf()); return new (Mem) DeclRefExpr(EmptyShell()); @@ -3939,7 +3947,8 @@ 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()); return new (Mem) DesignatedInitExpr(C, C.VoidTy, NumDesignators, Designators, ColonOrEqualLoc, UsesColonSyntax, IndexExprs, Init); Index: cfe/trunk/lib/AST/ExprCXX.cpp =================================================================== --- cfe/trunk/lib/AST/ExprCXX.cpp +++ cfe/trunk/lib/AST/ExprCXX.cpp @@ -1070,15 +1070,15 @@ return capture_range(implicit_capture_begin(), implicit_capture_end()); } -ArrayRef -LambdaExpr::getCaptureInitIndexVars(capture_init_iterator Iter) const { +ArrayRef +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]); } @@ -1099,9 +1099,13 @@ } 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(&getStoredStmts()[NumCaptures]) = + getCallOperator()->getBody(); + return reinterpret_cast(getStoredStmts()[NumCaptures]); } Index: cfe/trunk/lib/AST/Stmt.cpp =================================================================== --- cfe/trunk/lib/AST/Stmt.cpp +++ cfe/trunk/lib/AST/Stmt.cpp @@ -822,7 +822,7 @@ CXXTryStmt *CXXTryStmt::Create(const ASTContext &C, SourceLocation tryLoc, Stmt *tryBlock, ArrayRef 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()); return new (Mem) CXXTryStmt(tryLoc, tryBlock, handlers); @@ -831,7 +831,7 @@ 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()); return new (Mem) CXXTryStmt(Empty, numHandlers); @@ -2250,4 +2250,3 @@ C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *)); return new (Mem) OMPTeamsDirective(NumClauses); } - Index: cfe/trunk/lib/CodeGen/CGCleanup.h =================================================================== --- cfe/trunk/lib/CodeGen/CGCleanup.h +++ cfe/trunk/lib/CodeGen/CGCleanup.h @@ -216,7 +216,7 @@ }; /// 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; @@ -396,6 +396,15 @@ 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::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 @@ -472,27 +481,27 @@ EHScope &operator*() const { return *get(); } iterator &operator++() { + size_t Size; switch (get()->getKind()) { case EHScope::Catch: - Ptr += EHCatchScope::getSizeForNumHandlers( - static_cast(get())->getNumHandlers()); + Size = EHCatchScope::getSizeForNumHandlers( + static_cast(get())->getNumHandlers()); break; case EHScope::Filter: - Ptr += EHFilterScope::getSizeForNumFilters( - static_cast(get())->getNumFilters()); + Size = EHFilterScope::getSizeForNumFilters( + static_cast(get())->getNumFilters()); break; case EHScope::Cleanup: - Ptr += static_cast(get()) - ->getAllocatedSize(); + Size = static_cast(get())->getAllocatedSize(); break; case EHScope::Terminate: - Ptr += EHTerminateScope::getSize(); + Size = EHTerminateScope::getSize(); break; } - + Ptr += llvm::RoundUpToAlignment(Size, ScopeStackAlignment); return *this; } @@ -528,7 +537,7 @@ EHCatchScope &scope = cast(*begin()); InnermostEHScope = scope.getEnclosingEHScope(); - StartOfData += EHCatchScope::getSizeForNumHandlers(scope.getNumHandlers()); + deallocate(EHCatchScope::getSizeForNumHandlers(scope.getNumHandlers())); } inline void EHScopeStack::popTerminate() { @@ -536,7 +545,7 @@ EHTerminateScope &scope = cast(*begin()); InnermostEHScope = scope.getEnclosingEHScope(); - StartOfData += EHTerminateScope::getSize(); + deallocate(EHTerminateScope::getSize()); } inline EHScopeStack::iterator EHScopeStack::find(stable_iterator sp) const { Index: cfe/trunk/lib/CodeGen/CGCleanup.cpp =================================================================== --- cfe/trunk/lib/CodeGen/CGCleanup.cpp +++ cfe/trunk/lib/CodeGen/CGCleanup.cpp @@ -96,6 +96,7 @@ /// 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; @@ -125,6 +126,10 @@ 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++) { @@ -166,7 +171,6 @@ 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; @@ -194,7 +198,7 @@ EHCleanupScope &Cleanup = cast(*begin()); InnermostNormalCleanup = Cleanup.getEnclosingNormalCleanup(); InnermostEHScope = Cleanup.getEnclosingEHScope(); - StartOfData += Cleanup.getAllocatedSize(); + deallocate(Cleanup.getAllocatedSize()); // Destroy the cleanup. Cleanup.Destroy(); @@ -224,7 +228,7 @@ assert(!empty() && "popping exception stack when not empty"); EHFilterScope &filter = cast(*begin()); - StartOfData += EHFilterScope::getSizeForNumFilters(filter.getNumFilters()); + deallocate(EHFilterScope::getSizeForNumFilters(filter.getNumFilters())); InnermostEHScope = filter.getEnclosingEHScope(); } Index: cfe/trunk/lib/CodeGen/CGExprCXX.cpp =================================================================== --- cfe/trunk/lib/CodeGen/CGExprCXX.cpp +++ cfe/trunk/lib/CodeGen/CGExprCXX.cpp @@ -1844,8 +1844,8 @@ 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); Index: cfe/trunk/lib/CodeGen/CGStmt.cpp =================================================================== --- cfe/trunk/lib/CodeGen/CGStmt.cpp +++ cfe/trunk/lib/CodeGen/CGStmt.cpp @@ -2156,8 +2156,8 @@ 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()) { Index: cfe/trunk/lib/CodeGen/EHScopeStack.h =================================================================== --- cfe/trunk/lib/CodeGen/EHScopeStack.h +++ cfe/trunk/lib/CodeGen/EHScopeStack.h @@ -96,6 +96,8 @@ /// and catch blocks. class EHScopeStack { public: + enum { ScopeStackAlignment = llvm::AlignOf::Alignment }; + /// A saved depth on the scope stack. This is necessary because /// pushing scopes onto the stack invalidates iterators. class stable_iterator { @@ -248,6 +250,7 @@ SmallVector BranchFixups; char *allocate(size_t Size); + void deallocate(size_t Size); void *pushCleanup(CleanupKind K, size_t DataSize); @@ -259,6 +262,8 @@ /// Push a lazily-created cleanup on the stack. template void pushCleanup(CleanupKind Kind, As... A) { + static_assert(llvm::AlignOf::Alignment <= ScopeStackAlignment, + "Cleanup's alignment is too large."); void *Buffer = pushCleanup(Kind, sizeof(T)); Cleanup *Obj = new (Buffer) T(A...); (void) Obj; @@ -267,6 +272,8 @@ /// Push a lazily-created cleanup on the stack. Tuple version. template void pushCleanupTuple(CleanupKind Kind, std::tuple A) { + static_assert(llvm::AlignOf::Alignment <= ScopeStackAlignment, + "Cleanup's alignment is too large."); void *Buffer = pushCleanup(Kind, sizeof(T)); Cleanup *Obj = new (Buffer) T(std::move(A)); (void) Obj; @@ -287,6 +294,8 @@ /// stack is modified. template T *pushCleanupWithExtra(CleanupKind Kind, size_t N, As... A) { + static_assert(llvm::AlignOf::Alignment <= ScopeStackAlignment, + "Cleanup's alignment is too large."); void *Buffer = pushCleanup(Kind, sizeof(T) + T::getExtraSize(N)); return new (Buffer) T(N, A...); } Index: cfe/trunk/lib/Sema/SemaExceptionSpec.cpp =================================================================== --- cfe/trunk/lib/Sema/SemaExceptionSpec.cpp +++ cfe/trunk/lib/Sema/SemaExceptionSpec.cpp @@ -973,8 +973,9 @@ case Expr::LambdaExprClass: { const LambdaExpr *Lambda = cast(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;