forked from OSchip/llvm-project
Inline storage of attributes in AttributedStmt.
llvm-svn: 159925
This commit is contained in:
parent
75b9cfd1f0
commit
20f6fc6220
|
@ -149,8 +149,10 @@ typedef SmallVector<const Attr*, 2> ConstAttrVec;
|
|||
|
||||
/// specific_attr_iterator - Iterates over a subrange of an AttrVec, only
|
||||
/// providing attributes that are of a specifc type.
|
||||
template <typename SpecificAttr>
|
||||
template <typename SpecificAttr, typename Container = AttrVec>
|
||||
class specific_attr_iterator {
|
||||
typedef typename Container::const_iterator Iterator;
|
||||
|
||||
/// Current - The current, underlying iterator.
|
||||
/// In order to ensure we don't dereference an invalid iterator unless
|
||||
/// specifically requested, we don't necessarily advance this all the
|
||||
|
@ -158,14 +160,14 @@ class specific_attr_iterator {
|
|||
/// operation is acting on what should be a past-the-end iterator,
|
||||
/// then we offer no guarantees, but this way we do not dererence a
|
||||
/// past-the-end iterator when we move to a past-the-end position.
|
||||
mutable AttrVec::const_iterator Current;
|
||||
mutable Iterator Current;
|
||||
|
||||
void AdvanceToNext() const {
|
||||
while (!isa<SpecificAttr>(*Current))
|
||||
++Current;
|
||||
}
|
||||
|
||||
void AdvanceToNext(AttrVec::const_iterator I) const {
|
||||
void AdvanceToNext(Iterator I) const {
|
||||
while (Current != I && !isa<SpecificAttr>(*Current))
|
||||
++Current;
|
||||
}
|
||||
|
@ -178,7 +180,7 @@ public:
|
|||
typedef std::ptrdiff_t difference_type;
|
||||
|
||||
specific_attr_iterator() : Current() { }
|
||||
explicit specific_attr_iterator(AttrVec::const_iterator i) : Current(i) { }
|
||||
explicit specific_attr_iterator(Iterator i) : Current(i) { }
|
||||
|
||||
reference operator*() const {
|
||||
AdvanceToNext();
|
||||
|
@ -213,23 +215,27 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
inline specific_attr_iterator<T> specific_attr_begin(const AttrVec& vec) {
|
||||
return specific_attr_iterator<T>(vec.begin());
|
||||
template <typename SpecificAttr, typename Container>
|
||||
inline specific_attr_iterator<SpecificAttr, Container>
|
||||
specific_attr_begin(const Container& container) {
|
||||
return specific_attr_iterator<SpecificAttr, Container>(container.begin());
|
||||
}
|
||||
template <typename T>
|
||||
inline specific_attr_iterator<T> specific_attr_end(const AttrVec& vec) {
|
||||
return specific_attr_iterator<T>(vec.end());
|
||||
template <typename SpecificAttr, typename Container>
|
||||
inline specific_attr_iterator<SpecificAttr, Container>
|
||||
specific_attr_end(const Container& container) {
|
||||
return specific_attr_iterator<SpecificAttr, Container>(container.end());
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline bool hasSpecificAttr(const AttrVec& vec) {
|
||||
return specific_attr_begin<T>(vec) != specific_attr_end<T>(vec);
|
||||
template <typename SpecificAttr, typename Container>
|
||||
inline bool hasSpecificAttr(const Container& container) {
|
||||
return specific_attr_begin<SpecificAttr>(container) !=
|
||||
specific_attr_end<SpecificAttr>(container);
|
||||
}
|
||||
template <typename T>
|
||||
inline T *getSpecificAttr(const AttrVec& vec) {
|
||||
specific_attr_iterator<T> i = specific_attr_begin<T>(vec);
|
||||
if (i != specific_attr_end<T>(vec))
|
||||
template <typename SpecificAttr, typename Container>
|
||||
inline SpecificAttr *getSpecificAttr(const Container& container) {
|
||||
specific_attr_iterator<SpecificAttr, Container> i =
|
||||
specific_attr_begin<SpecificAttr>(container);
|
||||
if (i != specific_attr_end<SpecificAttr>(container))
|
||||
return *i;
|
||||
else
|
||||
return 0;
|
||||
|
|
|
@ -797,24 +797,32 @@ public:
|
|||
class AttributedStmt : public Stmt {
|
||||
Stmt *SubStmt;
|
||||
SourceLocation AttrLoc;
|
||||
AttrVec Attrs;
|
||||
// TODO: It can be done as Attr *Attrs[1]; and variable size array as in
|
||||
// StringLiteral
|
||||
unsigned NumAttrs;
|
||||
const Attr *Attrs[1];
|
||||
|
||||
friend class ASTStmtReader;
|
||||
|
||||
public:
|
||||
AttributedStmt(SourceLocation loc, const AttrVec &attrs, Stmt *substmt)
|
||||
: Stmt(AttributedStmtClass), SubStmt(substmt), AttrLoc(loc), Attrs(attrs) {
|
||||
AttributedStmt(SourceLocation Loc, ArrayRef<const Attr*> Attrs, Stmt *SubStmt)
|
||||
: Stmt(AttributedStmtClass), SubStmt(SubStmt), AttrLoc(Loc),
|
||||
NumAttrs(Attrs.size()) {
|
||||
memcpy(this->Attrs, Attrs.data(), Attrs.size() * sizeof(Attr*));
|
||||
}
|
||||
|
||||
// \brief Build an empty attributed statement.
|
||||
explicit AttributedStmt(EmptyShell Empty)
|
||||
: Stmt(AttributedStmtClass, Empty) {
|
||||
explicit AttributedStmt(EmptyShell Empty, unsigned NumAttrs)
|
||||
: Stmt(AttributedStmtClass, Empty), NumAttrs(NumAttrs) {
|
||||
memset(Attrs, 0, NumAttrs * sizeof(Attr*));
|
||||
}
|
||||
|
||||
public:
|
||||
static AttributedStmt *Create(ASTContext &C, SourceLocation Loc,
|
||||
ArrayRef<const Attr*> Attrs, Stmt *SubStmt);
|
||||
// \brief Build an empty attributed statement.
|
||||
static AttributedStmt *CreateEmpty(ASTContext &C, unsigned NumAttrs);
|
||||
|
||||
SourceLocation getAttrLoc() const { return AttrLoc; }
|
||||
const AttrVec &getAttrs() const { return Attrs; }
|
||||
ArrayRef<const Attr*> getAttrs() const {
|
||||
return ArrayRef<const Attr*>(Attrs, NumAttrs);
|
||||
}
|
||||
Stmt *getSubStmt() { return SubStmt; }
|
||||
const Stmt *getSubStmt() const { return SubStmt; }
|
||||
|
||||
|
|
|
@ -2467,7 +2467,8 @@ public:
|
|||
StmtResult ActOnLabelStmt(SourceLocation IdentLoc, LabelDecl *TheDecl,
|
||||
SourceLocation ColonLoc, Stmt *SubStmt);
|
||||
|
||||
StmtResult ActOnAttributedStmt(SourceLocation AttrLoc, const AttrVec &Attrs,
|
||||
StmtResult ActOnAttributedStmt(SourceLocation AttrLoc,
|
||||
ArrayRef<const Attr*> Attrs,
|
||||
Stmt *SubStmt);
|
||||
|
||||
StmtResult ActOnIfStmt(SourceLocation IfLoc,
|
||||
|
|
|
@ -427,7 +427,7 @@ private:
|
|||
void WriteReferencedSelectorsPool(Sema &SemaRef);
|
||||
void WriteIdentifierTable(Preprocessor &PP, IdentifierResolver &IdResolver,
|
||||
bool IsModule);
|
||||
void WriteAttributes(const AttrVec &Attrs, RecordDataImpl &Record);
|
||||
void WriteAttributes(ArrayRef<const Attr*> Attrs, RecordDataImpl &Record);
|
||||
void ResolveDeclUpdatesBlocks();
|
||||
void WriteDeclUpdatesBlocks();
|
||||
void WriteDeclReplacementsBlock();
|
||||
|
|
|
@ -273,6 +273,23 @@ const char *LabelStmt::getName() const {
|
|||
return getDecl()->getIdentifier()->getNameStart();
|
||||
}
|
||||
|
||||
AttributedStmt *AttributedStmt::Create(ASTContext &C, SourceLocation Loc,
|
||||
ArrayRef<const Attr*> Attrs,
|
||||
Stmt *SubStmt) {
|
||||
void *Mem = C.Allocate(sizeof(AttributedStmt) +
|
||||
sizeof(Attr*) * (Attrs.size() - 1),
|
||||
llvm::alignOf<AttributedStmt>());
|
||||
return new (Mem) AttributedStmt(Loc, Attrs, SubStmt);
|
||||
}
|
||||
|
||||
AttributedStmt *AttributedStmt::CreateEmpty(ASTContext &C, unsigned NumAttrs) {
|
||||
assert(NumAttrs > 0 && "NumAttrs should be greater than zero");
|
||||
void *Mem = C.Allocate(sizeof(AttributedStmt) +
|
||||
sizeof(Attr*) * (NumAttrs - 1),
|
||||
llvm::alignOf<AttributedStmt>());
|
||||
return new (Mem) AttributedStmt(EmptyShell(), NumAttrs);
|
||||
}
|
||||
|
||||
// This is defined here to avoid polluting Stmt.h with importing Expr.h
|
||||
SourceRange ReturnStmt::getSourceRange() const {
|
||||
if (RetExpr)
|
||||
|
|
|
@ -173,9 +173,9 @@ void StmtPrinter::VisitLabelStmt(LabelStmt *Node) {
|
|||
void StmtPrinter::VisitAttributedStmt(AttributedStmt *Node) {
|
||||
OS << "[[";
|
||||
bool first = true;
|
||||
for (AttrVec::const_iterator it = Node->getAttrs().begin(),
|
||||
end = Node->getAttrs().end();
|
||||
it != end; ++it) {
|
||||
for (ArrayRef<const Attr*>::iterator it = Node->getAttrs().begin(),
|
||||
end = Node->getAttrs().end();
|
||||
it != end; ++it) {
|
||||
if (!first) {
|
||||
OS << ", ";
|
||||
first = false;
|
||||
|
|
|
@ -370,12 +370,10 @@ Sema::ActOnLabelStmt(SourceLocation IdentLoc, LabelDecl *TheDecl,
|
|||
}
|
||||
|
||||
StmtResult Sema::ActOnAttributedStmt(SourceLocation AttrLoc,
|
||||
const AttrVec &Attrs,
|
||||
ArrayRef<const Attr*> Attrs,
|
||||
Stmt *SubStmt) {
|
||||
// Fill in the declaration and return it. Variable length will require to
|
||||
// change this to AttributedStmt::Create(Context, ....);
|
||||
// and probably using ArrayRef
|
||||
AttributedStmt *LS = new (Context) AttributedStmt(AttrLoc, Attrs, SubStmt);
|
||||
// Fill in the declaration and return it.
|
||||
AttributedStmt *LS = AttributedStmt::Create(Context, AttrLoc, Attrs, SubStmt);
|
||||
return Owned(LS);
|
||||
}
|
||||
|
||||
|
|
|
@ -61,7 +61,7 @@ static Attr *ProcessStmtAttribute(Sema &S, Stmt *St, const AttributeList &A,
|
|||
|
||||
StmtResult Sema::ProcessStmtAttributes(Stmt *S, AttributeList *AttrList,
|
||||
SourceRange Range) {
|
||||
AttrVec Attrs;
|
||||
SmallVector<const Attr*, 8> Attrs;
|
||||
for (const AttributeList* l = AttrList; l; l = l->getNext()) {
|
||||
if (Attr *a = ProcessStmtAttribute(*this, S, *l, Range))
|
||||
Attrs.push_back(a);
|
||||
|
|
|
@ -1050,7 +1050,8 @@ public:
|
|||
///
|
||||
/// By default, performs semantic analysis to build the new statement.
|
||||
/// Subclasses may override this routine to provide different behavior.
|
||||
StmtResult RebuildAttributedStmt(SourceLocation AttrLoc, const AttrVec &Attrs,
|
||||
StmtResult RebuildAttributedStmt(SourceLocation AttrLoc,
|
||||
ArrayRef<const Attr*> Attrs,
|
||||
Stmt *SubStmt) {
|
||||
return SemaRef.ActOnAttributedStmt(AttrLoc, Attrs, SubStmt);
|
||||
}
|
||||
|
|
|
@ -162,9 +162,12 @@ void ASTStmtReader::VisitLabelStmt(LabelStmt *S) {
|
|||
|
||||
void ASTStmtReader::VisitAttributedStmt(AttributedStmt *S) {
|
||||
VisitStmt(S);
|
||||
uint64_t NumAttrs = Record[Idx++];
|
||||
AttrVec Attrs;
|
||||
Reader.ReadAttributes(F, Attrs, Record, Idx);
|
||||
S->Attrs = Attrs;
|
||||
assert(NumAttrs == S->NumAttrs);
|
||||
assert(NumAttrs == Attrs.size());
|
||||
std::copy(Attrs.begin(), Attrs.end(), S->Attrs);
|
||||
S->SubStmt = Reader.ReadSubStmt();
|
||||
S->AttrLoc = ReadSourceLocation(Record, Idx);
|
||||
}
|
||||
|
@ -1648,7 +1651,9 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) {
|
|||
break;
|
||||
|
||||
case STMT_ATTRIBUTED:
|
||||
S = new (Context) AttributedStmt(Empty);
|
||||
S = AttributedStmt::CreateEmpty(
|
||||
Context,
|
||||
/*NumAttrs*/Record[ASTStmtReader::NumStmtFields]);
|
||||
break;
|
||||
|
||||
case STMT_IF:
|
||||
|
|
|
@ -3086,10 +3086,12 @@ void ASTWriter::WriteMergedDecls() {
|
|||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/// \brief Write a record containing the given attributes.
|
||||
void ASTWriter::WriteAttributes(const AttrVec &Attrs, RecordDataImpl &Record) {
|
||||
void ASTWriter::WriteAttributes(ArrayRef<const Attr*> Attrs,
|
||||
RecordDataImpl &Record) {
|
||||
Record.push_back(Attrs.size());
|
||||
for (AttrVec::const_iterator i = Attrs.begin(), e = Attrs.end(); i != e; ++i){
|
||||
const Attr * A = *i;
|
||||
for (ArrayRef<const Attr *>::iterator i = Attrs.begin(),
|
||||
e = Attrs.end(); i != e; ++i){
|
||||
const Attr *A = *i;
|
||||
Record.push_back(A->getKind()); // FIXME: stable encoding, target attrs
|
||||
AddSourceRange(A->getRange(), Record);
|
||||
|
||||
|
|
|
@ -151,7 +151,8 @@ void ASTDeclWriter::VisitDecl(Decl *D) {
|
|||
Record.push_back(D->isInvalidDecl());
|
||||
Record.push_back(D->hasAttrs());
|
||||
if (D->hasAttrs())
|
||||
Writer.WriteAttributes(D->getAttrs(), Record);
|
||||
Writer.WriteAttributes(ArrayRef<const Attr*>(D->getAttrs().begin(),
|
||||
D->getAttrs().size()), Record);
|
||||
Record.push_back(D->isImplicit());
|
||||
Record.push_back(D->isUsed(false));
|
||||
Record.push_back(D->isReferenced());
|
||||
|
|
|
@ -109,6 +109,7 @@ void ASTStmtWriter::VisitLabelStmt(LabelStmt *S) {
|
|||
|
||||
void ASTStmtWriter::VisitAttributedStmt(AttributedStmt *S) {
|
||||
VisitStmt(S);
|
||||
Record.push_back(S->getAttrs().size());
|
||||
Writer.WriteAttributes(S->getAttrs(), Record);
|
||||
Writer.AddStmt(S->getSubStmt());
|
||||
Writer.AddSourceLocation(S->getAttrLoc(), Record);
|
||||
|
|
Loading…
Reference in New Issue