Index: include/clang/AST/Decl.h =================================================================== --- include/clang/AST/Decl.h +++ include/clang/AST/Decl.h @@ -3757,6 +3757,9 @@ static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K == Import; } }; +static_assert(llvm::AlignOf::Alignment >= + llvm::AlignOf::Alignment, + "Alignment sufficient for objects appended to ImportDecl"); /// \brief Represents an empty-declaration. class EmptyDecl : public Decl { Index: include/clang/AST/DeclBase.h =================================================================== --- include/clang/AST/DeclBase.h +++ 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: include/clang/AST/DeclCXX.h =================================================================== --- include/clang/AST/DeclCXX.h +++ include/clang/AST/DeclCXX.h @@ -2133,6 +2133,10 @@ /// \brief Get the initializer. Expr *getInit() const { return static_cast(Init); } }; +static_assert( + llvm::AlignOf::Alignment >= + llvm::AlignOf::Alignment, + "Alignment sufficient for objects appended to CXXCtorInitializer"); /// \brief Represents a C++ constructor within a class. /// Index: include/clang/AST/DeclFriend.h =================================================================== --- include/clang/AST/DeclFriend.h +++ include/clang/AST/DeclFriend.h @@ -172,6 +172,9 @@ friend class ASTDeclReader; friend class ASTDeclWriter; }; +static_assert(llvm::AlignOf::Alignment >= + llvm::AlignOf::Alignment, + "Alignment sufficient for objects appended to FriendDecl"); /// An iterator over the friend declarations of a class. class CXXRecordDecl::friend_iterator { Index: include/clang/AST/DeclGroup.h =================================================================== --- include/clang/AST/DeclGroup.h +++ include/clang/AST/DeclGroup.h @@ -14,6 +14,7 @@ #ifndef LLVM_CLANG_AST_DECLGROUP_H #define LLVM_CLANG_AST_DECLGROUP_H +#include "llvm/Support/AlignOf.h" #include "llvm/Support/DataTypes.h" #include @@ -51,6 +52,9 @@ return ((Decl* const*) (this+1))[i]; } }; +static_assert(llvm::AlignOf::Alignment >= + llvm::AlignOf::Alignment, + "Alignment sufficient for objects appended to DeclGroup"); class DeclGroupRef { // Note this is not a PointerIntPair because we need the address of the Index: include/clang/AST/DeclOpenMP.h =================================================================== --- include/clang/AST/DeclOpenMP.h +++ include/clang/AST/DeclOpenMP.h @@ -84,6 +84,10 @@ static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K == OMPThreadPrivate; } }; +static_assert( + llvm::AlignOf::Alignment >= + llvm::AlignOf::Alignment, + "Alignment sufficient for objects appended to OMPThreadPrivateDecl"); } // end namespace clang Index: include/clang/AST/DeclTemplate.h =================================================================== --- include/clang/AST/DeclTemplate.h +++ 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; @@ -131,6 +131,10 @@ return SourceRange(TemplateLoc, RAngleLoc); } }; +static_assert( + llvm::AlignOf::Alignment >= + llvm::AlignOf::Alignment, + "Alignment sufficient for objects appended to TemplateParameterList"); /// \brief Stores a list of template parameters for a TemplateDecl and its /// derived classes. Suitable for creating on the stack. @@ -542,27 +546,18 @@ /// 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: @@ -573,7 +568,7 @@ /// \brief Returns the number of function templates that this might /// be a specialization of. unsigned getNumTemplates() const { - return d.NumTemplates; + return NumTemplates; } /// \brief Returns the i'th template candidate. @@ -584,13 +579,12 @@ /// \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; + return NumArgs; } /// \brief Returns the nth template argument. @@ -607,6 +601,15 @@ return AngleLocs.getEnd(); } }; +static_assert( + llvm::AlignOf::Alignment >= + llvm::AlignOf::Alignment, + "Alignment sufficient for objects appended to " + "DependentFunctionTemplateSpecializationInfo"); +static_assert(llvm::AlignOf::Alignment >= + llvm::AlignOf::Alignment, + "Alignment sufficient for objects appended to " + "DependentFunctionTemplateSpecializationInfo"); /// Declaration of a redeclarable template. class RedeclarableTemplateDecl : public TemplateDecl, @@ -1290,6 +1293,10 @@ static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K == NonTypeTemplateParm; } }; +static_assert( + llvm::AlignOf::Alignment >= + llvm::AlignOf::Alignment, + "Alignment sufficient for objects appended to NonTypeTemplateParmDecl"); /// TemplateTemplateParmDecl - Declares a template template parameter, /// e.g., "T" in @@ -1455,6 +1462,10 @@ friend class ASTDeclReader; friend class ASTDeclWriter; }; +static_assert( + llvm::AlignOf::Alignment >= + llvm::AlignOf::Alignment, + "Alignment sufficient for objects appended to TemplateTemplateParmDecl"); /// \brief Represents a class template specialization, which refers to /// a class template with a given set of template arguments. Index: include/clang/AST/EvaluatedExprVisitor.h =================================================================== --- include/clang/AST/EvaluatedExprVisitor.h +++ 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: include/clang/AST/Expr.h =================================================================== --- include/clang/AST/Expr.h +++ include/clang/AST/Expr.h @@ -896,7 +896,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; @@ -1050,13 +1050,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); } @@ -1169,6 +1173,16 @@ friend class ASTStmtReader; friend class ASTStmtWriter; }; +static_assert(llvm::AlignOf::Alignment >= + llvm::AlignOf::Alignment, + "Alignment sufficient for objects appended to DeclRefExpr"); +static_assert(llvm::AlignOf::Alignment >= + llvm::AlignOf::Alignment, + "Alignment sufficient for objects appended to DeclRefExpr"); +// Code re-aligns before ASTTemplateKWAndArgsInfo +static_assert(llvm::AlignOf::Alignment >= + llvm::AlignOf::Alignment, + "Alignment sufficient for objects appended to DeclRefExpr"); /// \brief [C99 6.4.2.2] - A predefined identifier such as __func__. class PredefinedExpr : public Expr { @@ -1970,6 +1984,12 @@ return child_range(begin, begin + NumExprs); } }; +static_assert(llvm::AlignOf::Alignment >= + llvm::AlignOf::Alignment, + "Alignment sufficient for objects appended to OffsetOfExpr"); +static_assert(llvm::AlignOf::Alignment >= + llvm::AlignOf::Alignment, + "Alignment sufficient for objects appended to OffsetOfExpr"); /// UnaryExprOrTypeTraitExpr - expression with either a type or (unevaluated) /// expression operand. Used for sizeof/alignof (C99 6.5.3.4) and @@ -2300,9 +2320,10 @@ /// 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 { + public: /// 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; @@ -2312,6 +2333,7 @@ DeclAccessPair FoundDecl; }; + private: /// Base - the expression for the base pointer or structure references. In /// X.F, this is "X". Stmt *Base; @@ -2585,6 +2607,12 @@ friend class ASTReader; friend class ASTStmtWriter; }; +static_assert(llvm::AlignOf::Alignment >= + llvm::AlignOf::Alignment, + "Alignment sufficient for objects appended to MemberExpr"); +static_assert(llvm::AlignOf::Alignment >= + llvm::AlignOf::Alignment, + "Alignment sufficient for objects appended to MemberExpr"); /// CompoundLiteralExpr - [C99 6.5.2.5] /// @@ -2741,6 +2769,11 @@ // Iterators child_range children() { return child_range(&Op, &Op+1); } }; +static_assert(llvm::AlignOf::Alignment >= + llvm::AlignOf::Alignment, + "Alignment sufficient for objects appended to CastExpr"); +// (Note that the data is actually tacked onto one of its subclasses, +// but they'll inherit alignment) /// ImplicitCastExpr - Allows us to explicitly represent implicit type /// conversions, which have no direct representation in the original @@ -4266,6 +4299,10 @@ return child_range(begin, begin + NumSubExprs); } }; +static_assert( + llvm::AlignOf::Alignment >= + llvm::AlignOf::Alignment, + "Alignment sufficient for objects appended to DesignatedInitExpr"); /// \brief Represents a place-holder for an object not to be initialized by /// anything. @@ -4817,6 +4854,9 @@ return T->getStmtClass() == PseudoObjectExprClass; } }; +static_assert(llvm::AlignOf::Alignment >= + llvm::AlignOf::Alignment, + "Alignment sufficient for objects appended to PseudoObjectExpr"); /// AtomicExpr - Variadic atomic builtins: __atomic_exchange, __atomic_fetch_*, /// __atomic_load, __atomic_store, and __atomic_compare_exchange_*, for the Index: include/clang/AST/ExprCXX.h =================================================================== --- include/clang/AST/ExprCXX.h +++ include/clang/AST/ExprCXX.h @@ -940,6 +940,9 @@ friend class ASTStmtReader; friend class ASTStmtWriter; }; +static_assert(llvm::AlignOf::Alignment >= + llvm::AlignOf::Alignment, + "Alignment sufficient for objects appended to CXXDefaultArgExpr"); /// \brief A use of a default initializer in a constructor or in aggregate /// initialization. @@ -1401,25 +1404,40 @@ 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,30 +1519,52 @@ /// 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() { + return capture_init_begin() + NumCaptures; + } + /// \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; + const_capture_init_iterator capture_init_end() const { + return capture_init_begin() + NumCaptures; } - /// \brief Retrieve the set of index variables used in the capture + /// \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 @@ -1579,6 +1619,16 @@ friend class ASTStmtReader; friend class ASTStmtWriter; }; +static_assert(llvm::AlignOf::Alignment >= + llvm::AlignOf::Alignment, + "Alignment sufficient for objects appended to LambdaExpr"); +static_assert(llvm::AlignOf::Alignment >= + llvm::AlignOf::Alignment, + "Alignment sufficient for objects appended to LambdaExpr"); +// Code re-aligns before VarDecl *[] +static_assert(llvm::AlignOf::Alignment >= + llvm::AlignOf::Alignment, + "Alignment sufficient for objects appended to LambdaExpr"); /// An expression "T()" which creates a value-initialized rvalue of type /// T, which is a non-class type. See (C++98 [5.2.3p2]). @@ -2170,6 +2220,9 @@ friend class ASTStmtWriter; }; +static_assert(llvm::AlignOf::Alignment >= + llvm::AlignOf::Alignment, + "Alignment sufficient for objects appended to TypeTraitExpr"); /// \brief An Embarcadero array type trait, as used in the implementation of /// __array_rank and __array_extent. @@ -2302,7 +2355,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; @@ -2591,6 +2644,10 @@ return T->getStmtClass() == UnresolvedLookupExprClass; } }; +static_assert( + llvm::AlignOf::Alignment >= + llvm::AlignOf::Alignment, + "Alignment sufficient for objects appended to UnresolvedLookupExpr"); /// \brief A qualified reference to a name whose declaration cannot /// yet be resolved. @@ -2606,7 +2663,7 @@ /// 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; @@ -2752,6 +2809,10 @@ friend class ASTStmtReader; friend class ASTStmtWriter; }; +static_assert( + llvm::AlignOf::Alignment >= + llvm::AlignOf::Alignment, + "Alignment sufficient for objects appended to DependentScopeDeclRefExpr"); /// Represents an expression -- generally a full-expression -- that /// introduces cleanups to be run at the end of the sub-expression's @@ -2823,6 +2884,9 @@ // Iterators child_range children() { return child_range(&SubExpr, &SubExpr + 1); } }; +static_assert(llvm::AlignOf::Alignment >= + llvm::AlignOf::Alignment, + "Alignment sufficient for objects appended to ExprWithCleanups"); /// \brief Describes an explicit type conversion that uses functional /// notion but could not be resolved because one or more arguments are @@ -2943,6 +3007,10 @@ return child_range(begin, begin + NumArgs); } }; +static_assert( + llvm::AlignOf::Alignment >= + llvm::AlignOf::Alignment, + "Alignment sufficient for objects appended to CXXUnresolvedConstructExpr"); /// \brief Represents a C++ member access expression where the actual /// member referenced could not be resolved because the base @@ -2951,7 +3019,7 @@ /// 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; @@ -3190,6 +3258,10 @@ friend class ASTStmtReader; friend class ASTStmtWriter; }; +static_assert( + llvm::AlignOf::Alignment >= + llvm::AlignOf::Alignment, + "Alignment sufficient for objects appended to CXXDependentScopeMemberExpr"); /// \brief Represents a C++ member access expression for which lookup /// produced a set of overloaded functions. @@ -3206,7 +3278,7 @@ /// 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; @@ -3329,6 +3401,20 @@ return child_range(&Base, &Base + 1); } }; +static_assert( + llvm::AlignOf::Alignment >= + llvm::AlignOf::Alignment, + "Alignment sufficient for objects appended to UnresolvedMemberExpr"); + +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]). /// @@ -3451,15 +3537,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. @@ -3722,6 +3799,10 @@ child_range children() { return child_range(); } }; +static_assert( + llvm::AlignOf::Alignment >= + llvm::AlignOf::Alignment, + "Alignment sufficient for objects appended to FunctionParmPackExpr"); /// \brief Represents a prvalue temporary that is written into memory so that /// a reference can bind to it. Index: include/clang/AST/ExprObjC.h =================================================================== --- include/clang/AST/ExprObjC.h +++ include/clang/AST/ExprObjC.h @@ -201,6 +201,9 @@ friend class ASTStmtReader; }; +static_assert(llvm::AlignOf::Alignment >= + llvm::AlignOf::Alignment, + "Alignment sufficient for objects appended to ObjCArrayLiteral"); /// \brief An element in an Objective-C dictionary literal. /// @@ -231,6 +234,7 @@ /// ObjCDictionaryLiteral - AST node to represent objective-c dictionary /// literals; as in: @{@"name" : NSUserName(), @"date" : [NSDate date] }; class ObjCDictionaryLiteral : public Expr { + public: /// \brief Key/value pair used to store the key and value of a given element. /// /// Objects of this type are stored directly after the expression. @@ -251,6 +255,7 @@ unsigned NumExpansionsPlusOne; }; + private: /// \brief The number of elements in this dictionary literal. unsigned NumElements : 31; @@ -341,6 +346,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); } @@ -348,7 +355,14 @@ friend class ASTStmtReader; friend class ASTStmtWriter; }; - +static_assert( + llvm::AlignOf::Alignment >= + llvm::AlignOf::Alignment, + "Alignment sufficient for objects appended to ObjCDictionaryLiteral"); +static_assert( + llvm::AlignOf::Alignment >= + llvm::AlignOf::Alignment, + "Alignment sufficient for objects appended to ObjCDictionaryLiteral"); /// ObjCEncodeExpr, used for \@encode in Objective-C. \@encode has the same /// type and behavior as StringLiteral except that the string initializer is @@ -1394,6 +1408,15 @@ friend class ASTStmtReader; friend class ASTStmtWriter; }; +static_assert(llvm::AlignOf::Alignment >= + llvm::AlignOf::Alignment, + "Alignment sufficient for objects appended to ObjCMessageExpr"); +static_assert(llvm::AlignOf::Alignment >= + llvm::AlignOf::Alignment, + "Alignment sufficient for objects appended to ObjCMessageExpr"); +static_assert(llvm::AlignOf::Alignment >= + llvm::AlignOf::Alignment, + "Alignment sufficient for objects appended to ObjCMessageExpr"); /// ObjCIsaExpr - Represent X->isa and X.isa when X is an ObjC 'id' type. /// (similar in spirit to MemberExpr). Index: include/clang/AST/Stmt.h =================================================================== --- include/clang/AST/Stmt.h +++ include/clang/AST/Stmt.h @@ -875,7 +875,9 @@ return T->getStmtClass() == AttributedStmtClass; } }; - +static_assert(llvm::AlignOf::Alignment >= + llvm::AlignOf::Alignment, + "Alignment sufficient for objects appended to AttributedStmt"); /// IfStmt - This represents an if/then/else. /// @@ -2076,8 +2078,12 @@ /// \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 +2102,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. @@ -2161,21 +2165,37 @@ unsigned capture_size() const { return NumCaptures; } /// \brief Iterator that walks over the capture initialization arguments. - typedef Expr **capture_init_iterator; + 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; } @@ -2197,6 +2217,13 @@ friend class ASTStmtReader; }; +static_assert(llvm::AlignOf::Alignment >= + llvm::AlignOf::Alignment, + "Alignment sufficient for objects appended to CapturedStmt"); +// Code re-aligns before Capture[] +static_assert(llvm::AlignOf::Alignment >= + llvm::AlignOf::Alignment, + "Alignment sufficient for objects appended to CapturedStmt"); } // end namespace clang Index: include/clang/AST/StmtCXX.h =================================================================== --- include/clang/AST/StmtCXX.h +++ include/clang/AST/StmtCXX.h @@ -118,6 +118,9 @@ friend class ASTStmtReader; }; +static_assert(llvm::AlignOf::Alignment >= + llvm::AlignOf::Alignment, + "Alignment sufficient for objects appended to CXXTryStmt"); /// CXXForRangeStmt - This represents C++0x [stmt.ranged]'s ranged for /// statement, represented as 'for (range-declarator : range-expression)'. Index: include/clang/AST/StmtObjC.h =================================================================== --- include/clang/AST/StmtObjC.h +++ include/clang/AST/StmtObjC.h @@ -250,6 +250,9 @@ getStmts() + 1 + NumCatchStmts + HasFinally); } }; +static_assert(llvm::AlignOf::Alignment >= + llvm::AlignOf::Alignment, + "Alignment sufficient for objects appended to ObjCAtTryStmt"); /// \brief Represents Objective-C's \@synchronized statement. /// Index: include/clang/AST/TemplateBase.h =================================================================== --- include/clang/AST/TemplateBase.h +++ include/clang/AST/TemplateBase.h @@ -360,6 +360,20 @@ void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context) const; }; +static_assert( + llvm::AlignOf::Alignment >= + llvm::AlignOf::Alignment, + "Alignment sufficient for objects appended to TemplateSpecializationType"); +static_assert( + llvm::AlignOf::Alignment >= + llvm::AlignOf::Alignment, + "Alignment sufficient for objects appended to TemplateSpecializationType"); + +static_assert(llvm::AlignOf::Alignment >= + llvm::AlignOf::Alignment, + "Alignment sufficient for objects appended to " + "DependentTemplateSpecializationType"); + /// Location information for a TemplateArgument. struct TemplateArgumentLocInfo { private: @@ -604,6 +618,10 @@ void copyInto(TemplateArgumentListInfo &List) const; static std::size_t sizeFor(unsigned NumTemplateArgs); }; +static_assert( + llvm::AlignOf::Alignment >= + llvm::AlignOf::Alignment, + "Alignment sufficient for objects appended to ASTTemplateArgumentListInfo"); /// \brief Extends ASTTemplateArgumentListInfo with the source location /// information for the template keyword; this is used as part of the @@ -640,6 +658,18 @@ static std::size_t sizeFor(unsigned NumTemplateArgs); }; +static_assert( + llvm::AlignOf::Alignment >= + llvm::AlignOf::Alignment, + "Alignment sufficient for objects appended to ASTTemplateKWAndArgsInfo"); +static_assert( + llvm::AlignOf::Alignment >= + llvm::AlignOf::Alignment, + "Alignment sufficient for objects appended to ASTTemplateKWAndArgsInfo"); +static_assert( + llvm::AlignOf::Alignment >= + llvm::AlignOf::Alignment, + "Alignment sufficient for objects appended to ASTTemplateKWAndArgsInfo"); const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, const TemplateArgument &Arg); Index: include/clang/AST/TemplateName.h =================================================================== --- include/clang/AST/TemplateName.h +++ include/clang/AST/TemplateName.h @@ -108,6 +108,10 @@ iterator begin() const { return getStorage(); } iterator end() const { return getStorage() + size(); } }; +static_assert( + llvm::AlignOf::Alignment >= + llvm::AlignOf::Alignment, + "Alignment sufficient for objects appended to OverloadedTemplateStorage"); /// \brief A structure for storing an already-substituted template template /// parameter pack. Index: include/clang/AST/Type.h =================================================================== --- include/clang/AST/Type.h +++ include/clang/AST/Type.h @@ -2992,11 +2992,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); } @@ -3168,7 +3170,26 @@ param_type_iterator ArgTys, unsigned NumArgs, const ExtProtoInfo &EPI, const ASTContext &Context); }; - +static_assert(llvm::AlignOf::Alignment >= + llvm::AlignOf::Alignment, + "Alignment sufficient for objects appended to FunctionProtoType"); +// After QualType[], there can be one of 4 options: more QualType, Expr*, 2x FunctionDecl*, FunctionDecl* +static_assert(llvm::AlignOf::Alignment >= + llvm::AlignOf::Alignment, + "Alignment sufficient for objects appended to FunctionProtoType"); +static_assert(llvm::AlignOf::Alignment >= + llvm::AlignOf::Alignment, + "Alignment sufficient for objects appended to FunctionProtoType"); +// And then, after any of those options, comes bool[] +static_assert(llvm::AlignOf::Alignment >= + llvm::AlignOf::Alignment, + "Alignment sufficient for objects appended to FunctionProtoType"); +static_assert(llvm::AlignOf::Alignment >= + llvm::AlignOf::Alignment, + "Alignment sufficient for objects appended to FunctionProtoType"); +static_assert(llvm::AlignOf::Alignment >= + llvm::AlignOf::Alignment, + "Alignment sufficient for objects appended to FunctionProtoType"); /// \brief Represents the dependent type named by a dependently-scoped /// typename using declaration, e.g. @@ -3777,7 +3798,7 @@ /// TemplateArguments, followed by a QualType representing the /// non-canonical aliased type when the template is a type alias /// template. -class TemplateSpecializationType +class LLVM_ALIGNAS(/*alignof(uint64_t)*/ 8) TemplateSpecializationType : public Type, public llvm::FoldingSetNode { /// \brief The name of the template being specialized. This is /// either a TemplateName::Template (in which case it is a @@ -3900,6 +3921,9 @@ return T->getTypeClass() == TemplateSpecialization; } }; +// The static_asserts for alignment of TemplateSpecializationType are +// located after class TemplateArgument, as it is is forward declared +// here. /// \brief The injected class name of a C++ class template or class /// template partial specialization. Used to record that a type was @@ -4175,7 +4199,7 @@ /// DependentTemplateSpecializationType - Represents a template /// specialization type whose template cannot be resolved, e.g. /// A::template B -class DependentTemplateSpecializationType : +class LLVM_ALIGNAS(/*alignof(uint64_t)*/ 8) DependentTemplateSpecializationType : public TypeWithKeyword, public llvm::FoldingSetNode { /// \brief The nested name specifier containing the qualifier. @@ -4241,6 +4265,9 @@ return T->getTypeClass() == DependentTemplateSpecialization; } }; +// The static_asserts for alignment of +// DependentTemplateSpecializationType are located after class +// TemplateArgument, as it is is forward declared here. /// \brief Represents a pack expansion of types. /// @@ -4456,6 +4483,10 @@ ObjCProtocolDecl *const *protocols, unsigned NumProtocols); }; +static_assert( + llvm::AlignOf::Alignment >= + llvm::AlignOf::Alignment, + "Alignment sufficient for objects appended to ObjCObjectTypeImpl"); inline ObjCProtocolDecl **ObjCObjectType::getProtocolStorage() { return reinterpret_cast( Index: include/clang/AST/TypeLoc.h =================================================================== --- include/clang/AST/TypeLoc.h +++ include/clang/AST/TypeLoc.h @@ -199,6 +199,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: include/clang/CodeGen/CGFunctionInfo.h =================================================================== --- include/clang/CodeGen/CGFunctionInfo.h +++ include/clang/CodeGen/CGFunctionInfo.h @@ -333,11 +333,12 @@ /// CGFunctionInfo - Class to encapsulate the information about a /// function definition. class CGFunctionInfo : public llvm::FoldingSetNode { + public: struct ArgInfo { CanQualType type; ABIArgInfo info; }; - + private: /// The LLVM::CallingConv to use for this function (as specified by the /// user). unsigned CallingConvention : 8; @@ -500,6 +501,9 @@ } } }; +static_assert(llvm::AlignOf::Alignment >= + llvm::AlignOf::Alignment, + "Alignment sufficient for objects appended to CGFunctionInfo"); } // end namespace CodeGen } // end namespace clang Index: include/clang/Lex/MacroArgs.h =================================================================== --- include/clang/Lex/MacroArgs.h +++ include/clang/Lex/MacroArgs.h @@ -15,13 +15,13 @@ #define LLVM_CLANG_LEX_MACROARGS_H #include "clang/Basic/LLVM.h" +#include "clang/Lex/Token.h" #include "llvm/ADT/ArrayRef.h" #include namespace clang { class MacroInfo; class Preprocessor; - class Token; class SourceLocation; /// MacroArgs - An instance of this class captures information about @@ -121,6 +121,9 @@ /// its freelist. MacroArgs *deallocate(); }; +static_assert(llvm::AlignOf::Alignment >= + llvm::AlignOf::Alignment, + "Alignment sufficient for objects appended to MacroArgs"); } // end namespace clang Index: include/clang/Lex/MacroInfo.h =================================================================== --- include/clang/Lex/MacroInfo.h +++ include/clang/Lex/MacroInfo.h @@ -295,6 +295,9 @@ friend class Preprocessor; }; +static_assert(llvm::AlignOf::Alignment >= + llvm::AlignOf::Alignment, + "Alignment sufficient for objects appended to MacroInfo"); class DefMacroDirective; @@ -556,6 +559,9 @@ /// Get the number of macros that override this one. unsigned getNumOverridingMacros() const { return NumOverriddenBy; } }; +static_assert(llvm::AlignOf::Alignment >= + llvm::AlignOf::Alignment, + "Alignment sufficient for objects appended to ModuleMacro"); /// \brief A description of the current definition of a macro. /// Index: include/clang/Sema/AttributeList.h =================================================================== --- include/clang/Sema/AttributeList.h +++ include/clang/Sema/AttributeList.h @@ -136,10 +136,10 @@ /// Arguments, if any, are stored immediately following the object. ArgsUnion *getArgsBuffer() { - return reinterpret_cast(this+1); + return reinterpret_cast(this + 1); } ArgsUnion const *getArgsBuffer() const { - return reinterpret_cast(this+1); + return reinterpret_cast(this + 1); } enum AvailabilitySlot { @@ -468,6 +468,22 @@ /// a Spelling enumeration, the value UINT_MAX is returned. unsigned getSemanticSpelling() const; }; +static_assert(llvm::AlignOf::Alignment >= + llvm::AlignOf::Alignment, + "Alignment sufficient for objects appended to AttributeList"); +static_assert(llvm::AlignOf::Alignment >= + llvm::AlignOf::Alignment, + "Alignment sufficient for objects appended to AttributeList"); +static_assert( + llvm::AlignOf::Alignment >= + llvm::AlignOf::Alignment, + "Alignment sufficient for objects appended to AttributeList"); +static_assert(llvm::AlignOf::Alignment >= + llvm::AlignOf::Alignment, + "Alignment sufficient for objects appended to AttributeList"); +static_assert(llvm::AlignOf::Alignment >= + llvm::AlignOf::Alignment, + "Alignment sufficient for objects appended to AttributeList"); /// A factory, from which one makes pools, from which one creates /// individual attributes which are deallocated with the pool. @@ -530,6 +546,7 @@ ~AttributeFactory(); }; + class AttributePool { AttributeFactory &Factory; AttributeList *Head; Index: include/clang/Sema/CodeCompleteConsumer.h =================================================================== --- include/clang/Sema/CodeCompleteConsumer.h +++ include/clang/Sema/CodeCompleteConsumer.h @@ -494,6 +494,14 @@ /// which is mainly useful for debugging. std::string getAsString() const; }; +static_assert( + llvm::AlignOf::Alignment >= + llvm::AlignOf::Alignment, + "Alignment sufficient for objects appended to CodeCompletionString"); +static_assert( + llvm::AlignOf::Alignment >= + llvm::AlignOf::Alignment, + "Alignment sufficient for objects appended to CodeCompletionString"); /// \brief An allocator used specifically for the purpose of code completion. class CodeCompletionAllocator : public llvm::BumpPtrAllocator { Index: include/clang/Sema/ParsedTemplate.h =================================================================== --- include/clang/Sema/ParsedTemplate.h +++ include/clang/Sema/ParsedTemplate.h @@ -205,6 +205,10 @@ free(this); } }; + static_assert( + llvm::AlignOf::Alignment >= + llvm::AlignOf::Alignment, + "Alignment sufficient for objects appended to TemplateIdAnnotation"); /// Retrieves the range of the given template parameter lists. SourceRange getTemplateParamsRange(TemplateParameterList const *const *Params, Index: include/clang/Serialization/Module.h =================================================================== --- include/clang/Serialization/Module.h +++ include/clang/Serialization/Module.h @@ -206,7 +206,7 @@ llvm::BitstreamCursor InputFilesCursor; /// \brief Offsets for all of the input file entries in the AST file. - const uint64_t *InputFileOffsets; + std::vector InputFileOffsets; /// \brief The input files that have been loaded from this AST file. std::vector InputFilesLoaded; Index: lib/AST/Decl.cpp =================================================================== --- lib/AST/Decl.cpp +++ lib/AST/Decl.cpp @@ -3112,8 +3112,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, @@ -3128,8 +3128,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: lib/AST/DeclBase.cpp =================================================================== --- lib/AST/DeclBase.cpp +++ 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: lib/AST/Expr.cpp =================================================================== --- lib/AST/Expr.cpp +++ lib/AST/Expr.cpp @@ -399,10 +399,13 @@ 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 +423,10 @@ 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()); @@ -3929,7 +3934,7 @@ 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: lib/AST/ExprCXX.cpp =================================================================== --- lib/AST/ExprCXX.cpp +++ lib/AST/ExprCXX.cpp @@ -1071,14 +1071,14 @@ } ArrayRef -LambdaExpr::getCaptureInitIndexVars(capture_init_iterator Iter) const { +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,12 @@ } 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: lib/AST/Stmt.cpp =================================================================== --- lib/AST/Stmt.cpp +++ 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); @@ -2165,4 +2165,3 @@ C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *)); return new (Mem) OMPTeamsDirective(NumClauses); } - Index: lib/Basic/IdentifierTable.cpp =================================================================== --- lib/Basic/IdentifierTable.cpp +++ lib/Basic/IdentifierTable.cpp @@ -392,6 +392,11 @@ Profile(ID, keyword_begin(), getNumArgs()); } }; +static_assert( + llvm::AlignOf::Alignment >= + llvm::AlignOf::Alignment, + "Alignment sufficient for objects appended to MultiKeywordSelector"); + } // end namespace clang. unsigned Selector::getNumArgs() const { Index: lib/CodeGen/CGCleanup.h =================================================================== --- lib/CodeGen/CGCleanup.h +++ lib/CodeGen/CGCleanup.h @@ -214,9 +214,12 @@ return Scope->getKind() == Catch; } }; +static_assert(llvm::AlignOf::Alignment >= + llvm::AlignOf::Alignment, + "Alignment sufficient for objects appended to EHCatchScope"); /// 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 +399,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 @@ -440,6 +452,9 @@ return scope->getKind() == Filter; } }; +static_assert(llvm::AlignOf::Alignment >= + llvm::AlignOf::Alignment, + "Alignment sufficient for objects appended to EHFilterScope"); /// An exceptions scope which calls std::terminate if any exception /// reaches it. @@ -472,27 +487,28 @@ EHScope &operator*() const { return *get(); } iterator &operator++() { + size_t Size; switch (get()->getKind()) { case EHScope::Catch: - Ptr += EHCatchScope::getSizeForNumHandlers( + Size = EHCatchScope::getSizeForNumHandlers( static_cast(get())->getNumHandlers()); break; case EHScope::Filter: - Ptr += EHFilterScope::getSizeForNumFilters( + Size = EHFilterScope::getSizeForNumFilters( static_cast(get())->getNumFilters()); break; case EHScope::Cleanup: - Ptr += static_cast(get()) + 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 +544,7 @@ EHCatchScope &scope = cast(*begin()); InnermostEHScope = scope.getEnclosingEHScope(); - StartOfData += EHCatchScope::getSizeForNumHandlers(scope.getNumHandlers()); + deallocate(EHCatchScope::getSizeForNumHandlers(scope.getNumHandlers())); } inline void EHScopeStack::popTerminate() { @@ -536,7 +552,7 @@ EHTerminateScope &scope = cast(*begin()); InnermostEHScope = scope.getEnclosingEHScope(); - StartOfData += EHTerminateScope::getSize(); + deallocate(EHTerminateScope::getSize()); } inline EHScopeStack::iterator EHScopeStack::find(stable_iterator sp) const { Index: lib/CodeGen/CGCleanup.cpp =================================================================== --- lib/CodeGen/CGCleanup.cpp +++ 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: lib/CodeGen/CGExprCXX.cpp =================================================================== --- lib/CodeGen/CGExprCXX.cpp +++ lib/CodeGen/CGExprCXX.cpp @@ -1153,6 +1153,10 @@ EmitNewDeleteCall(CGF, OperatorDelete, FPT, DeleteArgs); } }; + static_assert( + llvm::AlignOf::Alignment >= + llvm::AlignOf::Alignment, + "Alignment sufficient for objects appended to CallDeleteDuringNew"); /// A cleanup to call the given 'operator delete' function upon /// abnormal exit from a new expression when the new expression is @@ -1212,6 +1216,10 @@ EmitNewDeleteCall(CGF, OperatorDelete, FPT, DeleteArgs); } }; + static_assert( + llvm::AlignOf::Alignment >= + llvm::AlignOf::saved_type>::Alignment, + "Alignment sufficient for objects appended to CallDeleteDuringNew"); } /// Enter a cleanup to call 'operator delete' if the initializer in a @@ -1842,7 +1850,7 @@ 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(), + for (LambdaExpr::const_capture_init_iterator i = E->capture_init_begin(), e = E->capture_init_end(); i != e; ++i, ++CurField) { // Emit initialization Index: lib/CodeGen/CGStmt.cpp =================================================================== --- lib/CodeGen/CGStmt.cpp +++ lib/CodeGen/CGStmt.cpp @@ -2123,8 +2123,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: lib/CodeGen/EHScopeStack.h =================================================================== --- lib/CodeGen/EHScopeStack.h +++ 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 less than maximum"); 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 less than maximum"); 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 less than maximum"); void *Buffer = pushCleanup(Kind, sizeof(T) + T::getExtraSize(N)); return new (Buffer) T(N, A...); } Index: lib/Lex/PPDirectives.cpp =================================================================== --- lib/Lex/PPDirectives.cpp +++ lib/Lex/PPDirectives.cpp @@ -48,8 +48,6 @@ MacroInfo *Preprocessor::AllocateDeserializedMacroInfo(SourceLocation L, unsigned SubModuleID) { - static_assert(llvm::AlignOf::Alignment >= sizeof(SubModuleID), - "alignment for MacroInfo is less than the ID"); DeserializedMacroInfoChain *MIChain = BP.Allocate(); MIChain->Next = DeserialMIChainHead; Index: lib/Sema/SemaExceptionSpec.cpp =================================================================== --- lib/Sema/SemaExceptionSpec.cpp +++ lib/Sema/SemaExceptionSpec.cpp @@ -971,7 +971,7 @@ case Expr::LambdaExprClass: { const LambdaExpr *Lambda = cast(E); CanThrowResult CT = CT_Cannot; - for (LambdaExpr::capture_init_iterator Cap = Lambda->capture_init_begin(), + for (LambdaExpr::const_capture_init_iterator Cap = Lambda->capture_init_begin(), CapEnd = Lambda->capture_init_end(); Cap != CapEnd; ++Cap) CT = mergeCanThrow(CT, canThrow(*Cap)); Index: lib/Serialization/ASTReader.cpp =================================================================== --- lib/Serialization/ASTReader.cpp +++ lib/Serialization/ASTReader.cpp @@ -2306,7 +2306,10 @@ case INPUT_FILE_OFFSETS: NumInputs = Record[0]; NumUserInputs = Record[1]; - F.InputFileOffsets = (const uint64_t *)Blob.data(); + F.InputFileOffsets.resize(NumInputs); + // Note: Blob.data may not be properly aligned, so use memcpy + // here which can deal. + memcpy(&F.InputFileOffsets[0], Blob.data(), NumInputs * sizeof(uint64_t)); F.InputFilesLoaded.resize(NumInputs); break; }