Adds static_asserts to ensure alignment of concatenated objects is
correct, and fixes them where they are not.
Some const-correctness changes snuck in here too, since they were in the
area of code I was modifying.
This seems to make Clang actually work without Bus Error on 32bit
sparc.
http://reviews.llvm.org/D10272
Files:
include/clang/AST/Decl.h
include/clang/AST/DeclBase.h
include/clang/AST/DeclCXX.h
include/clang/AST/DeclFriend.h
include/clang/AST/DeclGroup.h
include/clang/AST/DeclOpenMP.h
include/clang/AST/DeclTemplate.h
include/clang/AST/Expr.h
include/clang/AST/ExprCXX.h
include/clang/AST/ExprObjC.h
include/clang/AST/Stmt.h
include/clang/AST/StmtCXX.h
include/clang/AST/StmtObjC.h
include/clang/AST/TemplateBase.h
include/clang/AST/TemplateName.h
include/clang/AST/Type.h
include/clang/AST/TypeLoc.h
include/clang/CodeGen/CGFunctionInfo.h
include/clang/Lex/MacroArgs.h
include/clang/Lex/MacroInfo.h
include/clang/Sema/AttributeList.h
include/clang/Sema/CodeCompleteConsumer.h
include/clang/Sema/ParsedTemplate.h
include/clang/Serialization/Module.h
lib/AST/Decl.cpp
lib/AST/DeclBase.cpp
lib/AST/Expr.cpp
lib/AST/ExprCXX.cpp
lib/AST/Stmt.cpp
lib/Basic/IdentifierTable.cpp
lib/CodeGen/CGCleanup.cpp
lib/CodeGen/CGCleanup.h
lib/CodeGen/CGExprCXX.cpp
lib/CodeGen/CGStmt.cpp
lib/CodeGen/EHScopeStack.h
lib/Lex/PPDirectives.cpp
lib/Sema/SemaExceptionSpec.cpp
lib/Serialization/ASTReader.cpp
EMAIL PREFERENCES
http://reviews.llvm.org/settings/panel/emailpreferences/
Index: include/clang/AST/Decl.h
===================================================================
--- include/clang/AST/Decl.h
+++ include/clang/AST/Decl.h
@@ -3753,6 +3753,10 @@
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == Import; }
};
+// Assert objects tacked on the end of ImportDecl won't be misaligned
+static_assert(llvm::AlignOf<ImportDecl>::Alignment >=
+ llvm::AlignOf<SourceLocation>::Alignment,
+ "");
/// \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,6 +70,9 @@
/// 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
+/// for all subclasses is asserted in DeclBase.cpp.
class Decl {
public:
/// \brief Lists the kind of concrete classes of Decl.
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<Expr*>(Init); }
};
+// Assert objects tacked on the end of CXXCtorInitializer won't be misaligned
+static_assert(llvm::AlignOf<CXXCtorInitializer>::Alignment >=
+ llvm::AlignOf<VarDecl *>::Alignment,
+ "");
/// \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,10 @@
friend class ASTDeclReader;
friend class ASTDeclWriter;
};
+// Assert objects tacked on the end of FriendDecl won't be misaligned
+static_assert(llvm::AlignOf<FriendDecl>::Alignment >=
+ llvm::AlignOf<TemplateParameterList *>::Alignment,
+ "");
/// 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 <cassert>
@@ -51,6 +52,10 @@
return ((Decl* const*) (this+1))[i];
}
};
+// Assert objects tacked on the end of DeclGroup won't be misaligned
+static_assert(llvm::AlignOf<DeclGroup>::Alignment >=
+ llvm::AlignOf<Decl *>::Alignment,
+ "");
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; }
};
+// Assert objects tacked on the end of OMPThreadPrivateDecl won't be misaligned
+static_assert(llvm::AlignOf<OMPThreadPrivateDecl>::Alignment >=
+ llvm::AlignOf<Expr *>::Alignment,
+ "");
} // 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);
}
};
+// Assert objects tacked on the end of TemplateParameterList won't be misaligned
+static_assert(llvm::AlignOf<TemplateParameterList>::Alignment >=
+ llvm::AlignOf<NamedDecl *>::Alignment,
+ "");
/// \brief Stores a list of template parameters for a TemplateDecl and its
/// derived classes. Suitable for creating on the stack.
@@ -460,27 +464,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<FunctionTemplateDecl*const*>(this+1);
+ return reinterpret_cast<FunctionTemplateDecl *const *>(
+ &getTemplateArgs()[NumArgs]);
}
public:
@@ -490,9 +487,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 {
@@ -502,14 +497,11 @@
/// \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 {
@@ -525,6 +517,15 @@
return AngleLocs.getEnd();
}
};
+// Assert objects tacked on the end of
+// DependentFunctionTemplateSpecializationInfo won't be misaligned.
+static_assert(
+ llvm::AlignOf<DependentFunctionTemplateSpecializationInfo>::Alignment >=
+ llvm::AlignOf<TemplateArgumentLoc>::Alignment,
+ "");
+static_assert(llvm::AlignOf<TemplateArgumentLoc>::Alignment >=
+ llvm::AlignOf<FunctionTemplateDecl *>::Alignment,
+ "");
/// Declaration of a redeclarable template.
class RedeclarableTemplateDecl : public TemplateDecl,
@@ -1204,6 +1205,11 @@
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == NonTypeTemplateParm; }
};
+// Assert objects tacked on the end of NonTypeTemplateParmDecl won't be
+// misaligned
+static_assert(llvm::AlignOf<NonTypeTemplateParmDecl>::Alignment >=
+ llvm::AlignOf<void *>::Alignment,
+ "");
/// TemplateTemplateParmDecl - Declares a template template parameter,
/// e.g., "T" in
@@ -1370,6 +1376,11 @@
friend class ASTDeclReader;
friend class ASTDeclWriter;
};
+// Assert objects tacked on the end of TemplateTemplateParmDecl won't be
+// misaligned
+static_assert(llvm::AlignOf<TemplateTemplateParmDecl>::Alignment >=
+ llvm::AlignOf<TemplateParameterList *>::Alignment,
+ "");
/// \brief Represents a class template specialization, which refers to
/// a class template with a given set of template arguments.
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<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);
}
@@ -1169,6 +1173,17 @@
friend class ASTStmtReader;
friend class ASTStmtWriter;
};
+// Assert objects tacked on the end of DeclRefExpr won't be misaligned.
+static_assert(llvm::AlignOf<DeclRefExpr>::Alignment >=
+ llvm::AlignOf<NestedNameSpecifierLoc>::Alignment,
+ "");
+static_assert(llvm::AlignOf<NestedNameSpecifierLoc>::Alignment >=
+ llvm::AlignOf<NamedDecl *>::Alignment,
+ "");
+// Code re-aligns before ASTTemplateKWAndArgsInfo
+static_assert(llvm::AlignOf<DeclRefExpr>::Alignment >=
+ llvm::AlignOf<ASTTemplateKWAndArgsInfo>::Alignment,
+ "");
/// \brief [C99 6.4.2.2] - A predefined identifier such as __func__.
class PredefinedExpr : public Expr {
@@ -1970,6 +1985,13 @@
return child_range(begin, begin + NumExprs);
}
};
+// Assert objects tacked on the end of OffsetOfExpr won't be misaligned
+static_assert(llvm::AlignOf<OffsetOfExpr>::Alignment >=
+ llvm::AlignOf<OffsetOfExpr::OffsetOfNode *>::Alignment,
+ "");
+static_assert(llvm::AlignOf<OffsetOfExpr::OffsetOfNode>::Alignment >=
+ llvm::AlignOf<Expr *>::Alignment,
+ "");
/// UnaryExprOrTypeTraitExpr - expression with either a type or (unevaluated)
/// expression operand. Used for sizeof/alignof (C99 6.5.3.4) and
@@ -2300,9 +2322,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 +2335,7 @@
DeclAccessPair FoundDecl;
};
+private:
/// Base - the expression for the base pointer or structure references. In
/// X.F, this is "X".
Stmt *Base;
@@ -2585,6 +2609,13 @@
friend class ASTReader;
friend class ASTStmtWriter;
};
+// Assert objects tacked on the end of MemberExpr won't be misaligned
+static_assert(llvm::AlignOf<MemberExpr>::Alignment >=
+ llvm::AlignOf<MemberExpr::MemberNameQualifier>::Alignment,
+ "");
+static_assert(llvm::AlignOf<MemberExpr::MemberNameQualifier>::Alignment >=
+ llvm::AlignOf<ASTTemplateKWAndArgsInfo>::Alignment,
+ "");
/// CompoundLiteralExpr - [C99 6.5.2.5]
///
@@ -2741,6 +2772,12 @@
// Iterators
child_range children() { return child_range(&Op, &Op+1); }
};
+// Assert objects tacked on the end of CastExpr won't be misaligned
+static_assert(llvm::AlignOf<CastExpr>::Alignment >=
+ llvm::AlignOf<CXXBaseSpecifier *>::Alignment,
+ "");
+// (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 +4303,10 @@
return child_range(begin, begin + NumSubExprs);
}
};
+// Assert objects tacked on the end of DesignatedInitExpr won't be misaligned
+static_assert(llvm::AlignOf<DesignatedInitExpr>::Alignment >=
+ llvm::AlignOf<Stmt *>::Alignment,
+ "");
/// \brief Represents an implicitly-generated value initialization of
/// an object of a given type.
@@ -4743,6 +4784,10 @@
return T->getStmtClass() == PseudoObjectExprClass;
}
};
+// Assert objects tacked on the end of PseudoObjectExpr won't be misaligned
+static_assert(llvm::AlignOf<PseudoObjectExpr>::Alignment >=
+ llvm::AlignOf<Expr *>::Alignment,
+ "");
/// 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,10 @@
friend class ASTStmtReader;
friend class ASTStmtWriter;
};
+// Assert objects tacked on the end of CXXDefaultArgExpr won't be misaligned
+static_assert(llvm::AlignOf<CXXDefaultArgExpr>::Alignment >=
+ llvm::AlignOf<Expr *>::Alignment,
+ "");
/// \brief A use of a default initializer in a constructor or in aggregate
/// initialization.
@@ -1401,25 +1405,39 @@
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,
@@ -1501,31 +1519,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_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 ([...]).
@@ -1579,6 +1620,17 @@
friend class ASTStmtReader;
friend class ASTStmtWriter;
};
+// Assert objects tacked on the end of LambdaExpr won't be misaligned
+static_assert(llvm::AlignOf<LambdaExpr>::Alignment >=
+ llvm::AlignOf<Stmt *>::Alignment,
+ "");
+static_assert(llvm::AlignOf<Stmt *>::Alignment >=
+ llvm::AlignOf<unsigned>::Alignment,
+ "");
+// Code re-aligns before VarDecl *[]
+static_assert(llvm::AlignOf<LambdaExpr>::Alignment >=
+ llvm::AlignOf<VarDecl *>::Alignment,
+ "");
/// 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 +2222,10 @@
friend class ASTStmtWriter;
};
+// Assert objects tacked on the end of TypeTraitExpr won't be misaligned
+static_assert(llvm::AlignOf<TypeTraitExpr>::Alignment >=
+ llvm::AlignOf<TypeSourceInfo *>::Alignment,
+ "");
/// \brief An Embarcadero array type trait, as used in the implementation of
/// __array_rank and __array_extent.
@@ -2302,7 +2358,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 +2647,10 @@
return T->getStmtClass() == UnresolvedLookupExprClass;
}
};
+// Assert objects tacked on the end of UnresolvedLookupExpr won't be misaligned
+static_assert(llvm::AlignOf<UnresolvedLookupExpr>::Alignment >=
+ llvm::AlignOf<ASTTemplateKWAndArgsInfo>::Alignment,
+ "");
/// \brief A qualified reference to a name whose declaration cannot
/// yet be resolved.
@@ -2606,7 +2666,8 @@
/// 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;
@@ -2752,6 +2813,11 @@
friend class ASTStmtReader;
friend class ASTStmtWriter;
};
+// Assert objects tacked on the end of DependentScopeDeclRefExpr won't be
+// misaligned
+static_assert(llvm::AlignOf<DependentScopeDeclRefExpr>::Alignment >=
+ llvm::AlignOf<ASTTemplateKWAndArgsInfo>::Alignment,
+ "");
/// Represents an expression -- generally a full-expression -- that
/// introduces cleanups to be run at the end of the sub-expression's
@@ -2823,6 +2889,10 @@
// Iterators
child_range children() { return child_range(&SubExpr, &SubExpr + 1); }
};
+// Assert objects tacked on the end of ExprWithCleanups won't be misaligned
+static_assert(llvm::AlignOf<ExprWithCleanups>::Alignment >=
+ llvm::AlignOf<ExprWithCleanups::CleanupObject>::Alignment,
+ "");
/// \brief Describes an explicit type conversion that uses functional
/// notion but could not be resolved because one or more arguments are
@@ -2943,15 +3013,21 @@
return child_range(begin, begin + NumArgs);
}
};
+// Assert objects tacked on the end of CXXUnresolvedConstructExpr won't be
+// misaligned
+static_assert(llvm::AlignOf<CXXUnresolvedConstructExpr>::Alignment >=
+ llvm::AlignOf<Expr *>::Alignment,
+ "");
/// \brief Represents a C++ member access expression where the actual
/// member referenced could not be resolved because the base
/// expression or the member name was dependent.
///
/// 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 +3266,11 @@
friend class ASTStmtReader;
friend class ASTStmtWriter;
};
+// Assert objects tacked on the end of CXXDependentScopeMemberExpr won't be
+// misaligned
+static_assert(llvm::AlignOf<CXXDependentScopeMemberExpr>::Alignment >=
+ llvm::AlignOf<ASTTemplateKWAndArgsInfo>::Alignment,
+ "");
/// \brief Represents a C++ member access expression for which lookup
/// produced a set of overloaded functions.
@@ -3206,7 +3287,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;
@@ -3329,6 +3411,21 @@
return child_range(&Base, &Base + 1);
}
};
+// Assert objects tacked on the end of UnresolvedMemberExpr won't be misaligned
+static_assert(llvm::AlignOf<UnresolvedMemberExpr>::Alignment >=
+ llvm::AlignOf<ASTTemplateKWAndArgsInfo>::Alignment,
+ "");
+
+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]).
///
@@ -3451,15 +3548,6 @@
}
};
-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.
@@ -3722,6 +3810,10 @@
child_range children() { return child_range(); }
};
+// Assert objects tacked on the end of FunctionParmPackExpr won't be misaligned
+static_assert(llvm::AlignOf<FunctionParmPackExpr>::Alignment >=
+ llvm::AlignOf<ParmVarDecl *>::Alignment,
+ "");
/// \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,10 @@
friend class ASTStmtReader;
};
+// Assert objects tacked on the end of ObjCArrayLiteral won't be misaligned
+static_assert(llvm::AlignOf<ObjCArrayLiteral>::Alignment >=
+ llvm::AlignOf<Expr *>::Alignment,
+ "");
/// \brief An element in an Objective-C dictionary literal.
///
@@ -231,6 +235,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 +256,7 @@
unsigned NumExpansionsPlusOne;
};
+private:
/// \brief The number of elements in this dictionary literal.
unsigned NumElements : 31;
@@ -341,14 +347,22 @@
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, "");
return child_range(reinterpret_cast<Stmt **>(this + 1),
reinterpret_cast<Stmt **>(this + 1) + NumElements * 2);
}
friend class ASTStmtReader;
friend class ASTStmtWriter;
};
-
+// Assert objects tacked on the end of ObjCDictionaryLiteral won't be misaligned
+static_assert(llvm::AlignOf<ObjCDictionaryLiteral>::Alignment >=
+ llvm::AlignOf<ObjCDictionaryLiteral::KeyValuePair>::Alignment,
+ "");
+static_assert(
+ llvm::AlignOf<ObjCDictionaryLiteral::KeyValuePair>::Alignment >=
+ llvm::AlignOf<ObjCDictionaryLiteral::ExpansionData>::Alignment,
+ "");
/// 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,16 @@
friend class ASTStmtReader;
friend class ASTStmtWriter;
};
+// Assert objects tacked on the end of ObjCMessageExpr won't be misaligned
+static_assert(llvm::AlignOf<ObjCMessageExpr>::Alignment >=
+ llvm::AlignOf<void *>::Alignment,
+ "");
+static_assert(llvm::AlignOf<void *>::Alignment >=
+ llvm::AlignOf<Expr *>::Alignment,
+ "");
+static_assert(llvm::AlignOf<Expr *>::Alignment >=
+ llvm::AlignOf<SourceLocation>::Alignment,
+ "");
/// 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,10 @@
return T->getStmtClass() == AttributedStmtClass;
}
};
-
+// Assert objects tacked on the end of AttributedStmt won't be misaligned
+static_assert(llvm::AlignOf<AttributedStmt>::Alignment >=
+ llvm::AlignOf<Attr *>::Alignment,
+ "");
/// IfStmt - This represents an if/then/else.
///
@@ -2076,8 +2079,10 @@
/// \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;
@@ -2096,14 +2101,12 @@
/// \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.
@@ -2164,18 +2167,36 @@
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;
}
@@ -2197,6 +2218,14 @@
friend class ASTStmtReader;
};
+// Assert objects tacked on the end of CapturedStmt won't be misaligned
+static_assert(llvm::AlignOf<CapturedStmt>::Alignment >=
+ llvm::AlignOf<Stmt *>::Alignment,
+ "");
+// Code re-aligns before Capture[]
+static_assert(llvm::AlignOf<CapturedStmt>::Alignment >=
+ llvm::AlignOf<CapturedStmt::Capture>::Alignment,
+ "");
} // end namespace clang
Index: include/clang/AST/StmtCXX.h
===================================================================
--- include/clang/AST/StmtCXX.h
+++ include/clang/AST/StmtCXX.h
@@ -118,6 +118,10 @@
friend class ASTStmtReader;
};
+// Assert objects tacked on the end of CXXTryStmt won't be misaligned
+static_assert(llvm::AlignOf<CXXTryStmt>::Alignment >=
+ llvm::AlignOf<Stmt *>::Alignment,
+ "");
/// 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,10 @@
getStmts() + 1 + NumCatchStmts + HasFinally);
}
};
+// Assert objects tacked on the end of ObjCAtTryStmt won't be misaligned
+static_assert(llvm::AlignOf<ObjCAtTryStmt>::Alignment >=
+ llvm::AlignOf<Stmt *>::Alignment,
+ "");
/// \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,21 @@
void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context) const;
};
+// Assert objects tacked on the end of TemplateSpecializationType won't be
+// misaligned
+static_assert(llvm::AlignOf<TemplateSpecializationType>::Alignment >=
+ llvm::AlignOf<TemplateArgument>::Alignment,
+ "");
+static_assert(llvm::AlignOf<TemplateArgument>::Alignment >=
+ llvm::AlignOf<QualType>::Alignment,
+ "");
+
+// Assert objects tacked on the end of DependentTemplateSpecializationType won't
+// be misaligned
+static_assert(llvm::AlignOf<DependentTemplateSpecializationType>::Alignment >=
+ llvm::AlignOf<TemplateArgument>::Alignment,
+ "");
+
/// Location information for a TemplateArgument.
struct TemplateArgumentLocInfo {
private:
@@ -604,6 +619,11 @@
void copyInto(TemplateArgumentListInfo &List) const;
static std::size_t sizeFor(unsigned NumTemplateArgs);
};
+// Assert objects tacked on the end of ASTTemplateArgumentListInfo won't be
+// misaligned
+static_assert(llvm::AlignOf<ASTTemplateArgumentListInfo>::Alignment >=
+ llvm::AlignOf<TemplateArgumentLoc>::Alignment,
+ "");
/// \brief Extends ASTTemplateArgumentListInfo with the source location
/// information for the template keyword; this is used as part of the
@@ -640,6 +660,17 @@
static std::size_t sizeFor(unsigned NumTemplateArgs);
};
+// Assert objects tacked on the end of ASTTemplateKWAndArgsInfo won't be
+// misaligned
+static_assert(llvm::AlignOf<ASTTemplateKWAndArgsInfo>::Alignment >=
+ llvm::AlignOf<TemplateArgumentLoc>::Alignment,
+ "");
+static_assert(llvm::AlignOf<ASTTemplateKWAndArgsInfo>::Alignment >=
+ llvm::AlignOf<SourceLocation>::Alignment,
+ "");
+static_assert(llvm::AlignOf<TemplateArgumentLoc>::Alignment >=
+ llvm::AlignOf<SourceLocation>::Alignment,
+ "");
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,11 @@
iterator begin() const { return getStorage(); }
iterator end() const { return getStorage() + size(); }
};
+// Assert objects tacked on the end of OverloadedTemplateStorage won't be
+// misaligned
+static_assert(llvm::AlignOf<OverloadedTemplateStorage>::Alignment >=
+ llvm::AlignOf<NamedDecl *>::Alignment,
+ "");
/// \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<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);
}
@@ -3168,7 +3170,28 @@
param_type_iterator ArgTys, unsigned NumArgs,
const ExtProtoInfo &EPI, const ASTContext &Context);
};
-
+// Assert objects tacked on the end of FunctionProtoType won't be misaligned
+static_assert(llvm::AlignOf<FunctionProtoType>::Alignment >=
+ llvm::AlignOf<QualType>::Alignment,
+ "");
+// After QualType[], there can be one of 4 options: more QualType, Expr*, 2x
+// FunctionDecl*, FunctionDecl*
+static_assert(llvm::AlignOf<QualType>::Alignment >=
+ llvm::AlignOf<Expr *>::Alignment,
+ "");
+static_assert(llvm::AlignOf<QualType>::Alignment >=
+ llvm::AlignOf<FunctionDecl *>::Alignment,
+ "");
+// And then, after any of those options, comes bool[]
+static_assert(llvm::AlignOf<QualType>::Alignment >=
+ llvm::AlignOf<bool>::Alignment,
+ "");
+static_assert(llvm::AlignOf<Expr *>::Alignment >=
+ llvm::AlignOf<bool>::Alignment,
+ "");
+static_assert(llvm::AlignOf<FunctionDecl *>::Alignment >=
+ llvm::AlignOf<bool>::Alignment,
+ "");
/// \brief Represents the dependent type named by a dependently-scoped
/// typename using declaration, e.g.
@@ -3777,8 +3800,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 {
/// \brief The name of the template being specialized. This is
/// either a TemplateName::Template (in which case it is a
/// ClassTemplateDecl*, a TemplateTemplateParmDecl*, or a
@@ -3900,6 +3924,13 @@
return T->getTypeClass() == TemplateSpecialization;
}
};
+// Assert objects tacked on the end of TemplateSpecializationType won't be
+// misaligned
+// static_assert(llvm::AlignOf<TemplateSpecializationType>::Alignment >=
+// llvm::AlignOf<TemplateArgument>::Alignment, "");
+// static_assert(llvm::AlignOf<TemplateArgument>::Alignment >=
+// llvm::AlignOf<QualType>::Alignment, "");
+// ^ Moved 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,8 +4206,9 @@
/// DependentTemplateSpecializationType - 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 {
/// \brief The nested name specifier containing the qualifier.
NestedNameSpecifier *NNS;
@@ -4241,6 +4273,11 @@
return T->getTypeClass() == DependentTemplateSpecialization;
}
};
+// Assert objects tacked on the end of DependentTemplateSpecializationType won't
+// be misaligned
+// static_assert(llvm::AlignOf<DependentTemplateSpecializationType>::Alignment
+// >= llvm::AlignOf<TemplateArgument>::Alignment, "");
+// ^ Moved after class TemplateArgument, as it is is forward declared here.
/// \brief Represents a pack expansion of types.
///
@@ -4456,6 +4493,10 @@
ObjCProtocolDecl *const *protocols,
unsigned NumProtocols);
};
+// Assert objects tacked on the end of ObjCObjectTypeImpl won't be misaligned
+static_assert(llvm::AlignOf<ObjCObjectTypeImpl>::Alignment >=
+ llvm::AlignOf<ObjCProtocolDecl *>::Alignment,
+ "");
inline ObjCProtocolDecl **ObjCObjectType::getProtocolStorage() {
return reinterpret_cast<ObjCProtocolDecl**>(
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<void*>(static_cast<const void*>(this + 1)));
}
Index: include/clang/CodeGen/CGFunctionInfo.h
===================================================================
--- include/clang/CodeGen/CGFunctionInfo.h
+++ include/clang/CodeGen/CGFunctionInfo.h
@@ -333,11 +333,13 @@
/// 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 +502,10 @@
}
}
};
+// Assert objects tacked on the end of CGFunctionInfo won't be misaligned
+static_assert(llvm::AlignOf<CGFunctionInfo>::Alignment >=
+ llvm::AlignOf<CGFunctionInfo::ArgInfo>::Alignment,
+ "");
} // 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 <vector>
namespace clang {
class MacroInfo;
class Preprocessor;
- class Token;
class SourceLocation;
/// MacroArgs - An instance of this class captures information about
@@ -121,6 +121,10 @@
/// its freelist.
MacroArgs *deallocate();
};
+// Assert objects tacked on the end of MacroArgs won't be misaligned
+static_assert(llvm::AlignOf<MacroArgs>::Alignment >=
+ llvm::AlignOf<Token>::Alignment,
+ "");
} // end namespace clang
Index: include/clang/Lex/MacroInfo.h
===================================================================
--- include/clang/Lex/MacroInfo.h
+++ include/clang/Lex/MacroInfo.h
@@ -295,6 +295,10 @@
friend class Preprocessor;
};
+// Assert objects tacked on the end of MacroInfo won't be misaligned
+static_assert(llvm::AlignOf<MacroInfo>::Alignment >=
+ llvm::AlignOf<unsigned>::Alignment,
+ "");
class DefMacroDirective;
@@ -556,6 +560,10 @@
/// Get the number of macros that override this one.
unsigned getNumOverridingMacros() const { return NumOverriddenBy; }
};
+// Assert objects tacked on the end of ModuleMacro won't be misaligned
+static_assert(llvm::AlignOf<ModuleMacro>::Alignment >=
+ llvm::AlignOf<ModuleMacro *>::Alignment,
+ "");
/// \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
@@ -135,11 +135,9 @@
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 {
@@ -468,6 +466,23 @@
/// a Spelling enumeration, the value UINT_MAX is returned.
unsigned getSemanticSpelling() const;
};
+// Assert objects tacked on the end of AttributeList won't be misaligned.
+static_assert(llvm::AlignOf<AttributeList>::Alignment >=
+ llvm::AlignOf<ArgsUnion>::Alignment,
+ "");
+static_assert(llvm::AlignOf<ArgsUnion>::Alignment >=
+ llvm::AlignOf<AvailabilityChange>::Alignment,
+ "");
+static_assert(
+ llvm::AlignOf<ArgsUnion>::Alignment >=
+ llvm::AlignOf<AttributeList::TypeTagForDatatypeData>::Alignment,
+ "");
+static_assert(llvm::AlignOf<AttributeList>::Alignment >=
+ llvm::AlignOf<ParsedType>::Alignment,
+ "");
+static_assert(llvm::AlignOf<AttributeList>::Alignment >=
+ llvm::AlignOf<AttributeList::PropertyData>::Alignment,
+ "");
/// A factory, from which one makes pools, from which one creates
/// individual attributes which are deallocated with the pool.
Index: include/clang/Sema/CodeCompleteConsumer.h
===================================================================
--- include/clang/Sema/CodeCompleteConsumer.h
+++ include/clang/Sema/CodeCompleteConsumer.h
@@ -494,6 +494,13 @@
/// which is mainly useful for debugging.
std::string getAsString() const;
};
+// Assert objects tacked on the end of CodeCompletionString won't be misaligned
+static_assert(llvm::AlignOf<CodeCompletionString>::Alignment >=
+ llvm::AlignOf<CodeCompletionString::Chunk>::Alignment,
+ "");
+static_assert(llvm::AlignOf<CodeCompletionString::Chunk>::Alignment >=
+ llvm::AlignOf<const char *>::Alignment,
+ "");
/// \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,11 @@
free(this);
}
};
+ // Assert objects tacked on the end of TemplateIdAnnotation won't be
+ // misaligned
+ static_assert(llvm::AlignOf<TemplateIdAnnotation>::Alignment >=
+ llvm::AlignOf<ParsedTemplateArgument>::Alignment,
+ "");
/// 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<uint64_t> InputFileOffsets;
/// \brief The input files that have been loaded from this AST file.
std::vector<InputFile> 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<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());
Index: lib/AST/DeclBase.cpp
===================================================================
--- lib/AST/DeclBase.cpp
+++ lib/AST/DeclBase.cpp
@@ -45,10 +45,20 @@
getASTContext().getExternalSource()->updateOutOfDateIdentifier(II);
}
+// Assert objects tacked on the end of all Decl subclasses won't be misaligned
+// by Decl::operator new().
+#define DECL(DERIVED, BASE) \
+ static_assert(llvm::AlignOf<uint64_t>::Alignment >= \
+ llvm::AlignOf<DERIVED##Decl>::Alignment, \
+ "");
+#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 >= llvm::AlignOf<uint64_t>::Alignment, "");
void *Start = Context.Allocate(Size + Extra + 8);
void *Result = (char*)Start + 8;
@@ -69,7 +79,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 *), llvm::alignOf<uint64_t>());
+ 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);
Index: lib/AST/Expr.cpp
===================================================================
--- lib/AST/Expr.cpp
+++ 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<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,
@@ -420,8 +425,11 @@
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());
@@ -3893,7 +3901,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<DesignatedInitExpr>());
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
@@ -1070,15 +1070,15 @@
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]);
}
@@ -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<clang::Stmt **>(&getStoredStmts()[NumCaptures]) =
+ getCallOperator()->getBody();
+
return reinterpret_cast<CompoundStmt *>(getStoredStmts()[NumCaptures]);
}
Index: lib/AST/Stmt.cpp
===================================================================
--- lib/AST/Stmt.cpp
+++ lib/AST/Stmt.cpp
@@ -822,16 +822,16 @@
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);
@@ -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
@@ -390,6 +390,11 @@
Profile(ID, keyword_begin(), getNumArgs());
}
};
+// Assert objects tacked on the end of MultiKeywordSelector won't be misaligned
+static_assert(llvm::AlignOf<MultiKeywordSelector>::Alignment >=
+ llvm::AlignOf<IdentifierInfo *>::Alignment,
+ "");
+
} // end namespace clang.
unsigned Selector::getNumArgs() 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::unallocate(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<EHCleanupScope>(*begin());
InnermostNormalCleanup = Cleanup.getEnclosingNormalCleanup();
InnermostEHScope = Cleanup.getEnclosingEHScope();
- StartOfData += Cleanup.getAllocatedSize();
+ unallocate(Cleanup.getAllocatedSize());
// Destroy the cleanup.
Cleanup.Destroy();
@@ -224,7 +228,7 @@
assert(!empty() && "popping exception stack when not empty");
EHFilterScope &filter = cast<EHFilterScope>(*begin());
- StartOfData += EHFilterScope::getSizeForNumFilters(filter.getNumFilters());
+ unallocate(EHFilterScope::getSizeForNumFilters(filter.getNumFilters()));
InnermostEHScope = filter.getEnclosingEHScope();
}
Index: lib/CodeGen/CGCleanup.h
===================================================================
--- lib/CodeGen/CGCleanup.h
+++ lib/CodeGen/CGCleanup.h
@@ -214,9 +214,13 @@
return Scope->getKind() == Catch;
}
};
+// Assert objects tacked on the end of EHCatchScope won't be misaligned
+static_assert(llvm::AlignOf<EHCatchScope>::Alignment >=
+ llvm::AlignOf<EHCatchScope::Handler *>::Alignment,
+ "");
/// 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 +400,13 @@
return (Scope->getKind() == Cleanup);
}
};
+// Assert objects tacked on the end of EHCleanupScope won't be
+// misaligned. NOTE: there's actually a bunch of different data
+// classes tacked on, so let's just ensure alignment good enough for
+// uint64_t bytes.
+static_assert(llvm::AlignOf<EHCleanupScope>::Alignment >=
+ llvm::AlignOf<uint64_t>::Alignment,
+ "");
/// An exceptions scope which filters exceptions thrown through it.
/// Only exceptions matching the filter types will be permitted to be
@@ -440,6 +451,10 @@
return scope->getKind() == Filter;
}
};
+// Assert objects tacked on the end of EHFilterScope won't be misaligned
+static_assert(llvm::AlignOf<EHFilterScope>::Alignment >=
+ llvm::AlignOf<llvm::Value *>::Alignment,
+ "");
/// An exceptions scope which calls std::terminate if any exception
/// reaches it.
@@ -472,27 +487,27 @@
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;
}
@@ -528,15 +543,15 @@
EHCatchScope &scope = cast<EHCatchScope>(*begin());
InnermostEHScope = scope.getEnclosingEHScope();
- StartOfData += EHCatchScope::getSizeForNumHandlers(scope.getNumHandlers());
+ unallocate(EHCatchScope::getSizeForNumHandlers(scope.getNumHandlers()));
}
inline void EHScopeStack::popTerminate() {
assert(!empty() && "popping exception stack when not empty");
EHTerminateScope &scope = cast<EHTerminateScope>(*begin());
InnermostEHScope = scope.getEnclosingEHScope();
- StartOfData += EHTerminateScope::getSize();
+ unallocate(EHTerminateScope::getSize());
}
inline EHScopeStack::iterator EHScopeStack::find(stable_iterator sp) const {
Index: lib/CodeGen/CGExprCXX.cpp
===================================================================
--- lib/CodeGen/CGExprCXX.cpp
+++ lib/CodeGen/CGExprCXX.cpp
@@ -1134,6 +1134,10 @@
EmitNewDeleteCall(CGF, OperatorDelete, FPT, DeleteArgs);
}
};
+ // Assert objects tacked on the end of CallDeleteDuringNew won't be misaligned
+ static_assert(llvm::AlignOf<CallDeleteDuringNew>::Alignment >=
+ llvm::AlignOf<RValue>::Alignment,
+ "");
/// A cleanup to call the given 'operator delete' function upon
/// abnormal exit from a new expression when the new expression is
@@ -1193,6 +1197,11 @@
EmitNewDeleteCall(CGF, OperatorDelete, FPT, DeleteArgs);
}
};
+ // Assert objects tacked on the end of CallDeleteDuringNew won't be misaligned
+ static_assert(
+ llvm::AlignOf<CallDeleteDuringConditionalNew>::Alignment >=
+ llvm::AlignOf<DominatingValue<RValue>::saved_type>::Alignment,
+ "");
}
/// Enter a cleanup to call 'operator delete' if the initializer in a
@@ -1823,8 +1832,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: lib/CodeGen/CGStmt.cpp
===================================================================
--- lib/CodeGen/CGStmt.cpp
+++ lib/CodeGen/CGStmt.cpp
@@ -2113,8 +2113,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<uint64_t>::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<BranchFixup, 8> BranchFixups;
char *allocate(size_t Size);
+ void unallocate(size_t Size);
void *pushCleanup(CleanupKind K, size_t DataSize);
@@ -259,14 +262,16 @@
/// 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, "");
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, "");
void *Buffer = pushCleanup(Kind, sizeof(T));
Cleanup *Obj = new (Buffer) T(std::move(A));
(void) Obj;
@@ -287,6 +292,7 @@
/// stack is modified.
template <class T, class... As>
T *pushCleanupWithExtra(CleanupKind Kind, size_t N, As... A) {
+ static_assert(llvm::AlignOf<T>::Alignment <= ScopeStackAlignment, "");
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<MacroInfo>::Alignment >= sizeof(SubModuleID),
- "alignment for MacroInfo is less than the ID");
DeserializedMacroInfoChain *MIChain =
BP.Allocate<DeserializedMacroInfoChain>();
MIChain->Next = DeserialMIChainHead;
Index: lib/Sema/SemaExceptionSpec.cpp
===================================================================
--- lib/Sema/SemaExceptionSpec.cpp
+++ lib/Sema/SemaExceptionSpec.cpp
@@ -971,8 +971,9 @@
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;
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;
}
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits