diff options
| author | James Y Knight <jyknight@google.com> | 2015-07-17 18:21:37 +0000 |
|---|---|---|
| committer | James Y Knight <jyknight@google.com> | 2015-07-17 18:21:37 +0000 |
| commit | 53c7616e2e6aa3bcef0123c1890f8fdeb0e760ab (patch) | |
| tree | 7e9e1de25a2500e592ba668b4405ce2a07ba1378 /clang/lib | |
| parent | 5a6d5bc17b385293e3337b9f2082151594f972f9 (diff) | |
| download | bcm5719-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.cpp | 6 | ||||
| -rw-r--r-- | clang/lib/AST/DeclBase.cpp | 19 | ||||
| -rw-r--r-- | clang/lib/AST/Expr.cpp | 17 | ||||
| -rw-r--r-- | clang/lib/AST/ExprCXX.cpp | 16 | ||||
| -rw-r--r-- | clang/lib/AST/Stmt.cpp | 5 | ||||
| -rw-r--r-- | clang/lib/CodeGen/CGCleanup.cpp | 10 | ||||
| -rw-r--r-- | clang/lib/CodeGen/CGCleanup.h | 31 | ||||
| -rw-r--r-- | clang/lib/CodeGen/CGExprCXX.cpp | 4 | ||||
| -rw-r--r-- | clang/lib/CodeGen/CGStmt.cpp | 4 | ||||
| -rw-r--r-- | clang/lib/CodeGen/EHScopeStack.h | 9 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaExceptionSpec.cpp | 5 |
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; |

