summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
authorJames Y Knight <jyknight@google.com>2015-07-17 18:21:37 +0000
committerJames Y Knight <jyknight@google.com>2015-07-17 18:21:37 +0000
commit53c7616e2e6aa3bcef0123c1890f8fdeb0e760ab (patch)
tree7e9e1de25a2500e592ba668b4405ce2a07ba1378 /clang/lib
parent5a6d5bc17b385293e3337b9f2082151594f972f9 (diff)
downloadbcm5719-llvm-53c7616e2e6aa3bcef0123c1890f8fdeb0e760ab.tar.gz
bcm5719-llvm-53c7616e2e6aa3bcef0123c1890f8fdeb0e760ab.zip
Fix alignment issues in Clang.
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. Follow-up patches will factor out a trailing-object helper class, to make classes using the idiom of appending objects to other objects easier to understand, and to ensure (with static_assert) that required alignment guarantees continue to hold. Differential Revision: http://reviews.llvm.org/D10272 llvm-svn: 242554
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/AST/Decl.cpp6
-rw-r--r--clang/lib/AST/DeclBase.cpp19
-rw-r--r--clang/lib/AST/Expr.cpp17
-rw-r--r--clang/lib/AST/ExprCXX.cpp16
-rw-r--r--clang/lib/AST/Stmt.cpp5
-rw-r--r--clang/lib/CodeGen/CGCleanup.cpp10
-rw-r--r--clang/lib/CodeGen/CGCleanup.h31
-rw-r--r--clang/lib/CodeGen/CGExprCXX.cpp4
-rw-r--r--clang/lib/CodeGen/CGStmt.cpp4
-rw-r--r--clang/lib/CodeGen/EHScopeStack.h9
-rw-r--r--clang/lib/Sema/SemaExceptionSpec.cpp5
11 files changed, 88 insertions, 38 deletions
diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp
index ea4b2f517cd..946d1bae21e 100644
--- a/clang/lib/AST/Decl.cpp
+++ b/clang/lib/AST/Decl.cpp
@@ -3116,8 +3116,8 @@ FunctionDecl::setDependentTemplateSpecialization(ASTContext &Context,
const TemplateArgumentListInfo &TemplateArgs) {
assert(TemplateOrSpecialization.isNull());
size_t Size = sizeof(DependentFunctionTemplateSpecializationInfo);
- Size += Templates.size() * sizeof(FunctionTemplateDecl*);
Size += TemplateArgs.size() * sizeof(TemplateArgumentLoc);
+ Size += Templates.size() * sizeof(FunctionTemplateDecl *);
void *Buffer = Context.Allocate(Size);
DependentFunctionTemplateSpecializationInfo *Info =
new (Buffer) DependentFunctionTemplateSpecializationInfo(Templates,
@@ -3132,8 +3132,8 @@ DependentFunctionTemplateSpecializationInfo(const UnresolvedSetImpl &Ts,
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());
diff --git a/clang/lib/AST/DeclBase.cpp b/clang/lib/AST/DeclBase.cpp
index 4fcec53d6eb..e772f195336 100644
--- a/clang/lib/AST/DeclBase.cpp
+++ b/clang/lib/AST/DeclBase.cpp
@@ -45,10 +45,19 @@ void Decl::updateOutOfDate(IdentifierInfo &II) const {
getASTContext().getExternalSource()->updateOutOfDateIdentifier(II);
}
+#define DECL(DERIVED, BASE) \
+ static_assert(Decl::DeclObjAlignment >= \
+ llvm::AlignOf<DERIVED##Decl>::Alignment, \
+ "Alignment sufficient after objects prepended to " #DERIVED);
+#define ABSTRACT_DECL(DECL)
+#include "clang/AST/DeclNodes.inc"
+
void *Decl::operator new(std::size_t Size, const ASTContext &Context,
unsigned ID, std::size_t Extra) {
// Allocate an extra 8 bytes worth of storage, which ensures that the
- // resulting pointer will still be 8-byte aligned.
+ // resulting pointer will still be 8-byte aligned.
+ static_assert(sizeof(unsigned) * 2 >= DeclObjAlignment,
+ "Decl won't be misaligned");
void *Start = Context.Allocate(Size + Extra + 8);
void *Result = (char*)Start + 8;
@@ -69,7 +78,13 @@ void *Decl::operator new(std::size_t Size, const ASTContext &Ctx,
// With local visibility enabled, we track the owning module even for local
// declarations.
if (Ctx.getLangOpts().ModulesLocalVisibility) {
- void *Buffer = ::operator new(sizeof(Module *) + Size + Extra, Ctx);
+ // Ensure required alignment of the resulting object by adding extra
+ // padding at the start if required.
+ size_t ExtraAlign =
+ llvm::OffsetToAlignment(sizeof(Module *), DeclObjAlignment);
+ char *Buffer = reinterpret_cast<char *>(
+ ::operator new(ExtraAlign + sizeof(Module *) + Size + Extra, Ctx));
+ Buffer += ExtraAlign;
return new (Buffer) Module*(nullptr) + 1;
}
return ::operator new(Size + Extra, Ctx);
diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp
index 2e066b2c42c..6c048f96d45 100644
--- a/clang/lib/AST/Expr.cpp
+++ b/clang/lib/AST/Expr.cpp
@@ -399,10 +399,15 @@ DeclRefExpr *DeclRefExpr::Create(const ASTContext &Context,
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 @@ DeclRefExpr *DeclRefExpr::CreateEmpty(const ASTContext &Context,
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());
@@ -3939,7 +3947,8 @@ DesignatedInitExpr::Create(const ASTContext &C, Designator *Designators,
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);
diff --git a/clang/lib/AST/ExprCXX.cpp b/clang/lib/AST/ExprCXX.cpp
index d6f2ce63a0a..2a93f71429e 100644
--- a/clang/lib/AST/ExprCXX.cpp
+++ b/clang/lib/AST/ExprCXX.cpp
@@ -1070,15 +1070,15 @@ LambdaExpr::capture_range LambdaExpr::implicit_captures() const {
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 @@ TemplateParameterList *LambdaExpr::getTemplateParameterList() const {
}
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]);
}
diff --git a/clang/lib/AST/Stmt.cpp b/clang/lib/AST/Stmt.cpp
index c0aab4c4db7..80b6be88a3e 100644
--- a/clang/lib/AST/Stmt.cpp
+++ b/clang/lib/AST/Stmt.cpp
@@ -822,7 +822,7 @@ SourceLocation ObjCAtTryStmt::getLocEnd() const {
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);
@@ -831,7 +831,7 @@ CXXTryStmt *CXXTryStmt::Create(const ASTContext &C, SourceLocation tryLoc,
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);
@@ -2250,4 +2250,3 @@ OMPTeamsDirective *OMPTeamsDirective::CreateEmpty(const ASTContext &C,
C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *));
return new (Mem) OMPTeamsDirective(NumClauses);
}
-
diff --git a/clang/lib/CodeGen/CGCleanup.cpp b/clang/lib/CodeGen/CGCleanup.cpp
index d97e40554ef..3d4c4850f60 100644
--- a/clang/lib/CodeGen/CGCleanup.cpp
+++ b/clang/lib/CodeGen/CGCleanup.cpp
@@ -96,6 +96,7 @@ RValue DominatingValue<RValue>::saved_type::restore(CodeGenFunction &CGF) {
/// 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 @@ char *EHScopeStack::allocate(size_t Size) {
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 @@ EHScopeStack::stable_iterator EHScopeStack::getInnermostActiveEHScope() const {
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 @@ void EHScopeStack::popCleanup() {
EHCleanupScope &Cleanup = cast<EHCleanupScope>(*begin());
InnermostNormalCleanup = Cleanup.getEnclosingNormalCleanup();
InnermostEHScope = Cleanup.getEnclosingEHScope();
- StartOfData += Cleanup.getAllocatedSize();
+ deallocate(Cleanup.getAllocatedSize());
// Destroy the cleanup.
Cleanup.Destroy();
@@ -224,7 +228,7 @@ void EHScopeStack::popFilter() {
assert(!empty() && "popping exception stack when not empty");
EHFilterScope &filter = cast<EHFilterScope>(*begin());
- StartOfData += EHFilterScope::getSizeForNumFilters(filter.getNumFilters());
+ deallocate(EHFilterScope::getSizeForNumFilters(filter.getNumFilters()));
InnermostEHScope = filter.getEnclosingEHScope();
}
diff --git a/clang/lib/CodeGen/CGCleanup.h b/clang/lib/CodeGen/CGCleanup.h
index 81c64123dfd..34866d4c47c 100644
--- a/clang/lib/CodeGen/CGCleanup.h
+++ b/clang/lib/CodeGen/CGCleanup.h
@@ -216,7 +216,7 @@ public:
};
/// A cleanup scope which generates the cleanup blocks lazily.
-class EHCleanupScope : public EHScope {
+class LLVM_ALIGNAS(/*alignof(uint64_t)*/ 8) EHCleanupScope : public EHScope {
/// The nearest normal cleanup scope enclosing this one.
EHScopeStack::stable_iterator EnclosingNormal;
@@ -396,6 +396,15 @@ public:
return (Scope->getKind() == Cleanup);
}
};
+// NOTE: there's a bunch of different data classes tacked on after an
+// EHCleanupScope. It is asserted (in EHScopeStack::pushCleanup*) that
+// they don't require greater alignment than ScopeStackAlignment. So,
+// EHCleanupScope ought to have alignment equal to that -- not more
+// (would be misaligned by the stack allocator), and not less (would
+// break the appended classes).
+static_assert(llvm::AlignOf<EHCleanupScope>::Alignment ==
+ EHScopeStack::ScopeStackAlignment,
+ "EHCleanupScope expected alignment");
/// An exceptions scope which filters exceptions thrown through it.
/// Only exceptions matching the filter types will be permitted to be
@@ -472,27 +481,27 @@ public:
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,7 +537,7 @@ inline void EHScopeStack::popCatch() {
EHCatchScope &scope = cast<EHCatchScope>(*begin());
InnermostEHScope = scope.getEnclosingEHScope();
- StartOfData += EHCatchScope::getSizeForNumHandlers(scope.getNumHandlers());
+ deallocate(EHCatchScope::getSizeForNumHandlers(scope.getNumHandlers()));
}
inline void EHScopeStack::popTerminate() {
@@ -536,7 +545,7 @@ inline void EHScopeStack::popTerminate() {
EHTerminateScope &scope = cast<EHTerminateScope>(*begin());
InnermostEHScope = scope.getEnclosingEHScope();
- StartOfData += EHTerminateScope::getSize();
+ deallocate(EHTerminateScope::getSize());
}
inline EHScopeStack::iterator EHScopeStack::find(stable_iterator sp) const {
diff --git a/clang/lib/CodeGen/CGExprCXX.cpp b/clang/lib/CodeGen/CGExprCXX.cpp
index c7adccaeeae..371f44fcc95 100644
--- a/clang/lib/CodeGen/CGExprCXX.cpp
+++ b/clang/lib/CodeGen/CGExprCXX.cpp
@@ -1844,8 +1844,8 @@ void CodeGenFunction::EmitLambdaExpr(const LambdaExpr *E, AggValueSlot Slot) {
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);
diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp
index 7a0b8a35be0..f58c2f440a6 100644
--- a/clang/lib/CodeGen/CGStmt.cpp
+++ b/clang/lib/CodeGen/CGStmt.cpp
@@ -2156,8 +2156,8 @@ LValue CodeGenFunction::InitCapturedStruct(const CapturedStmt &S) {
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()) {
diff --git a/clang/lib/CodeGen/EHScopeStack.h b/clang/lib/CodeGen/EHScopeStack.h
index a7951888c82..7b541b53ea6 100644
--- a/clang/lib/CodeGen/EHScopeStack.h
+++ b/clang/lib/CodeGen/EHScopeStack.h
@@ -96,6 +96,8 @@ enum CleanupKind : unsigned {
/// 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 @@ private:
SmallVector<BranchFixup, 8> BranchFixups;
char *allocate(size_t Size);
+ void deallocate(size_t Size);
void *pushCleanup(CleanupKind K, size_t DataSize);
@@ -259,6 +262,8 @@ public:
/// Push a lazily-created cleanup on the stack.
template <class T, class... As> void pushCleanup(CleanupKind Kind, As... A) {
+ static_assert(llvm::AlignOf<T>::Alignment <= ScopeStackAlignment,
+ "Cleanup's alignment is too large.");
void *Buffer = pushCleanup(Kind, sizeof(T));
Cleanup *Obj = new (Buffer) T(A...);
(void) Obj;
@@ -267,6 +272,8 @@ public:
/// Push a lazily-created cleanup on the stack. Tuple version.
template <class T, class... As>
void pushCleanupTuple(CleanupKind Kind, std::tuple<As...> A) {
+ static_assert(llvm::AlignOf<T>::Alignment <= ScopeStackAlignment,
+ "Cleanup's alignment is too large.");
void *Buffer = pushCleanup(Kind, sizeof(T));
Cleanup *Obj = new (Buffer) T(std::move(A));
(void) Obj;
@@ -287,6 +294,8 @@ public:
/// stack is modified.
template <class T, class... As>
T *pushCleanupWithExtra(CleanupKind Kind, size_t N, As... A) {
+ static_assert(llvm::AlignOf<T>::Alignment <= ScopeStackAlignment,
+ "Cleanup's alignment is too large.");
void *Buffer = pushCleanup(Kind, sizeof(T) + T::getExtraSize(N));
return new (Buffer) T(N, A...);
}
diff --git a/clang/lib/Sema/SemaExceptionSpec.cpp b/clang/lib/Sema/SemaExceptionSpec.cpp
index 094187025df..8a9372336e8 100644
--- a/clang/lib/Sema/SemaExceptionSpec.cpp
+++ b/clang/lib/Sema/SemaExceptionSpec.cpp
@@ -973,8 +973,9 @@ CanThrowResult Sema::canThrow(const Expr *E) {
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;
OpenPOWER on IntegriCloud