forked from OSchip/llvm-project
Flip the switch to use OffsetOfExpr unconditionally; feel free to revert if
this breaks something. I'll wait a few days before cleaning out UnaryOperator::OffsetOf. llvm-svn: 110328
This commit is contained in:
parent
74ef7cf144
commit
06dcfd94c8
|
@ -6990,135 +6990,11 @@ Sema::OwningExprResult Sema::ActOnBuiltinOffsetOf(Scope *S,
|
|||
if (ArgTy.isNull())
|
||||
return ExprError();
|
||||
|
||||
if (getLangOptions().CPlusPlus) {
|
||||
if (!ArgTInfo)
|
||||
ArgTInfo = Context.getTrivialTypeSourceInfo(ArgTy, TypeLoc);
|
||||
|
||||
return BuildBuiltinOffsetOf(BuiltinLoc, ArgTInfo, CompPtr, NumComponents,
|
||||
RPLoc);
|
||||
}
|
||||
|
||||
// FIXME: The code below is marked for death, once we have proper CodeGen
|
||||
// support for non-constant OffsetOf expressions.
|
||||
|
||||
bool Dependent = ArgTy->isDependentType();
|
||||
|
||||
// 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 (!Dependent && !ArgTy->isRecordType())
|
||||
return ExprError(Diag(TypeLoc, diag::err_offsetof_record_type) << ArgTy);
|
||||
|
||||
// FIXME: Type must be complete per C99 7.17p3 because a declaring a variable
|
||||
// with an incomplete type would be illegal.
|
||||
|
||||
// Otherwise, create a null pointer as the base, and iteratively process
|
||||
// the offsetof designators.
|
||||
QualType ArgTyPtr = Context.getPointerType(ArgTy);
|
||||
Expr* Res = new (Context) ImplicitValueInitExpr(ArgTyPtr);
|
||||
Res = new (Context) UnaryOperator(Res, UnaryOperator::Deref,
|
||||
ArgTy, SourceLocation());
|
||||
|
||||
// offsetof with non-identifier designators (e.g. "offsetof(x, a.b[c])") are a
|
||||
// GCC extension, diagnose them.
|
||||
// FIXME: This diagnostic isn't actually visible because the location is in
|
||||
// a system header!
|
||||
if (NumComponents != 1)
|
||||
Diag(BuiltinLoc, diag::ext_offsetof_extended_field_designator)
|
||||
<< SourceRange(CompPtr[1].LocStart, CompPtr[NumComponents-1].LocEnd);
|
||||
|
||||
if (!Dependent) {
|
||||
bool DidWarnAboutNonPOD = false;
|
||||
|
||||
if (RequireCompleteType(TypeLoc, Res->getType(),
|
||||
diag::err_offsetof_incomplete_type))
|
||||
return ExprError();
|
||||
|
||||
// FIXME: Dependent case loses a lot of information here. And probably
|
||||
// leaks like a sieve.
|
||||
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 = Context.getAsArrayType(Res->getType());
|
||||
if (!AT)
|
||||
return ExprError(Diag(OC.LocEnd, diag::err_offsetof_array_type)
|
||||
<< Res->getType());
|
||||
|
||||
// FIXME: C++: Verify that operator[] isn't overloaded.
|
||||
|
||||
// Promote the array so it looks more like a normal array subscript
|
||||
// expression.
|
||||
DefaultFunctionArrayLvalueConversion(Res);
|
||||
|
||||
// C99 6.5.2.1p1
|
||||
Expr *Idx = static_cast<Expr*>(OC.U.E);
|
||||
// FIXME: Leaks Res
|
||||
if (!Idx->isTypeDependent() && !Idx->getType()->isIntegerType())
|
||||
return ExprError(Diag(Idx->getLocStart(),
|
||||
diag::err_typecheck_subscript_not_integer)
|
||||
<< Idx->getSourceRange());
|
||||
|
||||
Res = new (Context) ArraySubscriptExpr(Res, Idx, AT->getElementType(),
|
||||
OC.LocEnd);
|
||||
continue;
|
||||
}
|
||||
|
||||
const RecordType *RC = Res->getType()->getAs<RecordType>();
|
||||
if (!RC)
|
||||
return ExprError(Diag(OC.LocEnd, diag::err_offsetof_record_type)
|
||||
<< Res->getType());
|
||||
|
||||
// Get the decl corresponding to this.
|
||||
RecordDecl *RD = RC->getDecl();
|
||||
if (CXXRecordDecl *CRD = dyn_cast<CXXRecordDecl>(RD)) {
|
||||
if (!CRD->isPOD() && !DidWarnAboutNonPOD &&
|
||||
DiagRuntimeBehavior(BuiltinLoc,
|
||||
PDiag(diag::warn_offsetof_non_pod_type)
|
||||
<< SourceRange(CompPtr[0].LocStart, OC.LocEnd)
|
||||
<< Res->getType()))
|
||||
DidWarnAboutNonPOD = true;
|
||||
}
|
||||
|
||||
LookupResult R(*this, OC.U.IdentInfo, OC.LocStart, LookupMemberName);
|
||||
LookupQualifiedName(R, RD);
|
||||
|
||||
FieldDecl *MemberDecl = R.getAsSingle<FieldDecl>();
|
||||
// FIXME: Leaks Res
|
||||
if (!MemberDecl)
|
||||
return ExprError(Diag(BuiltinLoc, diag::err_no_member)
|
||||
<< OC.U.IdentInfo << RD << SourceRange(OC.LocStart, OC.LocEnd));
|
||||
|
||||
// C99 7.17p3:
|
||||
// (If the specified member is a bit-field, the behavior is undefined.)
|
||||
//
|
||||
// We diagnose this as an error.
|
||||
if (MemberDecl->getBitWidth()) {
|
||||
Diag(OC.LocEnd, diag::err_offsetof_bitfield)
|
||||
<< MemberDecl->getDeclName()
|
||||
<< SourceRange(BuiltinLoc, RPLoc);
|
||||
Diag(MemberDecl->getLocation(), diag::note_bitfield_decl);
|
||||
return ExprError();
|
||||
}
|
||||
|
||||
// FIXME: C++: Verify that MemberDecl isn't a static field.
|
||||
// FIXME: Verify that MemberDecl isn't a bitfield.
|
||||
if (cast<RecordDecl>(MemberDecl->getDeclContext())->isAnonymousStructOrUnion()) {
|
||||
Res = BuildAnonymousStructUnionMemberReference(
|
||||
OC.LocEnd, MemberDecl, Res, OC.LocEnd).takeAs<Expr>();
|
||||
} else {
|
||||
PerformObjectMemberConversion(Res, /*Qualifier=*/0,
|
||||
*R.begin(), MemberDecl);
|
||||
// MemberDecl->getType() doesn't get the right qualifiers, but it
|
||||
// doesn't matter here.
|
||||
Res = new (Context) MemberExpr(Res, false, MemberDecl, OC.LocEnd,
|
||||
MemberDecl->getType().getNonReferenceType());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Owned(new (Context) UnaryOperator(Res, UnaryOperator::OffsetOf,
|
||||
Context.getSizeType(), BuiltinLoc));
|
||||
if (!ArgTInfo)
|
||||
ArgTInfo = Context.getTrivialTypeSourceInfo(ArgTy, TypeLoc);
|
||||
|
||||
return BuildBuiltinOffsetOf(BuiltinLoc, ArgTInfo, CompPtr, NumComponents,
|
||||
RPLoc);
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue