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:
Eli Friedman 2010-08-05 10:15:45 +00:00
parent 74ef7cf144
commit 06dcfd94c8
1 changed files with 5 additions and 129 deletions

View File

@ -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);
}