[TrailingObjects] Convert OffsetOfExpr.

That necessitated moving the OffsetOfNode class out of OffsetOfExpr.

llvm-svn: 256590
This commit is contained in:
James Y Knight 2015-12-29 22:31:18 +00:00
parent e77de75d7e
commit 7281c357b1
11 changed files with 161 additions and 166 deletions

View File

@ -1749,6 +1749,99 @@ public:
child_range children() { return child_range(&Val, &Val+1); }
};
/// Helper class for OffsetOfExpr.
// __builtin_offsetof(type, identifier(.identifier|[expr])*)
class OffsetOfNode {
public:
/// \brief The kind of offsetof node we have.
enum Kind {
/// \brief An index into an array.
Array = 0x00,
/// \brief A field.
Field = 0x01,
/// \brief A field in a dependent type, known only by its name.
Identifier = 0x02,
/// \brief An implicit indirection through a C++ base class, when the
/// field found is in a base class.
Base = 0x03
};
private:
enum { MaskBits = 2, Mask = 0x03 };
/// \brief The source range that covers this part of the designator.
SourceRange Range;
/// \brief The data describing the designator, which comes in three
/// different forms, depending on the lower two bits.
/// - An unsigned index into the array of Expr*'s stored after this node
/// in memory, for [constant-expression] designators.
/// - A FieldDecl*, for references to a known field.
/// - An IdentifierInfo*, for references to a field with a given name
/// when the class type is dependent.
/// - A CXXBaseSpecifier*, for references that look at a field in a
/// base class.
uintptr_t Data;
public:
/// \brief Create an offsetof node that refers to an array element.
OffsetOfNode(SourceLocation LBracketLoc, unsigned Index,
SourceLocation RBracketLoc)
: Range(LBracketLoc, RBracketLoc), Data((Index << 2) | Array) {}
/// \brief Create an offsetof node that refers to a field.
OffsetOfNode(SourceLocation DotLoc, FieldDecl *Field, SourceLocation NameLoc)
: Range(DotLoc.isValid() ? DotLoc : NameLoc, NameLoc),
Data(reinterpret_cast<uintptr_t>(Field) | OffsetOfNode::Field) {}
/// \brief Create an offsetof node that refers to an identifier.
OffsetOfNode(SourceLocation DotLoc, IdentifierInfo *Name,
SourceLocation NameLoc)
: Range(DotLoc.isValid() ? DotLoc : NameLoc, NameLoc),
Data(reinterpret_cast<uintptr_t>(Name) | Identifier) {}
/// \brief Create an offsetof node that refers into a C++ base class.
explicit OffsetOfNode(const CXXBaseSpecifier *Base)
: Range(), Data(reinterpret_cast<uintptr_t>(Base) | OffsetOfNode::Base) {}
/// \brief Determine what kind of offsetof node this is.
Kind getKind() const { return static_cast<Kind>(Data & Mask); }
/// \brief For an array element node, returns the index into the array
/// of expressions.
unsigned getArrayExprIndex() const {
assert(getKind() == Array);
return Data >> 2;
}
/// \brief For a field offsetof node, returns the field.
FieldDecl *getField() const {
assert(getKind() == Field);
return reinterpret_cast<FieldDecl *>(Data & ~(uintptr_t)Mask);
}
/// \brief For a field or identifier offsetof node, returns the name of
/// the field.
IdentifierInfo *getFieldName() const;
/// \brief For a base class node, returns the base specifier.
CXXBaseSpecifier *getBase() const {
assert(getKind() == Base);
return reinterpret_cast<CXXBaseSpecifier *>(Data & ~(uintptr_t)Mask);
}
/// \brief Retrieve the source range that covers this offsetof node.
///
/// For an array element node, the source range contains the locations of
/// the square brackets. For a field or identifier node, the source range
/// contains the location of the period (if there is one) and the
/// identifier.
SourceRange getSourceRange() const LLVM_READONLY { return Range; }
SourceLocation getLocStart() const LLVM_READONLY { return Range.getBegin(); }
SourceLocation getLocEnd() const LLVM_READONLY { return Range.getEnd(); }
};
/// OffsetOfExpr - [C99 7.17] - This represents an expression of the form
/// offsetof(record-type, member-designator). For example, given:
/// @code
@ -1763,104 +1856,9 @@ public:
/// @endcode
/// we can represent and evaluate the expression @c offsetof(struct T, s[2].d).
class OffsetOfExpr : public Expr {
public:
// __builtin_offsetof(type, identifier(.identifier|[expr])*)
class OffsetOfNode {
public:
/// \brief The kind of offsetof node we have.
enum Kind {
/// \brief An index into an array.
Array = 0x00,
/// \brief A field.
Field = 0x01,
/// \brief A field in a dependent type, known only by its name.
Identifier = 0x02,
/// \brief An implicit indirection through a C++ base class, when the
/// field found is in a base class.
Base = 0x03
};
private:
enum { MaskBits = 2, Mask = 0x03 };
/// \brief The source range that covers this part of the designator.
SourceRange Range;
/// \brief The data describing the designator, which comes in three
/// different forms, depending on the lower two bits.
/// - An unsigned index into the array of Expr*'s stored after this node
/// in memory, for [constant-expression] designators.
/// - A FieldDecl*, for references to a known field.
/// - An IdentifierInfo*, for references to a field with a given name
/// when the class type is dependent.
/// - A CXXBaseSpecifier*, for references that look at a field in a
/// base class.
uintptr_t Data;
public:
/// \brief Create an offsetof node that refers to an array element.
OffsetOfNode(SourceLocation LBracketLoc, unsigned Index,
SourceLocation RBracketLoc)
: Range(LBracketLoc, RBracketLoc), Data((Index << 2) | Array) { }
/// \brief Create an offsetof node that refers to a field.
OffsetOfNode(SourceLocation DotLoc, FieldDecl *Field,
SourceLocation NameLoc)
: Range(DotLoc.isValid()? DotLoc : NameLoc, NameLoc),
Data(reinterpret_cast<uintptr_t>(Field) | OffsetOfNode::Field) { }
/// \brief Create an offsetof node that refers to an identifier.
OffsetOfNode(SourceLocation DotLoc, IdentifierInfo *Name,
SourceLocation NameLoc)
: Range(DotLoc.isValid()? DotLoc : NameLoc, NameLoc),
Data(reinterpret_cast<uintptr_t>(Name) | Identifier) { }
/// \brief Create an offsetof node that refers into a C++ base class.
explicit OffsetOfNode(const CXXBaseSpecifier *Base)
: Range(), Data(reinterpret_cast<uintptr_t>(Base) | OffsetOfNode::Base) {}
/// \brief Determine what kind of offsetof node this is.
Kind getKind() const {
return static_cast<Kind>(Data & Mask);
}
/// \brief For an array element node, returns the index into the array
/// of expressions.
unsigned getArrayExprIndex() const {
assert(getKind() == Array);
return Data >> 2;
}
/// \brief For a field offsetof node, returns the field.
FieldDecl *getField() const {
assert(getKind() == Field);
return reinterpret_cast<FieldDecl *>(Data & ~(uintptr_t)Mask);
}
/// \brief For a field or identifier offsetof node, returns the name of
/// the field.
IdentifierInfo *getFieldName() const;
/// \brief For a base class node, returns the base specifier.
CXXBaseSpecifier *getBase() const {
assert(getKind() == Base);
return reinterpret_cast<CXXBaseSpecifier *>(Data & ~(uintptr_t)Mask);
}
/// \brief Retrieve the source range that covers this offsetof node.
///
/// For an array element node, the source range contains the locations of
/// the square brackets. For a field or identifier node, the source range
/// contains the location of the period (if there is one) and the
/// identifier.
SourceRange getSourceRange() const LLVM_READONLY { return Range; }
SourceLocation getLocStart() const LLVM_READONLY { return Range.getBegin(); }
SourceLocation getLocEnd() const LLVM_READONLY { return Range.getEnd(); }
};
private:
class OffsetOfExpr final
: public Expr,
private llvm::TrailingObjects<OffsetOfExpr, OffsetOfNode, Expr *> {
SourceLocation OperatorLoc, RParenLoc;
// Base type;
TypeSourceInfo *TSInfo;
@ -1869,6 +1867,10 @@ private:
// Number of sub-expressions (i.e. array subscript expressions).
unsigned NumExprs;
size_t numTrailingObjects(OverloadToken<OffsetOfNode>) const {
return NumComps;
}
OffsetOfExpr(const ASTContext &C, QualType type,
SourceLocation OperatorLoc, TypeSourceInfo *tsi,
ArrayRef<OffsetOfNode> comps, ArrayRef<Expr*> exprs,
@ -1905,12 +1907,12 @@ public:
const OffsetOfNode &getComponent(unsigned Idx) const {
assert(Idx < NumComps && "Subscript out of range");
return reinterpret_cast<const OffsetOfNode *> (this + 1)[Idx];
return getTrailingObjects<OffsetOfNode>()[Idx];
}
void setComponent(unsigned Idx, OffsetOfNode ON) {
assert(Idx < NumComps && "Subscript out of range");
reinterpret_cast<OffsetOfNode *> (this + 1)[Idx] = ON;
getTrailingObjects<OffsetOfNode>()[Idx] = ON;
}
unsigned getNumComponents() const {
@ -1919,17 +1921,17 @@ public:
Expr* getIndexExpr(unsigned Idx) {
assert(Idx < NumExprs && "Subscript out of range");
return reinterpret_cast<Expr **>(
reinterpret_cast<OffsetOfNode *>(this+1) + NumComps)[Idx];
return getTrailingObjects<Expr *>()[Idx];
}
const Expr *getIndexExpr(unsigned Idx) const {
return const_cast<OffsetOfExpr*>(this)->getIndexExpr(Idx);
assert(Idx < NumExprs && "Subscript out of range");
return getTrailingObjects<Expr *>()[Idx];
}
void setIndexExpr(unsigned Idx, Expr* E) {
assert(Idx < NumComps && "Subscript out of range");
reinterpret_cast<Expr **>(
reinterpret_cast<OffsetOfNode *>(this+1) + NumComps)[Idx] = E;
getTrailingObjects<Expr *>()[Idx] = E;
}
unsigned getNumExpressions() const {
@ -1945,11 +1947,10 @@ public:
// Iterators
child_range children() {
Stmt **begin =
reinterpret_cast<Stmt**>(reinterpret_cast<OffsetOfNode*>(this + 1)
+ NumComps);
Stmt **begin = reinterpret_cast<Stmt **>(getTrailingObjects<Expr *>());
return child_range(begin, begin + NumExprs);
}
friend TrailingObjects;
};
/// UnaryExprOrTypeTraitExpr - expression with either a type or (unevaluated)

View File

@ -1314,9 +1314,8 @@ OffsetOfExpr *OffsetOfExpr::Create(const ASTContext &C, QualType type,
ArrayRef<OffsetOfNode> comps,
ArrayRef<Expr*> exprs,
SourceLocation RParenLoc) {
void *Mem = C.Allocate(sizeof(OffsetOfExpr) +
sizeof(OffsetOfNode) * comps.size() +
sizeof(Expr*) * exprs.size());
void *Mem = C.Allocate(
totalSizeToAlloc<OffsetOfNode, Expr *>(comps.size(), exprs.size()));
return new (Mem) OffsetOfExpr(C, type, OperatorLoc, tsi, comps, exprs,
RParenLoc);
@ -1324,9 +1323,8 @@ OffsetOfExpr *OffsetOfExpr::Create(const ASTContext &C, QualType type,
OffsetOfExpr *OffsetOfExpr::CreateEmpty(const ASTContext &C,
unsigned numComps, unsigned numExprs) {
void *Mem = C.Allocate(sizeof(OffsetOfExpr) +
sizeof(OffsetOfNode) * numComps +
sizeof(Expr*) * numExprs);
void *Mem =
C.Allocate(totalSizeToAlloc<OffsetOfNode, Expr *>(numComps, numExprs));
return new (Mem) OffsetOfExpr(numComps, numExprs);
}
@ -1356,7 +1354,7 @@ OffsetOfExpr::OffsetOfExpr(const ASTContext &C, QualType type,
}
}
IdentifierInfo *OffsetOfExpr::OffsetOfNode::getFieldName() const {
IdentifierInfo *OffsetOfNode::getFieldName() const {
assert(getKind() == Field || getKind() == Identifier);
if (getKind() == Field)
return getField()->getIdentifier();

View File

@ -7617,9 +7617,9 @@ bool IntExprEvaluator::VisitOffsetOfExpr(const OffsetOfExpr *OOE) {
return Error(OOE);
QualType CurrentType = OOE->getTypeSourceInfo()->getType();
for (unsigned i = 0; i != n; ++i) {
OffsetOfExpr::OffsetOfNode ON = OOE->getComponent(i);
OffsetOfNode ON = OOE->getComponent(i);
switch (ON.getKind()) {
case OffsetOfExpr::OffsetOfNode::Array: {
case OffsetOfNode::Array: {
const Expr *Idx = OOE->getIndexExpr(ON.getArrayExprIndex());
APSInt IdxResult;
if (!EvaluateInteger(Idx, IdxResult, Info))
@ -7633,7 +7633,7 @@ bool IntExprEvaluator::VisitOffsetOfExpr(const OffsetOfExpr *OOE) {
break;
}
case OffsetOfExpr::OffsetOfNode::Field: {
case OffsetOfNode::Field: {
FieldDecl *MemberDecl = ON.getField();
const RecordType *RT = CurrentType->getAs<RecordType>();
if (!RT)
@ -7648,10 +7648,10 @@ bool IntExprEvaluator::VisitOffsetOfExpr(const OffsetOfExpr *OOE) {
break;
}
case OffsetOfExpr::OffsetOfNode::Identifier:
case OffsetOfNode::Identifier:
llvm_unreachable("dependent __builtin_offsetof");
case OffsetOfExpr::OffsetOfNode::Base: {
case OffsetOfNode::Base: {
CXXBaseSpecifier *BaseSpec = ON.getBase();
if (BaseSpec->isVirtual())
return Error(OOE);

View File

@ -1305,8 +1305,8 @@ void StmtPrinter::VisitOffsetOfExpr(OffsetOfExpr *Node) {
OS << ", ";
bool PrintedSomething = false;
for (unsigned i = 0, n = Node->getNumComponents(); i < n; ++i) {
OffsetOfExpr::OffsetOfNode ON = Node->getComponent(i);
if (ON.getKind() == OffsetOfExpr::OffsetOfNode::Array) {
OffsetOfNode ON = Node->getComponent(i);
if (ON.getKind() == OffsetOfNode::Array) {
// Array node
OS << "[";
PrintExpr(Node->getIndexExpr(ON.getArrayExprIndex()));
@ -1316,7 +1316,7 @@ void StmtPrinter::VisitOffsetOfExpr(OffsetOfExpr *Node) {
}
// Skip implicit base indirections.
if (ON.getKind() == OffsetOfExpr::OffsetOfNode::Base)
if (ON.getKind() == OffsetOfNode::Base)
continue;
// Field or identifier node.

View File

@ -675,22 +675,22 @@ void StmtProfiler::VisitOffsetOfExpr(const OffsetOfExpr *S) {
VisitType(S->getTypeSourceInfo()->getType());
unsigned n = S->getNumComponents();
for (unsigned i = 0; i < n; ++i) {
const OffsetOfExpr::OffsetOfNode& ON = S->getComponent(i);
const OffsetOfNode &ON = S->getComponent(i);
ID.AddInteger(ON.getKind());
switch (ON.getKind()) {
case OffsetOfExpr::OffsetOfNode::Array:
case OffsetOfNode::Array:
// Expressions handled below.
break;
case OffsetOfExpr::OffsetOfNode::Field:
case OffsetOfNode::Field:
VisitDecl(ON.getField());
break;
case OffsetOfExpr::OffsetOfNode::Identifier:
case OffsetOfNode::Identifier:
ID.AddPointer(ON.getFieldName());
break;
case OffsetOfExpr::OffsetOfNode::Base:
case OffsetOfNode::Base:
// These nodes are implicit, and therefore don't need profiling.
break;
}

View File

@ -1924,10 +1924,10 @@ Value *ScalarExprEmitter::VisitOffsetOfExpr(OffsetOfExpr *E) {
llvm::Value* Result = llvm::Constant::getNullValue(ResultType);
QualType CurrentType = E->getTypeSourceInfo()->getType();
for (unsigned i = 0; i != n; ++i) {
OffsetOfExpr::OffsetOfNode ON = E->getComponent(i);
OffsetOfNode ON = E->getComponent(i);
llvm::Value *Offset = nullptr;
switch (ON.getKind()) {
case OffsetOfExpr::OffsetOfNode::Array: {
case OffsetOfNode::Array: {
// Compute the index
Expr *IdxExpr = E->getIndexExpr(ON.getArrayExprIndex());
llvm::Value* Idx = CGF.EmitScalarExpr(IdxExpr);
@ -1947,7 +1947,7 @@ Value *ScalarExprEmitter::VisitOffsetOfExpr(OffsetOfExpr *E) {
break;
}
case OffsetOfExpr::OffsetOfNode::Field: {
case OffsetOfNode::Field: {
FieldDecl *MemberDecl = ON.getField();
RecordDecl *RD = CurrentType->getAs<RecordType>()->getDecl();
const ASTRecordLayout &RL = CGF.getContext().getASTRecordLayout(RD);
@ -1973,10 +1973,10 @@ Value *ScalarExprEmitter::VisitOffsetOfExpr(OffsetOfExpr *E) {
break;
}
case OffsetOfExpr::OffsetOfNode::Identifier:
case OffsetOfNode::Identifier:
llvm_unreachable("dependent __builtin_offsetof");
case OffsetOfExpr::OffsetOfNode::Base: {
case OffsetOfNode::Base: {
if (ON.getBase()->isVirtual()) {
CGF.ErrorUnsupported(E, "virtual base in offsetof");
continue;

View File

@ -11189,7 +11189,6 @@ ExprResult Sema::BuildBuiltinOffsetOf(SourceLocation BuiltinLoc,
bool DidWarnAboutNonPOD = false;
QualType CurrentType = ArgTy;
typedef OffsetOfExpr::OffsetOfNode OffsetOfNode;
SmallVector<OffsetOfNode, 4> Comps;
SmallVector<Expr*, 4> Exprs;
for (const OffsetOfComponent &OC : Components) {

View File

@ -8063,16 +8063,15 @@ TreeTransform<Derived>::TransformOffsetOfExpr(OffsetOfExpr *E) {
// template code that we don't care.
bool ExprChanged = false;
typedef Sema::OffsetOfComponent Component;
typedef OffsetOfExpr::OffsetOfNode Node;
SmallVector<Component, 4> Components;
for (unsigned I = 0, N = E->getNumComponents(); I != N; ++I) {
const Node &ON = E->getComponent(I);
const OffsetOfNode &ON = E->getComponent(I);
Component Comp;
Comp.isBrackets = true;
Comp.LocStart = ON.getSourceRange().getBegin();
Comp.LocEnd = ON.getSourceRange().getEnd();
switch (ON.getKind()) {
case Node::Array: {
case OffsetOfNode::Array: {
Expr *FromIndex = E->getIndexExpr(ON.getArrayExprIndex());
ExprResult Index = getDerived().TransformExpr(FromIndex);
if (Index.isInvalid())
@ -8084,8 +8083,8 @@ TreeTransform<Derived>::TransformOffsetOfExpr(OffsetOfExpr *E) {
break;
}
case Node::Field:
case Node::Identifier:
case OffsetOfNode::Field:
case OffsetOfNode::Identifier:
Comp.isBrackets = false;
Comp.U.IdentInfo = ON.getFieldName();
if (!Comp.U.IdentInfo)
@ -8093,7 +8092,7 @@ TreeTransform<Derived>::TransformOffsetOfExpr(OffsetOfExpr *E) {
break;
case Node::Base:
case OffsetOfNode::Base:
// Will be recomputed during the rebuild.
continue;
}

View File

@ -550,7 +550,6 @@ void ASTStmtReader::VisitUnaryOperator(UnaryOperator *E) {
}
void ASTStmtReader::VisitOffsetOfExpr(OffsetOfExpr *E) {
typedef OffsetOfExpr::OffsetOfNode Node;
VisitExpr(E);
assert(E->getNumComponents() == Record[Idx]);
++Idx;
@ -560,29 +559,29 @@ void ASTStmtReader::VisitOffsetOfExpr(OffsetOfExpr *E) {
E->setRParenLoc(ReadSourceLocation(Record, Idx));
E->setTypeSourceInfo(GetTypeSourceInfo(Record, Idx));
for (unsigned I = 0, N = E->getNumComponents(); I != N; ++I) {
Node::Kind Kind = static_cast<Node::Kind>(Record[Idx++]);
OffsetOfNode::Kind Kind = static_cast<OffsetOfNode::Kind>(Record[Idx++]);
SourceLocation Start = ReadSourceLocation(Record, Idx);
SourceLocation End = ReadSourceLocation(Record, Idx);
switch (Kind) {
case Node::Array:
E->setComponent(I, Node(Start, Record[Idx++], End));
break;
case Node::Field:
E->setComponent(I, Node(Start, ReadDeclAs<FieldDecl>(Record, Idx), End));
case OffsetOfNode::Array:
E->setComponent(I, OffsetOfNode(Start, Record[Idx++], End));
break;
case Node::Identifier:
E->setComponent(I,
Node(Start,
Reader.GetIdentifierInfo(F, Record, Idx),
End));
case OffsetOfNode::Field:
E->setComponent(
I, OffsetOfNode(Start, ReadDeclAs<FieldDecl>(Record, Idx), End));
break;
case Node::Base: {
case OffsetOfNode::Identifier:
E->setComponent(
I,
OffsetOfNode(Start, Reader.GetIdentifierInfo(F, Record, Idx), End));
break;
case OffsetOfNode::Base: {
CXXBaseSpecifier *Base = new (Reader.getContext()) CXXBaseSpecifier();
*Base = Reader.ReadCXXBaseSpecifier(F, Record, Idx);
E->setComponent(I, Node(Base));
E->setComponent(I, OffsetOfNode(Base));
break;
}
}

View File

@ -484,24 +484,24 @@ void ASTStmtWriter::VisitOffsetOfExpr(OffsetOfExpr *E) {
Writer.AddSourceLocation(E->getRParenLoc(), Record);
Writer.AddTypeSourceInfo(E->getTypeSourceInfo(), Record);
for (unsigned I = 0, N = E->getNumComponents(); I != N; ++I) {
const OffsetOfExpr::OffsetOfNode &ON = E->getComponent(I);
const OffsetOfNode &ON = E->getComponent(I);
Record.push_back(ON.getKind()); // FIXME: Stable encoding
Writer.AddSourceLocation(ON.getSourceRange().getBegin(), Record);
Writer.AddSourceLocation(ON.getSourceRange().getEnd(), Record);
switch (ON.getKind()) {
case OffsetOfExpr::OffsetOfNode::Array:
case OffsetOfNode::Array:
Record.push_back(ON.getArrayExprIndex());
break;
case OffsetOfExpr::OffsetOfNode::Field:
case OffsetOfNode::Field:
Writer.AddDeclRef(ON.getField(), Record);
break;
case OffsetOfExpr::OffsetOfNode::Identifier:
case OffsetOfNode::Identifier:
Writer.AddIdentifierRef(ON.getFieldName(), Record);
break;
case OffsetOfExpr::OffsetOfNode::Base:
case OffsetOfNode::Base:
Writer.AddCXXBaseSpecifier(*ON.getBase(), Record);
break;
}

View File

@ -2434,7 +2434,6 @@ void EnqueueVisitor::VisitObjCMessageExpr(const ObjCMessageExpr *M) {
void EnqueueVisitor::VisitOffsetOfExpr(const OffsetOfExpr *E) {
// Visit the components of the offsetof expression.
for (unsigned N = E->getNumComponents(), I = N; I > 0; --I) {
typedef OffsetOfExpr::OffsetOfNode OffsetOfNode;
const OffsetOfNode &Node = E->getComponent(I-1);
switch (Node.getKind()) {
case OffsetOfNode::Array: