forked from OSchip/llvm-project
implement initial sema support for __builtin_offsetof
llvm-svn: 41613
This commit is contained in:
parent
e4ee2dfcf5
commit
f17bd423c2
|
@ -69,6 +69,7 @@ const char *UnaryOperator::getOpcodeStr(Opcode Op) {
|
|||
case SizeOf: return "sizeof";
|
||||
case AlignOf: return "alignof";
|
||||
case Extension: return "__extension__";
|
||||
case OffsetOf: return "__builtin_offsetof";
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -307,6 +307,13 @@ public:
|
|||
virtual ExprResult ParseStmtExpr(SourceLocation LPLoc, StmtTy *SubStmt,
|
||||
SourceLocation RPLoc); // "({..})"
|
||||
|
||||
/// __builtin_offsetof(type, a.b[123][456].c)
|
||||
virtual ExprResult ParseBuiltinOffsetOf(SourceLocation BuiltinLoc,
|
||||
SourceLocation TypeLoc, TypeTy *Arg1,
|
||||
OffsetOfComponent *CompPtr,
|
||||
unsigned NumComponents,
|
||||
SourceLocation RParenLoc);
|
||||
|
||||
// __builtin_types_compatible_p(type1, type2)
|
||||
virtual ExprResult ParseTypesCompatibleExpr(SourceLocation BuiltinLoc,
|
||||
TypeTy *arg1, TypeTy *arg2,
|
||||
|
|
|
@ -619,7 +619,8 @@ ParseCallExpr(ExprTy *fn, SourceLocation LParenLoc,
|
|||
if (ImplicitCastExpr *IcExpr = dyn_cast<ImplicitCastExpr>(Fn))
|
||||
if (DeclRefExpr *DRExpr = dyn_cast<DeclRefExpr>(IcExpr->getSubExpr()))
|
||||
if (FunctionDecl *FDecl = dyn_cast<FunctionDecl>(DRExpr->getDecl()))
|
||||
if (CheckFunctionCall(Fn, LParenLoc, RParenLoc, FDecl, Args, NumArgsInCall))
|
||||
if (CheckFunctionCall(Fn, LParenLoc, RParenLoc, FDecl, Args,
|
||||
NumArgsInCall))
|
||||
return true;
|
||||
|
||||
return new CallExpr(Fn, Args, NumArgsInCall, resultType, RParenLoc);
|
||||
|
@ -731,8 +732,9 @@ inline QualType Sema::CheckConditionalOperands( // C99 6.5.15
|
|||
}
|
||||
// The pointer types are compatible.
|
||||
// C99 6.5.15p6: If both operands are pointers to compatible types *or* to
|
||||
// differently qualified versions of compatible types, the result type is a
|
||||
// pointer to an appropriately qualified version of the *composite* type.
|
||||
// differently qualified versions of compatible types, the result type is
|
||||
// a pointer to an appropriately qualified version of the *composite*
|
||||
// type.
|
||||
return lexT; // FIXME: Need to return the composite type.
|
||||
}
|
||||
}
|
||||
|
@ -1315,7 +1317,8 @@ inline QualType Sema::CheckAssignmentOperands( // C99 6.5.16.1
|
|||
// it is the unqualified version of the type of the left operand.
|
||||
// C99 6.5.16.1p2: In simple assignment, the value of the right operand
|
||||
// is converted to the type of the assignment expression (above).
|
||||
// C++ 5.17p1: the type of the assignment expression is that of its left oprdu.
|
||||
// C++ 5.17p1: the type of the assignment expression is that of its left
|
||||
// oprdu.
|
||||
return hadError ? QualType() : lhsType.getUnqualifiedType();
|
||||
}
|
||||
|
||||
|
@ -1715,6 +1718,68 @@ Sema::ExprResult Sema::ParseStmtExpr(SourceLocation LPLoc, StmtTy *substmt,
|
|||
return new StmtExpr(Compound, Ty, LPLoc, RPLoc);
|
||||
}
|
||||
|
||||
Sema::ExprResult Sema::ParseBuiltinOffsetOf(SourceLocation BuiltinLoc,
|
||||
SourceLocation TypeLoc,
|
||||
TypeTy *argty,
|
||||
OffsetOfComponent *CompPtr,
|
||||
unsigned NumComponents,
|
||||
SourceLocation RPLoc) {
|
||||
QualType ArgTy = QualType::getFromOpaquePtr(argty);
|
||||
assert(!ArgTy.isNull() && "Missing type argument!");
|
||||
|
||||
// We must have at least one component that refers to the type, and the first
|
||||
// one is known to be a field designator. Verify that the ArgTy represents
|
||||
// a struct/union/class.
|
||||
if (!ArgTy->isRecordType())
|
||||
return Diag(TypeLoc, diag::err_offsetof_record_type,ArgTy.getAsString());
|
||||
|
||||
// Otherwise, create a compound literal expression as the base, and
|
||||
// iteratively process the offsetof designators.
|
||||
Expr *Res = new CompoundLiteralExpr(ArgTy, 0);
|
||||
|
||||
for (unsigned i = 0; i != NumComponents; ++i) {
|
||||
const OffsetOfComponent &OC = CompPtr[i];
|
||||
if (OC.isBrackets) {
|
||||
// Offset of an array sub-field. TODO: Should we allow vector elements?
|
||||
const ArrayType *AT = Res->getType()->getAsArrayType();
|
||||
if (!AT) {
|
||||
delete Res;
|
||||
return Diag(OC.LocEnd, diag::err_offsetof_array_type,
|
||||
Res->getType().getAsString());
|
||||
}
|
||||
|
||||
// C99 6.5.2.1p1
|
||||
Expr *Idx = static_cast<Expr*>(OC.U.E);
|
||||
if (!Idx->getType()->isIntegerType())
|
||||
return Diag(Idx->getLocStart(), diag::err_typecheck_subscript,
|
||||
Idx->getSourceRange());
|
||||
|
||||
Res = new ArraySubscriptExpr(Res, Idx, AT->getElementType(), OC.LocEnd);
|
||||
continue;
|
||||
}
|
||||
|
||||
const RecordType *RC = Res->getType()->getAsRecordType();
|
||||
if (!RC) {
|
||||
delete Res;
|
||||
return Diag(OC.LocEnd, diag::err_offsetof_record_type,
|
||||
Res->getType().getAsString());
|
||||
}
|
||||
|
||||
// Get the decl corresponding to this.
|
||||
RecordDecl *RD = RC->getDecl();
|
||||
FieldDecl *MemberDecl = RD->getMember(OC.U.IdentInfo);
|
||||
if (!MemberDecl)
|
||||
return Diag(BuiltinLoc, diag::err_typecheck_no_member,
|
||||
OC.U.IdentInfo->getName(),
|
||||
SourceRange(OC.LocStart, OC.LocEnd));
|
||||
Res = new MemberExpr(Res, false, MemberDecl, OC.LocEnd);
|
||||
}
|
||||
|
||||
return new UnaryOperator(Res, UnaryOperator::OffsetOf, Context.getSizeType(),
|
||||
BuiltinLoc);
|
||||
}
|
||||
|
||||
|
||||
Sema::ExprResult Sema::ParseTypesCompatibleExpr(SourceLocation BuiltinLoc,
|
||||
TypeTy *arg1, TypeTy *arg2,
|
||||
SourceLocation RPLoc) {
|
||||
|
@ -1723,7 +1788,7 @@ Sema::ExprResult Sema::ParseTypesCompatibleExpr(SourceLocation BuiltinLoc,
|
|||
|
||||
assert((!argT1.isNull() && !argT2.isNull()) && "Missing type argument(s)");
|
||||
|
||||
return new TypesCompatibleExpr(Context.IntTy, BuiltinLoc, argT1, argT2, RPLoc);
|
||||
return new TypesCompatibleExpr(Context.IntTy, BuiltinLoc, argT1, argT2,RPLoc);
|
||||
}
|
||||
|
||||
Sema::ExprResult Sema::ParseChooseExpr(SourceLocation BuiltinLoc, ExprTy *cond,
|
||||
|
|
|
@ -32,7 +32,6 @@ class Expr : public Stmt {
|
|||
QualType TR;
|
||||
protected:
|
||||
Expr(StmtClass SC, QualType T) : Stmt(SC), TR(T) {}
|
||||
~Expr() {}
|
||||
public:
|
||||
QualType getType() const { return TR; }
|
||||
void setType(QualType t) { TR = t; }
|
||||
|
@ -329,6 +328,10 @@ public:
|
|||
/// applied to a non-complex value, the former returns its operand and the
|
||||
/// later returns zero in the type of the operand.
|
||||
///
|
||||
/// __builtin_offsetof(type, a.b[10]) is represented as a unary operator whose
|
||||
/// subexpression is a compound literal with the various MemberExpr and
|
||||
/// ArraySubscriptExpr's applied to it.
|
||||
///
|
||||
class UnaryOperator : public Expr {
|
||||
public:
|
||||
// Note that additions to this should also update the StmtVisitor class.
|
||||
|
@ -340,7 +343,8 @@ public:
|
|||
Not, LNot, // [C99 6.5.3.3] Unary arithmetic operators.
|
||||
SizeOf, AlignOf, // [C99 6.5.3.4] Sizeof (expr, not type) operator.
|
||||
Real, Imag, // "__real expr"/"__imag expr" Extension.
|
||||
Extension // __extension__ marker.
|
||||
Extension, // __extension__ marker.
|
||||
OffsetOf // __builtin_offsetof
|
||||
};
|
||||
private:
|
||||
Expr *Val;
|
||||
|
@ -431,9 +435,8 @@ class ArraySubscriptExpr : public Expr {
|
|||
SourceLocation RBracketLoc;
|
||||
public:
|
||||
ArraySubscriptExpr(Expr *lhs, Expr *rhs, QualType t,
|
||||
SourceLocation rbracketloc) :
|
||||
Expr(ArraySubscriptExprClass, t),
|
||||
RBracketLoc(rbracketloc) {
|
||||
SourceLocation rbracketloc)
|
||||
: Expr(ArraySubscriptExprClass, t), RBracketLoc(rbracketloc) {
|
||||
SubExprs[LHS] = lhs;
|
||||
SubExprs[RHS] = rhs;
|
||||
}
|
||||
|
@ -636,7 +639,11 @@ public:
|
|||
const Expr *getInitializer() const { return Init; }
|
||||
Expr *getInitializer() { return Init; }
|
||||
|
||||
virtual SourceRange getSourceRange() const { return Init->getSourceRange(); }
|
||||
virtual SourceRange getSourceRange() const {
|
||||
if (Init)
|
||||
return Init->getSourceRange();
|
||||
return SourceRange();
|
||||
}
|
||||
|
||||
static bool classof(const Stmt *T) {
|
||||
return T->getStmtClass() == CompoundLiteralExprClass;
|
||||
|
@ -908,7 +915,7 @@ public:
|
|||
QualType getArgType1() const { return Type1; }
|
||||
QualType getArgType2() const { return Type2; }
|
||||
|
||||
int typesAreCompatible() const { return Type::typesAreCompatible(Type1,Type2); }
|
||||
int typesAreCompatible() const {return Type::typesAreCompatible(Type1,Type2);}
|
||||
|
||||
virtual SourceRange getSourceRange() const {
|
||||
return SourceRange(BuiltinLoc, RParenLoc);
|
||||
|
|
|
@ -95,6 +95,7 @@ public:
|
|||
case UnaryOperator::Real: DISPATCH(UnaryReal, UnaryOperator);
|
||||
case UnaryOperator::Imag: DISPATCH(UnaryImag, UnaryOperator);
|
||||
case UnaryOperator::Extension: DISPATCH(UnaryExtension, UnaryOperator);
|
||||
case UnaryOperator::OffsetOf: DISPATCH(UnaryExtension, UnaryOperator);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -158,7 +159,7 @@ public:
|
|||
UNARYOP_FALLBACK(Not) UNARYOP_FALLBACK(LNot)
|
||||
UNARYOP_FALLBACK(SizeOf) UNARYOP_FALLBACK(AlignOf)
|
||||
UNARYOP_FALLBACK(Real) UNARYOP_FALLBACK(Imag)
|
||||
UNARYOP_FALLBACK(Extension)
|
||||
UNARYOP_FALLBACK(Extension) UNARYOP_FALLBACK(OffsetOf)
|
||||
#undef UNARYOP_FALLBACK
|
||||
|
||||
// Base case, ignore it. :)
|
||||
|
|
|
@ -581,6 +581,11 @@ DIAG(err_sizeof_incomplete_type, ERROR,
|
|||
"invalid application of 'sizeof' to an incomplete type '%0'")
|
||||
DIAG(err_alignof_incomplete_type, ERROR,
|
||||
"invalid application of '__alignof' to an incomplete type '%0'")
|
||||
DIAG(err_offsetof_record_type, ERROR,
|
||||
"offsetof requires struct, union, or class type, '%0' invalid")
|
||||
DIAG(err_offsetof_array_type, ERROR,
|
||||
"offsetof requires array type, '%0' invalid")
|
||||
|
||||
DIAG(err_invalid_suffix_integer_constant, ERROR,
|
||||
"invalid suffix '%0' on integer constant")
|
||||
DIAG(err_invalid_suffix_float_constant, ERROR,
|
||||
|
|
Loading…
Reference in New Issue