<div dir="ltr">I have no idea what's wrong... With lg from chandlerc on irc I'm rolling back and adding a regression test case.<div><br></div><div style>/Manuel</div></div><div class="gmail_extra"><br><br><div class="gmail_quote">
On Fri, Jun 7, 2013 at 11:09 AM, Manuel Klimek <span dir="ltr"><<a href="mailto:klimek@google.com" target="_blank">klimek@google.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div dir="ltr">More specifically, we get a TemplateSpecializationTypeLoc for which:<div>getLAngleLoc().isValid() is false, while</div><div>getRAngleLoc().isValid() && getLocStart().isValid() && getLocEnd().isValid() is true.</div>
</div><div class="HOEnZb"><div class="h5"><div class="gmail_extra"><br><br><div class="gmail_quote">On Fri, Jun 7, 2013 at 10:46 AM, Manuel Klimek <span dir="ltr"><<a href="mailto:klimek@google.com" target="_blank">klimek@google.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">FYI: this test leads to invalid type source locations in some cases. I don't have a good enough repro yet (internal refactoring tests found this), but the general idea is this:<div>
Given a TypeLoc for a templated type A<B> of a function parameter (like void f(const A<B>&), trying to getAs<clang::TemplateSpecializationTypeLoc> would previously return a valid type loc, and now returns an invalid type loc... Is that intentional?</div>
<div><br></div><div>Thanks,</div><div>/Manuel</div><div><br></div></div><div><div><div class="gmail_extra"><br><br><div class="gmail_quote">On Fri, Jun 7, 2013 at 2:04 AM, Eli Friedman <span dir="ltr"><<a href="mailto:eli.friedman@gmail.com" target="_blank">eli.friedman@gmail.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: efriedma<br>
Date: Thu Jun 6 19:04:31 2013<br>
New Revision: 183466<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=183466&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=183466&view=rev</a><br>
Log:<br>
Perform dynamic alignment computations so that the data in TypeLocs is<br>
correctly aligned. Not performing such computations led to misaligned loads,<br>
which crash on some platforms and are generally bad on other platforms.<br>
<br>
The implementation of TypeLocBuilder::pushImpl is rather messy; code using<br>
TypeLocBuilder accidentally assumes that partial TypeLocs are<br>
laid out like a complete TypeLoc. As a followup, I intend to work on<br>
fixing the TypeLocBuilder API to avoid exposing partial TypeLocs; this should<br>
substantially simplify the implemementation.<br>
<br>
Fixes PR16144.<br>
<br>
<br>
Added:<br>
cfe/trunk/lib/Sema/TypeLocBuilder.cpp<br>
Modified:<br>
cfe/trunk/include/clang/AST/TypeLoc.h<br>
cfe/trunk/lib/AST/TypeLoc.cpp<br>
cfe/trunk/lib/Sema/CMakeLists.txt<br>
cfe/trunk/lib/Sema/SemaLambda.cpp<br>
cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp<br>
cfe/trunk/lib/Sema/TreeTransform.h<br>
cfe/trunk/lib/Sema/TypeLocBuilder.h<br>
<br>
Modified: cfe/trunk/include/clang/AST/TypeLoc.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/TypeLoc.h?rev=183466&r1=183465&r2=183466&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/TypeLoc.h?rev=183466&r1=183465&r2=183466&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/include/clang/AST/TypeLoc.h (original)<br>
+++ cfe/trunk/include/clang/AST/TypeLoc.h Thu Jun 6 19:04:31 2013<br>
@@ -95,6 +95,10 @@ public:<br>
/// \brief Returns the size of type source info data block for the given type.<br>
static unsigned getFullDataSizeForType(QualType Ty);<br>
<br>
+ /// \brief Returns the alignment of type source info data block for<br>
+ /// the given type.<br>
+ static unsigned getLocalAlignmentForType(QualType Ty);<br>
+<br>
/// \brief Get the type for which this source info wrapper provides<br>
/// information.<br>
QualType getType() const {<br>
@@ -229,7 +233,11 @@ public:<br>
}<br>
<br>
UnqualTypeLoc getUnqualifiedLoc() const {<br>
- return UnqualTypeLoc(getTypePtr(), Data);<br>
+ unsigned align =<br>
+ TypeLoc::getLocalAlignmentForType(QualType(getTypePtr(), 0));<br>
+ uintptr_t dataInt = reinterpret_cast<uintptr_t>(Data);<br>
+ dataInt = llvm::RoundUpToAlignment(dataInt, align);<br>
+ return UnqualTypeLoc(getTypePtr(), reinterpret_cast<void*>(dataInt));<br>
}<br>
<br>
/// Initializes the local data of this type source info block to<br>
@@ -250,10 +258,11 @@ public:<br>
return 0;<br>
}<br>
<br>
- /// \brief Returns the size of the type source info data block.<br>
- unsigned getFullDataSize() const {<br>
- return getLocalDataSize() +<br>
- getFullDataSizeForType(getType().getLocalUnqualifiedType());<br>
+ /// \brief Returns the alignment of the type source info data block that is<br>
+ /// specific to this type.<br>
+ unsigned getLocalDataAlignment() const {<br>
+ // We don't preserve any location information.<br>
+ return 1;<br>
}<br>
<br>
private:<br>
@@ -280,9 +289,6 @@ inline UnqualTypeLoc TypeLoc::getUnquali<br>
/// \tparam LocalData the structure type of local location data for<br>
/// this type<br>
///<br>
-/// sizeof(LocalData) needs to be a multiple of sizeof(void*) or<br>
-/// else the world will end.<br>
-///<br>
/// TypeLocs with non-constant amounts of local data should override<br>
/// getExtraLocalDataSize(); getExtraLocalData() will then point to<br>
/// this extra memory.<br>
@@ -317,12 +323,16 @@ class ConcreteTypeLoc : public Base {<br>
}<br>
<br>
public:<br>
- unsigned getLocalDataSize() const {<br>
- return sizeof(LocalData) + asDerived()->getExtraLocalDataSize();<br>
+ unsigned getLocalDataAlignment() const {<br>
+ return std::max(llvm::alignOf<LocalData>(),<br>
+ asDerived()->getExtraLocalDataAlignment());<br>
}<br>
- // Give a default implementation that's useful for leaf types.<br>
- unsigned getFullDataSize() const {<br>
- return asDerived()->getLocalDataSize() + getInnerTypeSize();<br>
+ unsigned getLocalDataSize() const {<br>
+ unsigned size = sizeof(LocalData);<br>
+ unsigned extraAlign = asDerived()->getExtraLocalDataAlignment();<br>
+ size = llvm::RoundUpToAlignment(size, extraAlign);<br>
+ size += asDerived()->getExtraLocalDataSize();<br>
+ return size;<br>
}<br>
<br>
TypeLoc getNextTypeLoc() const {<br>
@@ -338,6 +348,10 @@ protected:<br>
return 0;<br>
}<br>
<br>
+ unsigned getExtraLocalDataAlignment() const {<br>
+ return 1;<br>
+ }<br>
+<br>
LocalData *getLocalData() const {<br>
return static_cast<LocalData*>(Base::Data);<br>
}<br>
@@ -346,11 +360,17 @@ protected:<br>
/// local data that can't be captured in the Info (e.g. because it's<br>
/// of variable size).<br>
void *getExtraLocalData() const {<br>
- return getLocalData() + 1;<br>
+ unsigned size = sizeof(LocalData);<br>
+ unsigned extraAlign = asDerived()->getExtraLocalDataAlignment();<br>
+ size = llvm::RoundUpToAlignment(size, extraAlign);<br>
+ return reinterpret_cast<char*>(Base::Data) + size;<br>
}<br>
<br>
void *getNonLocalData() const {<br>
- return static_cast<char*>(Base::Data) + asDerived()->getLocalDataSize();<br>
+ uintptr_t data = reinterpret_cast<uintptr_t>(Base::Data);<br>
+ data += asDerived()->getLocalDataSize();<br>
+ data = llvm::RoundUpToAlignment(data, getNextTypeAlign());<br>
+ return reinterpret_cast<void*>(data);<br>
}<br>
<br>
struct HasNoInnerType {};<br>
@@ -373,6 +393,18 @@ private:<br>
return getInnerTypeLoc().getFullDataSize();<br>
}<br>
<br>
+ unsigned getNextTypeAlign() const {<br>
+ return getNextTypeAlign(asDerived()->getInnerType());<br>
+ }<br>
+<br>
+ unsigned getNextTypeAlign(HasNoInnerType _) const {<br>
+ return 1;<br>
+ }<br>
+<br>
+ unsigned getNextTypeAlign(QualType T) const {<br>
+ return TypeLoc::getLocalAlignmentForType(T);<br>
+ }<br>
+<br>
TypeLoc getNextTypeLoc(HasNoInnerType _) const {<br>
return TypeLoc();<br>
}<br>
@@ -417,7 +449,8 @@ class TypeSpecTypeLoc : public ConcreteT<br>
Type,<br>
TypeSpecLocInfo> {<br>
public:<br>
- enum { LocalDataSize = sizeof(TypeSpecLocInfo) };<br>
+ enum { LocalDataSize = sizeof(TypeSpecLocInfo),<br>
+ LocalDataAlignment = llvm::AlignOf<TypeSpecLocInfo>::Alignment };<br>
<br>
SourceLocation getNameLoc() const {<br>
return this->getLocalData()->NameLoc;<br>
@@ -448,8 +481,6 @@ class BuiltinTypeLoc : public ConcreteTy<br>
BuiltinType,<br>
BuiltinLocInfo> {<br>
public:<br>
- enum { LocalDataSize = sizeof(BuiltinLocInfo) };<br>
-<br>
SourceLocation getBuiltinLoc() const {<br>
return getLocalData()->BuiltinLoc;<br>
}<br>
@@ -478,6 +509,10 @@ public:<br>
return needsExtraLocalData() ? sizeof(WrittenBuiltinSpecs) : 0;<br>
}<br>
<br>
+ unsigned getExtraLocalDataAlignment() const {<br>
+ return needsExtraLocalData() ? llvm::alignOf<WrittenBuiltinSpecs>() : 1;<br>
+ }<br>
+<br>
SourceRange getLocalSourceRange() const {<br>
return SourceRange(getBuiltinLoc(), getBuiltinLoc());<br>
}<br>
@@ -840,6 +875,10 @@ public:<br>
return this->getNumProtocols() * sizeof(SourceLocation);<br>
}<br>
<br>
+ unsigned getExtraLocalDataAlignment() const {<br>
+ return llvm::alignOf<SourceLocation>();<br>
+ }<br>
+<br>
QualType getInnerType() const {<br>
return getTypePtr()->getBaseType();<br>
}<br>
@@ -1166,6 +1205,10 @@ public:<br>
return getNumArgs() * sizeof(ParmVarDecl*);<br>
}<br>
<br>
+ unsigned getExtraLocalDataAlignment() const {<br>
+ return llvm::alignOf<ParmVarDecl*>();<br>
+ }<br>
+<br>
QualType getInnerType() const { return getTypePtr()->getResultType(); }<br>
};<br>
<br>
@@ -1357,6 +1400,10 @@ public:<br>
return getNumArgs() * sizeof(TemplateArgumentLocInfo);<br>
}<br>
<br>
+ unsigned getExtraLocalDataAlignment() const {<br>
+ return llvm::alignOf<TemplateArgumentLocInfo>();<br>
+ }<br>
+<br>
private:<br>
TemplateArgumentLocInfo *getArgInfos() const {<br>
return static_cast<TemplateArgumentLocInfo*>(getExtraLocalData());<br>
@@ -1761,6 +1808,10 @@ public:<br>
return getNumArgs() * sizeof(TemplateArgumentLocInfo);<br>
}<br>
<br>
+ unsigned getExtraLocalDataAlignment() const {<br>
+ return llvm::alignOf<TemplateArgumentLocInfo>();<br>
+ }<br>
+<br>
private:<br>
TemplateArgumentLocInfo *getArgInfos() const {<br>
return static_cast<TemplateArgumentLocInfo*>(getExtraLocalData());<br>
<br>
Modified: cfe/trunk/lib/AST/TypeLoc.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/TypeLoc.cpp?rev=183466&r1=183465&r2=183466&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/TypeLoc.cpp?rev=183466&r1=183465&r2=183466&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/AST/TypeLoc.cpp (original)<br>
+++ cfe/trunk/lib/AST/TypeLoc.cpp Thu Jun 6 19:04:31 2013<br>
@@ -41,12 +41,30 @@ SourceRange TypeLoc::getLocalSourceRange<br>
}<br>
<br>
namespace {<br>
+ class TypeAligner : public TypeLocVisitor<TypeAligner, unsigned> {<br>
+ public:<br>
+#define ABSTRACT_TYPELOC(CLASS, PARENT)<br>
+#define TYPELOC(CLASS, PARENT) \<br>
+ unsigned Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \<br>
+ return TyLoc.getLocalDataAlignment(); \<br>
+ }<br>
+#include "clang/AST/TypeLocNodes.def"<br>
+ };<br>
+}<br>
+<br>
+/// \brief Returns the alignment of the type source info data block.<br>
+unsigned TypeLoc::getLocalAlignmentForType(QualType Ty) {<br>
+ if (Ty.isNull()) return 1;<br>
+ return TypeAligner().Visit(TypeLoc(Ty, 0));<br>
+}<br>
+<br>
+namespace {<br>
class TypeSizer : public TypeLocVisitor<TypeSizer, unsigned> {<br>
public:<br>
#define ABSTRACT_TYPELOC(CLASS, PARENT)<br>
#define TYPELOC(CLASS, PARENT) \<br>
unsigned Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \<br>
- return TyLoc.getFullDataSize(); \<br>
+ return TyLoc.getLocalDataSize(); \<br>
}<br>
#include "clang/AST/TypeLocNodes.def"<br>
};<br>
@@ -54,8 +72,18 @@ namespace {<br>
<br>
/// \brief Returns the size of the type source info data block.<br>
unsigned TypeLoc::getFullDataSizeForType(QualType Ty) {<br>
- if (Ty.isNull()) return 0;<br>
- return TypeSizer().Visit(TypeLoc(Ty, 0));<br>
+ unsigned Total = 0;<br>
+ TypeLoc TyLoc(Ty, 0);<br>
+ unsigned MaxAlign = 1;<br>
+ while (!TyLoc.isNull()) {<br>
+ unsigned Align = getLocalAlignmentForType(TyLoc.getType());<br>
+ MaxAlign = std::max(Align, MaxAlign);<br>
+ Total = llvm::RoundUpToAlignment(Total, Align);<br>
+ Total += TypeSizer().Visit(TyLoc);<br>
+ TyLoc = TyLoc.getNextTypeLoc();<br>
+ }<br>
+ Total = llvm::RoundUpToAlignment(Total, MaxAlign);<br>
+ return Total;<br>
}<br>
<br>
namespace {<br>
<br>
Modified: cfe/trunk/lib/Sema/CMakeLists.txt<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/CMakeLists.txt?rev=183466&r1=183465&r2=183466&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/CMakeLists.txt?rev=183466&r1=183465&r2=183466&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/Sema/CMakeLists.txt (original)<br>
+++ cfe/trunk/lib/Sema/CMakeLists.txt Thu Jun 6 19:04:31 2013<br>
@@ -51,6 +51,7 @@ add_clang_library(clangSema<br>
SemaTemplateVariadic.cpp<br>
SemaType.cpp<br>
TargetAttributesSema.cpp<br>
+ TypeLocBuilder.cpp<br>
)<br>
<br>
add_dependencies(clangSema<br>
<br>
Modified: cfe/trunk/lib/Sema/SemaLambda.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaLambda.cpp?rev=183466&r1=183465&r2=183466&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaLambda.cpp?rev=183466&r1=183465&r2=183466&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/Sema/SemaLambda.cpp (original)<br>
+++ cfe/trunk/lib/Sema/SemaLambda.cpp Thu Jun 6 19:04:31 2013<br>
@@ -445,6 +445,7 @@ FieldDecl *Sema::checkInitCapture(Source<br>
assert(!DeductType.isNull() && "can't build reference to auto");<br>
TLB.push<ReferenceTypeLoc>(DeductType).setSigilLoc(Loc);<br>
}<br>
+ TypeSourceInfo *TSI = TLB.getTypeSourceInfo(Context, DeductType);<br>
<br>
InitializationKind InitKind = InitializationKind::CreateDefault(Loc);<br>
Expr *Init = InitExpr;<br>
@@ -476,8 +477,7 @@ FieldDecl *Sema::checkInitCapture(Source<br>
else<br>
InitKind = InitializationKind::CreateCopy(Loc, Loc);<br>
QualType DeducedType;<br>
- if (DeduceAutoType(TLB.getTemporaryTypeLoc(DeductType),<br>
- Init, DeducedType) == DAR_Failed) {<br>
+ if (DeduceAutoType(TSI, Init, DeducedType) == DAR_Failed) {<br>
if (isa<InitListExpr>(Init))<br>
Diag(Loc, diag::err_init_capture_deduction_failure_from_init_list)<br>
<< Id << Init->getSourceRange();<br>
@@ -492,7 +492,7 @@ FieldDecl *Sema::checkInitCapture(Source<br>
// the closure type. This member is not a bit-field and not mutable.<br>
// Core issue: the member is (probably...) public.<br>
FieldDecl *NewFD = CheckFieldDecl(<br>
- Id, DeducedType, TLB.getTypeSourceInfo(Context, DeductType), LSI->Lambda,<br>
+ Id, DeducedType, TSI, LSI->Lambda,<br>
Loc, /*Mutable*/ false, /*BitWidth*/ 0, ICIS_NoInit,<br>
Loc, AS_public, /*PrevDecl*/ 0, /*Declarator*/ 0);<br>
LSI->Lambda->addDecl(NewFD);<br>
<br>
Modified: cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp?rev=183466&r1=183465&r2=183466&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp?rev=183466&r1=183465&r2=183466&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp (original)<br>
+++ cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp Thu Jun 6 19:04:31 2013<br>
@@ -18,6 +18,7 @@<br>
#include "clang/Sema/ScopeInfo.h"<br>
#include "clang/Sema/SemaInternal.h"<br>
#include "clang/Sema/Template.h"<br>
+#include "TypeLocBuilder.h"<br>
<br>
using namespace clang;<br>
<br>
@@ -463,17 +464,13 @@ Sema::CheckPackExpansion(TypeSourceInfo<br>
EllipsisLoc, NumExpansions);<br>
if (Result.isNull())<br>
return 0;<br>
-<br>
- TypeSourceInfo *TSResult = Context.CreateTypeSourceInfo(Result);<br>
- PackExpansionTypeLoc TL =<br>
- TSResult->getTypeLoc().castAs<PackExpansionTypeLoc>();<br>
+<br>
+ TypeLocBuilder TLB;<br>
+ TLB.pushFullCopy(Pattern->getTypeLoc());<br>
+ PackExpansionTypeLoc TL = TLB.push<PackExpansionTypeLoc>(Result);<br>
TL.setEllipsisLoc(EllipsisLoc);<br>
-<br>
- // Copy over the source-location information from the type.<br>
- memcpy(TL.getNextTypeLoc().getOpaqueData(),<br>
- Pattern->getTypeLoc().getOpaqueData(),<br>
- Pattern->getTypeLoc().getFullDataSize());<br>
- return TSResult;<br>
+<br>
+ return TLB.getTypeSourceInfo(Context, Result);<br>
}<br>
<br>
QualType Sema::CheckPackExpansion(QualType Pattern, SourceRange PatternRange,<br>
<br>
Modified: cfe/trunk/lib/Sema/TreeTransform.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=183466&r1=183465&r2=183466&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=183466&r1=183465&r2=183466&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/Sema/TreeTransform.h (original)<br>
+++ cfe/trunk/lib/Sema/TreeTransform.h Thu Jun 6 19:04:31 2013<br>
@@ -3427,7 +3427,7 @@ TreeTransform<Derived>::TransformQualifi<br>
} else {<br>
// Otherwise, complain about the addition of a qualifier to an<br>
// already-qualified type.<br>
- SourceRange R = TLB.getTemporaryTypeLoc(Result).getSourceRange();<br>
+ SourceRange R = T.getUnqualifiedLoc().getSourceRange();<br>
SemaRef.Diag(R.getBegin(), diag::err_attr_objc_ownership_redundant)<br>
<< Result << R;<br>
<br>
<br>
Added: cfe/trunk/lib/Sema/TypeLocBuilder.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TypeLocBuilder.cpp?rev=183466&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TypeLocBuilder.cpp?rev=183466&view=auto</a><br>
==============================================================================<br>
--- cfe/trunk/lib/Sema/TypeLocBuilder.cpp (added)<br>
+++ cfe/trunk/lib/Sema/TypeLocBuilder.cpp Thu Jun 6 19:04:31 2013<br>
@@ -0,0 +1,136 @@<br>
+//===--- TypeLocBuilder.cpp - Type Source Info collector ------------------===//<br>
+//<br>
+// The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+//<br>
+// This files defines TypeLocBuilder, a class for building TypeLocs<br>
+// bottom-up.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+#include "TypeLocBuilder.h"<br>
+<br>
+using namespace clang;<br>
+<br>
+void TypeLocBuilder::pushFullCopy(TypeLoc L) {<br>
+ size_t Size = L.getFullDataSize();<br>
+ reserve(Size);<br>
+<br>
+ SmallVector<TypeLoc, 4> TypeLocs;<br>
+ TypeLoc CurTL = L;<br>
+ while (CurTL) {<br>
+ TypeLocs.push_back(CurTL);<br>
+ CurTL = CurTL.getNextTypeLoc();<br>
+ }<br>
+<br>
+ for (unsigned i = 0, e = TypeLocs.size(); i < e; ++i) {<br>
+ TypeLoc CurTL = TypeLocs[e-i-1];<br>
+ switch (CurTL.getTypeLocClass()) {<br>
+#define ABSTRACT_TYPELOC(CLASS, PARENT)<br>
+#define TYPELOC(CLASS, PARENT) \<br>
+ case TypeLoc::CLASS: { \<br>
+ CLASS##TypeLoc NewTL = push<class CLASS##TypeLoc>(CurTL.getType()); \<br>
+ memcpy(NewTL.getOpaqueData(), CurTL.getOpaqueData(), NewTL.getLocalDataSize()); \<br>
+ break; \<br>
+ }<br>
+#include "clang/AST/TypeLocNodes.def"<br>
+ }<br>
+ }<br>
+}<br>
+<br>
+void TypeLocBuilder::grow(size_t NewCapacity) {<br>
+ assert(NewCapacity > Capacity);<br>
+<br>
+ // Allocate the new buffer and copy the old data into it.<br>
+ char *NewBuffer = new char[NewCapacity];<br>
+ unsigned NewIndex = Index + NewCapacity - Capacity;<br>
+ memcpy(&NewBuffer[NewIndex],<br>
+ &Buffer[Index],<br>
+ Capacity - Index);<br>
+<br>
+ if (Buffer != InlineBuffer.buffer)<br>
+ delete[] Buffer;<br>
+<br>
+ Buffer = NewBuffer;<br>
+ Capacity = NewCapacity;<br>
+ Index = NewIndex;<br>
+}<br>
+<br>
+TypeLoc TypeLocBuilder::pushImpl(QualType T, size_t LocalSize, unsigned LocalAlignment) {<br>
+#ifndef NDEBUG<br>
+ QualType TLast = TypeLoc(T, 0).getNextTypeLoc().getType();<br>
+ assert(TLast == LastTy &&<br>
+ "mismatch between last type and new type's inner type");<br>
+ LastTy = T;<br>
+#endif<br>
+<br>
+ assert(LocalAlignment <= BufferMaxAlignment && "Unexpected alignment");<br>
+<br>
+ // If we need to grow, grow by a factor of 2.<br>
+ if (LocalSize > Index) {<br>
+ size_t RequiredCapacity = Capacity + (LocalSize - Index);<br>
+ size_t NewCapacity = Capacity * 2;<br>
+ while (RequiredCapacity > NewCapacity)<br>
+ NewCapacity *= 2;<br>
+ grow(NewCapacity);<br>
+ }<br>
+<br>
+ // Because we're adding elements to the TypeLoc backwards, we have to<br>
+ // do some extra work to keep everything aligned appropriately.<br>
+ // FIXME: This algorithm is a absolute mess because every TypeLoc returned<br>
+ // needs to be valid. Partial TypeLocs are a terrible idea.<br>
+ // FIXME: 4 and 8 are sufficient at the moment, but it's pretty ugly to<br>
+ // hardcode them.<br>
+ if (LocalAlignment == 4) {<br>
+ if (NumBytesAtAlign8 == 0) {<br>
+ NumBytesAtAlign4 += LocalSize;<br>
+ } else {<br>
+ unsigned Padding = NumBytesAtAlign4 % 8;<br>
+ if (Padding == 0) {<br>
+ if (LocalSize % 8 == 0) {<br>
+ // Everything is set: there's no padding and we don't need to add<br>
+ // any.<br>
+ } else {<br>
+ assert(LocalSize % 8 == 4);<br>
+ // No existing padding; add in 4 bytes padding<br>
+ memmove(&Buffer[Index - 4], &Buffer[Index], NumBytesAtAlign4);<br>
+ Index -= 4;<br>
+ }<br>
+ } else {<br>
+ assert(Padding == 4);<br>
+ if (LocalSize % 8 == 0) {<br>
+ // Everything is set: there's 4 bytes padding and we don't need<br>
+ // to add any.<br>
+ } else {<br>
+ assert(LocalSize % 8 == 4);<br>
+ // There are 4 bytes padding, but we don't need any; remove it.<br>
+ memmove(&Buffer[Index + 4], &Buffer[Index], NumBytesAtAlign4);<br>
+ Index += 4;<br>
+ }<br>
+ }<br>
+ NumBytesAtAlign4 += LocalSize;<br>
+ }<br>
+ } else if (LocalAlignment == 8) {<br>
+ if (!NumBytesAtAlign8 && NumBytesAtAlign4 % 8 != 0) {<br>
+ // No existing padding and misaligned members; add in 4 bytes padding<br>
+ memmove(&Buffer[Index - 4], &Buffer[Index], NumBytesAtAlign4);<br>
+ Index -= 4;<br>
+ }<br>
+ // Forget about any padding.<br>
+ NumBytesAtAlign4 = 0;<br>
+ NumBytesAtAlign8 += LocalSize;<br>
+ } else {<br>
+ assert(LocalSize == 0);<br>
+ }<br>
+<br>
+ Index -= LocalSize;<br>
+<br>
+ assert(Capacity - Index == TypeLoc::getFullDataSizeForType(T) &&<br>
+ "incorrect data size provided to CreateTypeSourceInfo!");<br>
+<br>
+ return getTemporaryTypeLoc(T);<br>
+}<br>
<br>
Modified: cfe/trunk/lib/Sema/TypeLocBuilder.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TypeLocBuilder.h?rev=183466&r1=183465&r2=183466&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TypeLocBuilder.h?rev=183466&r1=183465&r2=183466&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/Sema/TypeLocBuilder.h (original)<br>
+++ cfe/trunk/lib/Sema/TypeLocBuilder.h Thu Jun 6 19:04:31 2013<br>
@@ -39,14 +39,19 @@ class TypeLocBuilder {<br>
#endif<br>
<br>
/// The inline buffer.<br>
- char InlineBuffer[InlineCapacity];<br>
+ enum { BufferMaxAlignment = llvm::AlignOf<void*>::Alignment };<br>
+ llvm::AlignedCharArray<BufferMaxAlignment, InlineCapacity> InlineBuffer;<br>
+ unsigned NumBytesAtAlign4, NumBytesAtAlign8;<br>
<br>
public:<br>
TypeLocBuilder()<br>
- : Buffer(InlineBuffer), Capacity(InlineCapacity), Index(InlineCapacity) {}<br>
+ : Buffer(InlineBuffer.buffer), Capacity(InlineCapacity),<br>
+ Index(InlineCapacity), NumBytesAtAlign4(0), NumBytesAtAlign8(0)<br>
+ {<br>
+ }<br>
<br>
~TypeLocBuilder() {<br>
- if (Buffer != InlineBuffer)<br>
+ if (Buffer != InlineBuffer.buffer)<br>
delete[] Buffer;<br>
}<br>
<br>
@@ -59,23 +64,14 @@ class TypeLocBuilder {<br>
<br>
/// Pushes a copy of the given TypeLoc onto this builder. The builder<br>
/// must be empty for this to work.<br>
- void pushFullCopy(TypeLoc L) {<br>
- size_t Size = L.getFullDataSize();<br>
- TypeLoc Copy = pushFullUninitializedImpl(L.getType(), Size);<br>
- memcpy(Copy.getOpaqueData(), L.getOpaqueData(), Size);<br>
- }<br>
-<br>
- /// Pushes uninitialized space for the given type. The builder must<br>
- /// be empty.<br>
- TypeLoc pushFullUninitialized(QualType T) {<br>
- return pushFullUninitializedImpl(T, TypeLoc::getFullDataSizeForType(T));<br>
- }<br>
+ void pushFullCopy(TypeLoc L);<br>
<br>
/// Pushes space for a typespec TypeLoc. Invalidates any TypeLocs<br>
/// previously retrieved from this builder.<br>
TypeSpecTypeLoc pushTypeSpec(QualType T) {<br>
size_t LocalSize = TypeSpecTypeLoc::LocalDataSize;<br>
- return pushImpl(T, LocalSize).castAs<TypeSpecTypeLoc>();<br>
+ unsigned LocalAlign = TypeSpecTypeLoc::LocalDataAlignment;<br>
+ return pushImpl(T, LocalSize, LocalAlign).castAs<TypeSpecTypeLoc>();<br>
}<br>
<br>
/// Resets this builder to the newly-initialized state.<br>
@@ -84,6 +80,7 @@ class TypeLocBuilder {<br>
LastTy = QualType();<br>
#endif<br>
Index = Capacity;<br>
+ NumBytesAtAlign4 = NumBytesAtAlign8 = 0;<br>
}<br>
<br>
/// \brief Tell the TypeLocBuilder that the type it is storing has been<br>
@@ -97,8 +94,10 @@ class TypeLocBuilder {<br>
/// Pushes space for a new TypeLoc of the given type. Invalidates<br>
/// any TypeLocs previously retrieved from this builder.<br>
template <class TyLocType> TyLocType push(QualType T) {<br>
- size_t LocalSize = TypeLoc(T, 0).castAs<TyLocType>().getLocalDataSize();<br>
- return pushImpl(T, LocalSize).castAs<TyLocType>();<br>
+ TyLocType Loc = TypeLoc(T, 0).castAs<TyLocType>();<br>
+ size_t LocalSize = Loc.getLocalDataSize();<br>
+ unsigned LocalAlign = Loc.getLocalDataAlignment();<br>
+ return pushImpl(T, LocalSize, LocalAlign).castAs<TyLocType>();<br>
}<br>
<br>
/// Creates a TypeSourceInfo for the given type.<br>
@@ -127,61 +126,12 @@ class TypeLocBuilder {<br>
}<br>
<br>
private:<br>
- TypeLoc pushImpl(QualType T, size_t LocalSize) {<br>
-#ifndef NDEBUG<br>
- QualType TLast = TypeLoc(T, 0).getNextTypeLoc().getType();<br>
- assert(TLast == LastTy &&<br>
- "mismatch between last type and new type's inner type");<br>
- LastTy = T;<br>
-#endif<br>
-<br>
- // If we need to grow, grow by a factor of 2.<br>
- if (LocalSize > Index) {<br>
- size_t RequiredCapacity = Capacity + (LocalSize - Index);<br>
- size_t NewCapacity = Capacity * 2;<br>
- while (RequiredCapacity > NewCapacity)<br>
- NewCapacity *= 2;<br>
- grow(NewCapacity);<br>
- }<br>
<br>
- Index -= LocalSize;<br>
-<br>
- return getTemporaryTypeLoc(T);<br>
- }<br>
+ TypeLoc pushImpl(QualType T, size_t LocalSize, unsigned LocalAlignment);<br>
<br>
/// Grow to the given capacity.<br>
- void grow(size_t NewCapacity) {<br>
- assert(NewCapacity > Capacity);<br>
-<br>
- // Allocate the new buffer and copy the old data into it.<br>
- char *NewBuffer = new char[NewCapacity];<br>
- unsigned NewIndex = Index + NewCapacity - Capacity;<br>
- memcpy(&NewBuffer[NewIndex],<br>
- &Buffer[Index],<br>
- Capacity - Index);<br>
-<br>
- if (Buffer != InlineBuffer)<br>
- delete[] Buffer;<br>
-<br>
- Buffer = NewBuffer;<br>
- Capacity = NewCapacity;<br>
- Index = NewIndex;<br>
- }<br>
-<br>
- TypeLoc pushFullUninitializedImpl(QualType T, size_t Size) {<br>
-#ifndef NDEBUG<br>
- assert(LastTy.isNull() && "pushing full on non-empty TypeLocBuilder");<br>
- LastTy = T;<br>
-#endif<br>
- assert(Index == Capacity && "pushing full on non-empty TypeLocBuilder");<br>
-<br>
- reserve(Size);<br>
- Index -= Size;<br>
-<br>
- return getTemporaryTypeLoc(T);<br>
- }<br>
+ void grow(size_t NewCapacity);<br>
<br>
-public:<br>
/// \brief Retrieve a temporary TypeLoc that refers into this \c TypeLocBuilder<br>
/// object.<br>
///<br>
<br>
<br>
_______________________________________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@cs.uiuc.edu" target="_blank">cfe-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits</a><br>
</blockquote></div><br></div>
</div></div></blockquote></div><br></div>
</div></div></blockquote></div><br></div>